Esempio n. 1
0
        /// <summary>Computes the Discrete Fourier Transform of a double2 vector x whose length is a power of 16.
        /// x = { Re[x0] Im[x0] Re[x1] Im[x1] ... Re[xn] Im[xn] }, n = power of 16 (Length = 2*pow(16,n))</summary>
        public static CLCalc.Program.Variable FFT16(ref CLCalc.Program.Variable CLx)
        {
            if (CLy == null || CLy.OriginalVarLength != CLx.OriginalVarLength)
            {
                CLy = new CLCalc.Program.Variable(new float[CLx.OriginalVarLength]);
            }

            if (CLCalc.CLAcceleration != CLCalc.CLAccelerationType.UsingCL)
            {
                return(null);
            }

            int nn = (int)Math.Log(CLx.OriginalVarLength >> 1, 16);

            nn = 1 << ((nn << 2) + 1);
            if (nn != CLx.OriginalVarLength)
            {
                throw new Exception("Number of elements should be a power of 16 ( vector length should be 2*pow(16,n) )");
            }

            if (kernelfft_radix16 == null)
            {
                InitKernels();
            }

            CLCalc.Program.Variable[] args  = new CLCalc.Program.Variable[] { CLx, CLy, CLp };
            CLCalc.Program.Variable[] args2 = new CLCalc.Program.Variable[] { CLy, CLx, CLp };
            bool usar2 = true;

            int[] p = new int[] { 1 };
            CLp.WriteToDevice(p);
            int n = CLx.OriginalVarLength >> 5;

            while (p[0] <= n)
            {
                usar2 = !usar2;
                if (usar2)
                {
                    kernelfft_radix16.Execute(args2, n);
                }
                else
                {
                    kernelfft_radix16.Execute(args, n);
                }

                p[0] = p[0] << 4;
                CLp.WriteToDevice(p);
            }

            if (usar2)
            {
                CLCalc.Program.Variable temp = CLx;
                CLx = CLy; CLy = temp;
            }

            return(CLy);
        }
Esempio n. 2
0
 private CLCalc.Program.Variable CLCalcVertexDisplacement(float[] ObjVertex, float[] ObjDisplacement)
 {
     CLCalc.Program.Variable variable1 = new CLCalc.Program.Variable(ObjVertex);
     CLCalc.Program.Variable variable2 = new CLCalc.Program.Variable(ObjDisplacement);
     CLCalc.Program.Variable variable3 = new CLCalc.Program.Variable(ObjVertex);
     float[] numArray = new float[9];
     CLCalc.Program.Variable variable4 = new CLCalc.Program.Variable(numArray);
     int[] GlobalWorkSize = new int[1]
     {
         ObjVertex.Length
     };
     if ((double)ObjDisplacement[3] != 0.0 || (double)ObjDisplacement[4] != 0.0 || (double)ObjDisplacement[5] != 0.0)
     {
         this.CalcRotMatrix(numArray, ObjDisplacement);
         variable4.WriteToDevice(numArray);
         this.kernelCalcRotacoes.Execute((CLCalc.Program.MemoryObject[]) new CLCalc.Program.Variable[3]
         {
             variable4,
             variable1,
             variable3
         }, GlobalWorkSize);
     }
     this.kernelCalcTransl.Execute((CLCalc.Program.MemoryObject[]) new CLCalc.Program.Variable[2]
     {
         variable2,
         variable3
     }, GlobalWorkSize);
     return(variable3);
 }
Esempio n. 3
0
        /// <summary>Computes the Discrete Fourier Transform of a double2 vector x whose length is a power of 16.
        /// x = { Re[x0] Im[x0] Re[x1] Im[x1] ... Re[xn] Im[xn] }, n = power of 16 (Length = 2*pow(16,n))</summary>
        public static double[] FFT16(double[] x)
        {
            if (CLx == null || CLx.OriginalVarLength != x.Length)
            {
                CLx = new CLCalc.Program.Variable(x);
                CLy = new CLCalc.Program.Variable(x);
            }

            //Writes original content
            CLx.WriteToDevice(x);

            CLy = FFT16(ref CLx);


            double[] y = new double[x.Length];
            CLy.ReadFromDeviceTo(y);
            return(y);
        }
Esempio n. 4
0
        /// <summary>Computes the inverse Discrete Fourier Transform of a double2 vector x whose length is a power of 16.
        /// x = { Re[x0] Im[x0] Re[x1] Im[x1] ... Re[xn] Im[xn] }, n = power of 16 (Length = 2*pow(16,n))</summary>
        public static CLCalc.Program.Variable iFFT16(CLCalc.Program.Variable CLx)
        {
            if (CLScale == null)
            {
                CLScale = new CLCalc.Program.Variable(new double[1]);
            }

            //Trick: DFT-1 (x) = DFT(x*)*/N;
            //Conjugate
            double[] vx = new double[CLx.OriginalVarLength];
            CLx.ReadFromDeviceTo(vx);

            double[] scale = new double[] { 1 };
            CLScale.WriteToDevice(scale);
            kernelConjugate.Execute(new CLCalc.Program.Variable[] { CLx, CLScale }, CLx.OriginalVarLength >> 1);
            CLx.ReadFromDeviceTo(vx);

            CLy = FFT16(ref CLx);

            scale[0] = 1 / (double)(CLx.OriginalVarLength >> 1);
            CLScale.WriteToDevice(scale);
            kernelConjugate.Execute(new CLCalc.Program.Variable[] { CLy, CLScale }, CLy.OriginalVarLength >> 1);
            return(CLy);
        }
        public int Step(int nSteps)
        {
            //grabs the Stereoscopic parameters
            dimensions[0] = CLX.VarSize;
            dimensions[1] = CLY.VarSize;
            dimensions[2] = CLZ.VarSize;
            CLDimensions.WriteToDevice(dimensions);

            //steps forward;
            for (int k = 0; k < nSteps - 1; k++)
            {
                vetTransl.Execute(new CLCalc.Program.MemoryObject[] { CLimg, CLDimensions, CLX, CLY, CLZ }, new int[] { dimensions[0] - 2, dimensions[1] - 2 });
            }

            vetTransl.Execute(new CLCalc.Program.MemoryObject[] { CLimg, CLDimensions, CLX, CLY, CLZ }, new int[] { dimensions[0] - 2, dimensions[1] - 2 });

            return(nSteps << 1);
        }
Esempio n. 6
0
        /// <summary>Equalizes image histogram using OpenCL</summary>
        private void CLEqualizeHistogram(ref Bitmap bmp)
        {
            if (CLCalc.CLAcceleration == CLCalc.CLAccelerationType.Unknown)
            {
                CLCalc.InitCL();
            }
            if (CLCalc.CLAcceleration != CLCalc.CLAccelerationType.UsingCL)
            {
                return;
            }

            float[] PartialHistograms = new float[NLumIntens * bmp.Width];
            float[] histLuminance     = new float[NLumIntens];

            if (kernelComputeHistograms == null || CLN == null || CLHistogram == null)
            {
                CLHistogram         = new CLCalc.Program.Variable(histLuminance);
                CLPartialHistograms = new CLCalc.Program.Variable(PartialHistograms);
            }
            InitKernels();


            System.Diagnostics.Stopwatch swTotal               = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch swCopyBmp             = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch swRescaling           = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch swComputeHistPartial  = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch swComputeHistConsolid = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch swHistIntegral        = new System.Diagnostics.Stopwatch();

            swTotal.Start();

            swCopyBmp.Start();
            if (CLbmp == null || CLbmp.Height != bmp.Height || CLbmp.Width != bmp.Width)
            {
                CLbmp               = new CLCalc.Program.Image2D(bmp);
                CLNewBmp            = new CLCalc.Program.Image2D(bmp);
                CLPartialHistograms = new CLCalc.Program.Variable(PartialHistograms);
            }
            else
            {
                CLbmp.WriteBitmap(bmp);
                CLN.WriteToDevice(new int[] { NLumIntens });
                CLWidth.WriteToDevice(new int[] { bmp.Width });
                CLHeight.WriteToDevice(new int[] { bmp.Height });
            }
            swCopyBmp.Stop();

            swComputeHistPartial.Start();

            //Partial histograms
            CLCalc.Program.MemoryObject[] args = new CLCalc.Program.MemoryObject[] { CLbmp, CLPartialHistograms, CLHeight, CLN };

            kernelComputeHistograms.Execute(args, bmp.Width);
            CLCalc.Program.Sync();
            swComputeHistPartial.Stop();



            swComputeHistConsolid.Start();

            args = new CLCalc.Program.MemoryObject[] { CLPartialHistograms, CLHistogram, CLHeight, CLN };
            kernelConsolidateHist.Execute(args, NLumIntens);

            CLHistogram.ReadFromDeviceTo(histLuminance);

            swComputeHistConsolid.Stop();


            swHistIntegral.Start();
            //Perform histogram integration - better performance in CPU
            //Compute histogram integrals in-place
            for (int i = 1; i < NLumIntens; i++)
            {
                histLuminance[i] += histLuminance[i - 1];
            }

            float scale = 0.9f / histLuminance[NLumIntens - 1];

            //Scales histograms
            for (int i = 0; i < NLumIntens; i++)
            {
                histLuminance[i] *= scale;
            }

            //Writes histogram integral
            CLHistogram.WriteToDevice(histLuminance);
            swHistIntegral.Stop();

            swRescaling.Start();
            //Computes equalized image
            args = new CLCalc.Program.MemoryObject[] { CLbmp, CLNewBmp, CLHistogram, CLN };
            kernelPerformNormalization.Execute(args, new int [] { bmp.Width, bmp.Height });

            bmp = CLNewBmp.ReadBitmap();
            swRescaling.Stop();


            swTotal.Stop();
        }
Esempio n. 7
0
        /// <summary>Creates a new isosurface calculator. You may pass variables created from a OpenGL context to the CL variables if you are using interop or NULL
        /// if not using OpenCL/GL interop.</summary>
        /// <param name="FuncValues">Values of the evaluated 3D function f(x,y,z). FuncValues=float[maxX,maxY,maxZ]</param>
        /// <param name="CLEdgeCoords">OpenCL variable (float) to hold edge coordinates. Dimension has to be 9 * maxX * maxY * maxZ</param>
        /// <param name="CLEdgeNormals">OpenCL variable (float) to hold edge normals. Dimension has to be 9 * maxX * maxY * maxZ</param>
        /// <param name="CLElementArrayIndex">OpenCL variable (int) to hold element array index. Dimension has to be 5 * 3 * (maxX - 1) * (maxY - 1) * (maxZ - 1)</param>
        private void InitMarchingCubes(float[, ,] FuncValues, CLCalc.Program.Variable CLEdgeCoords, CLCalc.Program.Variable CLEdgeNormals, CLCalc.Program.Variable CLElementArrayIndex)
        {
            if (CLCalc.CLAcceleration == CLCalc.CLAccelerationType.Unknown) CLCalc.InitCL();

            if (CLCalc.CLAcceleration == CLCalc.CLAccelerationType.UsingCL)
            {
                //Reads maximum lengths
                int maxX = FuncValues.GetLength(0);
                int maxY = FuncValues.GetLength(1);
                int maxZ = FuncValues.GetLength(2);
                max = new int[] { maxX, maxY, maxZ };

                #region Creating variables

                //Isolevel
                isoLevel = new float[1] { 1.32746E-5f };
                varIsoLevel = new CLCalc.Program.Variable(isoLevel);

                //Step size and x0,y0,z0
                varStep = new CLCalc.Program.Variable(step);
                varInitVals = new CLCalc.Program.Variable(initVals);

                //Create and copy function values
                funcVals = new float[maxX * maxY * maxZ];
                CLFuncVals = new CLCalc.Program.Variable(funcVals);
                SetFuncVals(FuncValues);

                //Edge coordinates - 3 coords * 3 possible directions * number of points
                edgeCoords = new float[9 * maxX * maxY * maxZ];
                if (CLEdgeCoords != null)
                {
                    varEdgeCoords = CLEdgeCoords;
                    varEdgeCoords.WriteToDevice(edgeCoords);
                }
                else varEdgeCoords = new CLCalc.Program.Variable(edgeCoords);

                //4 preliminary normals per edge - has to be averaged afterwards
                edgePrelimNormals = new float[36 * maxX * maxY * maxZ];
                varEdgePrelimNormals = new CLCalc.Program.Variable(edgePrelimNormals);

                //Edge normals
                edgeNormals = new float[9 * maxX * maxY * maxZ];
                if (CLEdgeNormals != null)
                {
                    varEdgeNormals = CLEdgeNormals;
                    varEdgeNormals.WriteToDevice(edgeNormals);
                }
                else varEdgeNormals = new CLCalc.Program.Variable(edgeNormals);

                //Number of cubes: (maxX-1)*(maxY-1)*(maxZ-1)
                //Marching cube algorithm: each cube can have 5 triangles drawn, 3 vertexes per triangle
                //q-th vertex of p-th triangle of the ijk-th cube: [(5*(i+(maxX-1)*j+k*(maxX-1)*(maxY-1))+p)*3+q]
                elementIndex = new int[5 * 3 * (maxX - 1) * (maxY - 1) * (maxZ - 1)];
                if (CLElementArrayIndex != null)
                {
                    varElemIndex = CLElementArrayIndex;
                    varElemIndex.WriteToDevice(elementIndex);
                }
                else varElemIndex = new CLCalc.Program.Variable(elementIndex);

                //Edge remapping to build output
                edges = new int[edgeCoords.Length / 3];
                for (int i = 0; i < edges.Length; i++) edges[i] = -1;

                #endregion

                #region Compile code and create kernels

                CLMarchingCubesSrc cmsrc = new CLMarchingCubesSrc();

                CLCalc.Program.Compile(new string[] { cmsrc.definitions, cmsrc.src });
                kernelInterpPts = new CLCalc.Program.Kernel("interpPts");
                kernelPolygonize = new CLCalc.Program.Kernel("Polygonize");
                kernelSmoothNormals = new CLCalc.Program.Kernel("SmoothNormals");
                kernelPolygonizeNoNormals = new CLCalc.Program.Kernel("PolygonizeNoNormals");
                #endregion
            }
            else throw new Exception("OpenCL not available");
        }
Esempio n. 8
0
        /// <summary>Creates a new isosurface calculator. You may pass variables created from a OpenGL context to the CL variables if you are using interop or NULL
        /// if not using OpenCL/GL interop.</summary>
        /// <param name="FuncValues">Values of the evaluated 3D function f(x,y,z). FuncValues=float[maxX,maxY,maxZ]</param>
        /// <param name="CLEdgeCoords">OpenCL variable (float) to hold edge coordinates. Dimension has to be 9 * maxX * maxY * maxZ</param>
        /// <param name="CLEdgeNormals">OpenCL variable (float) to hold edge normals. Dimension has to be 9 * maxX * maxY * maxZ</param>
        /// <param name="CLElementArrayIndex">OpenCL variable (int) to hold element array index. Dimension has to be 5 * 3 * (maxX - 1) * (maxY - 1) * (maxZ - 1)</param>
        private void InitMarchingCubes(float[, ,] FuncValues, CLCalc.Program.Variable CLEdgeCoords, CLCalc.Program.Variable CLEdgeNormals, CLCalc.Program.Variable CLElementArrayIndex)
        {
            if (CLCalc.CLAcceleration == CLCalc.CLAccelerationType.Unknown)
            {
                CLCalc.InitCL();
            }

            if (CLCalc.CLAcceleration == CLCalc.CLAccelerationType.UsingCL)
            {
                //Reads maximum lengths
                int maxX = FuncValues.GetLength(0);
                int maxY = FuncValues.GetLength(1);
                int maxZ = FuncValues.GetLength(2);
                max = new int[] { maxX, maxY, maxZ };

                #region Creating variables

                //Isolevel
                isoLevel = new float[1] {
                    1.32746E-5f
                };
                varIsoLevel = new CLCalc.Program.Variable(isoLevel);

                //Step size and x0,y0,z0
                varStep     = new CLCalc.Program.Variable(step);
                varInitVals = new CLCalc.Program.Variable(initVals);

                //Create and copy function values
                funcVals   = new float[maxX * maxY * maxZ];
                CLFuncVals = new CLCalc.Program.Variable(funcVals);
                SetFuncVals(FuncValues);

                //Edge coordinates - 3 coords * 3 possible directions * number of points
                edgeCoords = new float[9 * maxX * maxY * maxZ];
                if (CLEdgeCoords != null)
                {
                    varEdgeCoords = CLEdgeCoords;
                    varEdgeCoords.WriteToDevice(edgeCoords);
                }
                else
                {
                    varEdgeCoords = new CLCalc.Program.Variable(edgeCoords);
                }

                //4 preliminary normals per edge - has to be averaged afterwards
                edgePrelimNormals    = new float[36 * maxX * maxY * maxZ];
                varEdgePrelimNormals = new CLCalc.Program.Variable(edgePrelimNormals);

                //Edge normals
                edgeNormals = new float[9 * maxX * maxY * maxZ];
                if (CLEdgeNormals != null)
                {
                    varEdgeNormals = CLEdgeNormals;
                    varEdgeNormals.WriteToDevice(edgeNormals);
                }
                else
                {
                    varEdgeNormals = new CLCalc.Program.Variable(edgeNormals);
                }

                //Number of cubes: (maxX-1)*(maxY-1)*(maxZ-1)
                //Marching cube algorithm: each cube can have 5 triangles drawn, 3 vertexes per triangle
                //q-th vertex of p-th triangle of the ijk-th cube: [(5*(i+(maxX-1)*j+k*(maxX-1)*(maxY-1))+p)*3+q]
                elementIndex = new int[5 * 3 * (maxX - 1) * (maxY - 1) * (maxZ - 1)];
                if (CLElementArrayIndex != null)
                {
                    varElemIndex = CLElementArrayIndex;
                    varElemIndex.WriteToDevice(elementIndex);
                }
                else
                {
                    varElemIndex = new CLCalc.Program.Variable(elementIndex);
                }

                //Edge remapping to build output
                edges = new int[edgeCoords.Length / 3];
                for (int i = 0; i < edges.Length; i++)
                {
                    edges[i] = -1;
                }

                #endregion

                #region Compile code and create kernels

                CLMarchingCubesSrc cmsrc = new CLMarchingCubesSrc();

                CLCalc.Program.Compile(new string[] { cmsrc.definitions, cmsrc.src });
                kernelInterpPts           = new CLCalc.Program.Kernel("interpPts");
                kernelPolygonize          = new CLCalc.Program.Kernel("Polygonize");
                kernelSmoothNormals       = new CLCalc.Program.Kernel("SmoothNormals");
                kernelPolygonizeNoNormals = new CLCalc.Program.Kernel("PolygonizeNoNormals");
                #endregion
            }
            else
            {
                throw new Exception("OpenCL not available");
            }
        }
Esempio n. 9
0
 /// <summary>Reads data from a bitmap.</summary>
 /// <param name="bmp">Source bitmap</param>
 public void ReadBmp(Bitmap bmp)
 {
     ReadToLocalData(bmp);
     varData.WriteToDevice(Data);
 }
Esempio n. 10
0
        /// <summary>Writes Training Set into device memory</summary>
        private void WriteToDevice()
        {
            //Vector length
            if (HostVLen == null)
            {
                HostVLen    = new int[1];
                HostVLen[0] = (1 + ((TrainingSet.trainingArray[0].xVector.Length - 1) >> 2)) << 2;
            }

            //Populates OpenCL buffer
            if (TrainingFeatures == null) // || TrainingFeatures.Length != TrainingSet.getN * HostVLen[0])
            {
                TrainingFeatures = new float[TrainingSet.getN * HostVLen[0]];
            }

            for (int i = 0; i < TrainingSet.getN; i++)
            {
                for (int j = 0; j < TrainingSet.trainingArray[0].xVector.Length; j++)
                {
                    TrainingFeatures[j + i * HostVLen[0]] = TrainingSet.trainingArray[i].xVector[j];
                }
            }

            if (CLCalc.CLAcceleration != CLCalc.CLAccelerationType.UsingCL)
            {
                return;
            }
            lock (CLResource)
            {
                //Writes to OpenCL memory
                //if (CLTrainingFeatures != null) CLTrainingFeatures.Dispose();
                if (CLTrainingFeatures == null || CLTrainingFeatures.OriginalVarLength != TrainingFeatures.Length)
                {
                    if (CLTrainingFeatures != null)
                    {
                        CLTrainingFeatures.Dispose();
                    }
                    CLTrainingFeatures = new CLCalc.Program.Variable(TrainingFeatures);
                }
                else
                {
                    CLTrainingFeatures.WriteToDevice(TrainingFeatures);
                }

                //if (CLXVecLen != null) CLXVecLen.Dispose();
                if (CLXVecLen == null)
                {
                    CLXVecLen = new CLCalc.Program.Variable(HostVLen);
                }
                else
                {
                    CLXVecLen.WriteToDevice(HostVLen);
                }

                HostSample = new float[HostVLen[0]];
                //if (CLSample != null) CLSample.Dispose();
                if (CLSample == null)
                {
                    CLSample = new CLCalc.Program.Image2D(HostSample, HostVLen[0] >> 2, 1);
                }
                else
                {
                    CLSample.WriteToDevice(HostSample);
                }

                //if (CLKernelValues != null) CLKernelValues.Dispose();
                if (CLKernelValues == null || CLKernelValues.OriginalVarLength != TrainingSet.getN)
                {
                    CLKernelValues = new CLCalc.Program.Variable(new float[TrainingSet.getN]);
                }
                else
                {
                    CLKernelValues.WriteToDevice(new float[TrainingSet.getN]);
                }

                //if (CLLambda != null) CLLambda.Dispose();
                if (CLLambda == null)
                {
                    CLLambda = new CLCalc.Program.Variable(new float[] { this.ProblemCfg.lambda });
                }
                else
                {
                    CLLambda.WriteToDevice(new float[] { this.ProblemCfg.lambda });
                }
            }
        }
Esempio n. 11
0
        /// <summary>Shades a bitmap</summary>
        /// <param name="bmp">Bitmap to shade</param>
        /// <param name="bmp">Actually render?</param>
        /// <returns></returns>
        public void Shade(Bitmap bmp, PictureBox pb, bool doRender)
        {
            Bitmap   bmp2 = new Bitmap(bmp.Width, bmp.Height);
            Graphics g    = Graphics.FromImage(bmp2);

            g.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height);

            //draws points onto thresholded bitmap
            for (int i = 0; i < Colors.Count; i++)
            {
                if (Points[i].Count > 1)
                {
                    g.DrawLines(new Pen(Color.Black, 2), Points[i].ToArray());
                }
            }


            #region Initializations
            if (CLbmpSrc == null || CLbmpSrc.Width != bmp.Width || CLbmpSrc.Height != bmp.Height)
            {
                CLbmpSrc     = new CLCalc.Program.Image2D(bmp2);
                CLbmpThresh  = new CLCalc.Program.Image2D(bmp);
                CLthreshInfo = new CLCalc.Program.Variable(typeof(byte), bmp.Width * bmp.Height);
                CLbmpStroke  = new CLCalc.Program.Image2D(bmp);
                CLbmpDists   = new CLCalc.Program.Image2D(bmp);

                CLimgFinal1 = new CLCalc.Program.Image2D(new Bitmap(bmp2.Width, bmp2.Height));
                CLimgFinal2 = new CLCalc.Program.Image2D(new Bitmap(bmp2.Width, bmp2.Height));

                CLTotalPixWeight = new CLCalc.Program.Variable(typeof(float), bmp.Width * bmp.Height);
                lastPixWeight    = new float[bmp.Width * bmp.Height];
                CLWeight         = new CLCalc.Program.Variable(typeof(float), bmp.Width * bmp.Height);
                lastImage        = new Bitmap(bmp.Width, bmp.Height);
            }
            else
            {
                CLbmpSrc.WriteBitmap(bmp2);
                CLimgFinal1.WriteBitmap(new Bitmap(bmp2.Width, bmp2.Height));
                CLimgFinal2.WriteBitmap(new Bitmap(bmp2.Width, bmp2.Height));
                kernelinitTotalWeight.Execute(new CLCalc.Program.MemoryObject[] { CLTotalPixWeight }, new int[] { CLbmpSrc.Width, CLbmpSrc.Height });
            }
            #endregion

            System.Diagnostics.Stopwatch sw   = new System.Diagnostics.Stopwatch();
            System.Diagnostics.Stopwatch swCL = new System.Diagnostics.Stopwatch();
            sw.Start();

            //computes threshold
            kernelThreshold.Execute(new CLCalc.Program.MemoryObject[] { CLcfgVars, CLbmpSrc, CLthreshInfo, CLbmpThresh }, new int[] { bmp.Width, bmp.Height });

            if (!doRender)
            {
                return;
            }

            //Reuse last render?
            if (ReUseLastRender)
            {
                CLTotalPixWeight.WriteToDevice(lastPixWeight);
                CLimgFinal1.WriteBitmap(lastImage);
            }
            else
            {
                lastRenderedIdx = 0;
            }

            //generates images for points
            for (int i = lastRenderedIdx; i < Colors.Count; i++)
            {
                Bitmap bmpStroke = new Bitmap(bmp.Width, bmp.Height);

                if (Points[i].Count > 1)
                {
                    if (DistanceMaps[i] == null)
                    {
                        Graphics g2 = Graphics.FromImage(bmpStroke);
                        g2.DrawLines(new Pen(Colors[i], 2), Points[i].ToArray());

                        CLbmpStroke.WriteBitmap(bmpStroke);

                        int[] changed = new int[] { 0 };
                        swCL.Start();
                        changed[0] = 1;
                        kernelinitWeight.Execute(new CLCalc.Program.MemoryObject[] { CLWeight }, new int[] { CLbmpSrc.Width, CLbmpSrc.Height });

                        int n = 0;
                        while (changed[0] > 0 && n < MAXPROPAGITERS)
                        {
                            n++;
                            changed[0] = 0;
                            CLchanged.WriteToDevice(changed);
                            kernelPropagateDist.Execute(new CLCalc.Program.MemoryObject[] { CLchanged, CLbmpStroke, CLthreshInfo, CLWeight, CLbmpDists },
                                                        new int[] { CLbmpSrc.Width, CLbmpSrc.Height });

                            CLchanged.ReadFromDeviceTo(changed);
                        }
                        swCL.Stop();

                        DistanceMaps[i] = new float[CLWeight.OriginalVarLength];
                        CLWeight.ReadFromDeviceTo(DistanceMaps[i]);
                    }
                    else
                    {
                        CLWeight.WriteToDevice(DistanceMaps[i]);
                    }



                    //composes total weight
                    CLcolor.WriteToDevice(new float[] { (float)Colors[i].B, (float)Colors[i].G, (float)Colors[i].R });

                    kernelAddToTotalWeight.Execute(new CLCalc.Program.MemoryObject[] { CLTotalPixWeight, CLWeight, CLcolor, CLimgFinal1, CLimgFinal2, CLthreshInfo }, new int[] { CLbmpSrc.Width, CLbmpSrc.Height });
                    //swaps final images - result is always on CLimgFinal1
                    CLCalc.Program.Image2D temp = CLimgFinal1;
                    CLimgFinal1 = CLimgFinal2;
                    CLimgFinal2 = temp;

                    if (pb != null)
                    {
                        pb.Image = GetRenderedImage();
                        pb.Refresh();
                    }
                }
                bmpStroke.Dispose();
            }
            sw.Stop();

            lastRenderedIdx = Colors.Count;
            //saves total pixel weight and final image
            CLTotalPixWeight.ReadFromDeviceTo(lastPixWeight);
            if (lastImage != null)
            {
                lastImage.Dispose();
            }
            lastImage = CLimgFinal1.ReadBitmap();
        }