Ejemplo n.º 1
0
        //private IEnumerable<Vector2d> GenerateLensSamples(int tileSize, int sqrtSampleCount)
        //{
        //    int pixelCount = tileSize * tileSize;
        //    IEnumerator<Vector2d>[] jitteredSamplers = new IEnumerator<Vector2d>[pixelCount];
        //    Sampler sampler = new Sampler();
        //    for (int i = 0; i < pixelCount; i++)
        //    {
        //        jitteredSamplers[i] = sampler.GenerateJitteredSamples(MaxTotalSampleCount).GetEnumerator();
        //    }
        //    for (int sample = 0; sample < MaxTotalSampleCount; sample++)
        //    {
        //        for (int i = 0; i < pixelCount; i++)
        //        {
        //            jitteredSamplers[i].MoveNext();
        //            yield return jitteredSamplers[i].Current;
        //        }
        //    }
        //}

        private void GeneratePixelSamplesTexture(int textureId, int sqrtSampleCount, int sampleCount)
        {
            GL.BindTexture(TextureTarget.Texture1D, textureId);
            // size of a group of samples for a single pixel
            int bands       = 2;
            int textureSize = bands * sampleCount;

            Sampler sampler    = new Sampler();
            IntPtr  texturePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Half)) * textureSize);

            unsafe
            {
                Half *row   = (Half *)texturePtr;
                int   index = 0;
                foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount))
                {
                    row[index] = (Half)(sample.X - 0.5f);
                    index++;
                    row[index] = (Half)(sample.Y - 0.5f);
                    index++;
                }
            }

            // TODO: could be an half float or unsigned byte instead of a float
            // TODO: two sample pair could be stored in one 4-channel value
            GL.TexImage1D(TextureTarget.Texture1D, 0, PixelInternalFormat.Rg16f,
                          sampleCount, 0,
                          PixelFormat.Rg, PixelType.HalfFloat, texturePtr);

            Marshal.FreeHGlobal(texturePtr);

            GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
            GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
            GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
        }
Ejemplo n.º 2
0
        public FloatMapImage RenderImage(Size imageSize)
        {
            int height = imageSize.Height;
            int width = imageSize.Width;
            FloatMapImage outputImage = new FloatMapImage((uint)width, (uint)height, PixelFormat.Greyscale);
            Sensor.RasterSize = imageSize;

            Sampler sampler = new Sampler();
            int SqrtSampleCount = (int)Math.Sqrt(SampleCount);
            foreach (Vector2d sample in sampler.GenerateJitteredSamples(SqrtSampleCount))
            {
                // generate a sample at the lens surface
                Vector3d lensPos = Lens.GetBackSurfaceSample(sample);
                lensPos.Z = 0;
                // make an incoming ray from the light source to the lens sample and
                // transfer the incoming ray through the lens creating the outgoing ray
                Ray outgoingRay = Lens.Transfer(LightSourcePosition, lensPos);
                if (outgoingRay == null)
                {
                    continue;
                }
                // intersect the senzor with the outgoing ray
                Intersection intersection = Sensor.Intersect(outgoingRay);
                if (intersection == null)
                {
                    continue;
                }
                Vector3d intersectionPoint = intersection.Position;
                Vector2d intersectionPixelPoint = Sensor.CameraToImage(intersectionPoint);
                // put a splat on the senzor at the intersection
                Splat(outputImage, LightIntensity, intersectionPixelPoint);
            }

            return outputImage;
        }
Ejemplo n.º 3
0
        public void IntersectSphere()
        {
            Sphere sphere = new Sphere()
            {
                Radius = 2
            };
            double biggerSphereFactor = 3;

            Sampler sampler         = new Sampler();
            int     sampleCount     = 64;
            int     sqrtSampleCount = (int)Math.Sqrt(sampleCount);

            foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount))
            {
                // shoot rays at the sphere center from a bigger concontric sphere
                Vector3d     unitSphereSample = Sampler.UniformSampleSphereWithEqualArea(sample, -1, 1);
                Vector3d     sourcePos        = biggerSphereFactor * sphere.Radius * unitSphereSample;
                Ray          ray          = new Ray(sourcePos, sphere.Center - sourcePos);
                Intersection intersection = sphere.Intersect(ray);
                Assert.NotNull(intersection);
                Vector3d intPos = intersection.Position;
                Console.WriteLine("Black, {0},", ray.ToLine());
                Console.WriteLine(String.Format("Red, {0},", intPos.ToPoint()));
            }
        }
Ejemplo n.º 4
0
            public static IList <Star> GenerateStars(int count, float intensity, bool colorize, int seed)
            {
                Sampler     sampler       = new Sampler(seed);
                Random      random        = new Random(seed);
                var         starPositions = sampler.GenerateJitteredSamples((int)Math.Sqrt(count)).ToList();
                List <Star> stars         = new List <Star>(starPositions.Count());

                foreach (var starPosition in starPositions)
                {
                    Vector3 color = new Vector3(intensity, intensity, intensity);
                    if (colorize)
                    {
                        color = Vector3.Multiply(color, new Vector3(
                                                     (float)random.NextDouble(),
                                                     (float)random.NextDouble(),
                                                     (float)random.NextDouble()));
                    }
                    else
                    {
                        color = Vector3.Multiply(color, (float)random.NextDouble());
                    }
                    Vector2 position = new Vector2((float)starPosition.X, (float)starPosition.Y);
                    stars.Add(new Star()
                    {
                        Position = position, Color = color
                    });
                }
                return(stars);
            }
Ejemplo n.º 5
0
        public void TraceRays()
        {
            ComplexLens lens = ComplexLens.CreateBiconvexLens(4, 2, 0);

            Sampler sampler = new Sampler();
            int sampleCount = 64;
            int sqrtSampleCount = (int)Math.Sqrt(sampleCount);
            Vector3d objectPos = new Vector3d(10, 0, 100);
            foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount))
            {
                Vector3d lensPos = lens.GetBackSurfaceSample(sample);
                Ray result = lens.Transfer(objectPos, lensPos);
            }
        }
Ejemplo n.º 6
0
        public void TraceRays()
        {
            ComplexLens lens = ComplexLens.CreateBiconvexLens(4, 2, 0);

            Sampler  sampler         = new Sampler();
            int      sampleCount     = 64;
            int      sqrtSampleCount = (int)Math.Sqrt(sampleCount);
            Vector3d objectPos       = new Vector3d(10, 0, 100);

            foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount))
            {
                Vector3d lensPos = lens.GetBackSurfaceSample(sample);
                Ray      result  = lens.Transfer(objectPos, lensPos);
            }
        }
Ejemplo n.º 7
0
        private void GenerateLensSamplesTexture(int textureId, int tileSize, int sqrtSampleCount, int totalSampleCount, float lensApertureRadius)
        {
            GL.BindTexture(TextureTarget.Texture3D, textureId);
            // size of a group of samples for a single pixel
            int bands       = 2;
            int groupSize   = bands * totalSampleCount;
            int textureSize = groupSize * tileSize * tileSize;

            Sampler sampler    = new Sampler();
            IntPtr  texturePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(float)) * textureSize);

            unsafe
            {
                int zStride = bands * tileSize * tileSize;
                for (int y = 0; y < tileSize; y++)
                {
                    for (int x = 0; x < tileSize; x++)
                    {
                        float *row   = (float *)texturePtr + bands * (y * tileSize + x);
                        int    index = 0;
                        // Z dimension, totalSampleCount times
                        foreach (Vector2d sample in
                                 sampler.GenerateJitteredSamples(sqrtSampleCount))
                        {
                            Vector2d lensPos = lensApertureRadius *
                                               //2 * (sample - new Vector2d(0.5, 0.5));
                                               Sampler.ConcentricSampleDisk(sample);
                            row[index]     = (float)lensPos.X;
                            row[index + 1] = (float)lensPos.Y;
                            index         += zStride;
                        }
                    }
                }
            }

            // TODO: could be an unsigned byte instead of a float
            // TODO: two sample pair could be stored in one 4-channel value
            GL.TexImage3D(TextureTarget.Texture3D, 0, PixelInternalFormat.Rg32f,
                          tileSize, tileSize, totalSampleCount, 0,
                          PixelFormat.Rg, PixelType.Float, texturePtr);

            GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
            GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
            GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
            GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
            GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapR, (int)TextureWrapMode.Clamp);
        }
Ejemplo n.º 8
0
        public void TraceParallelRays()
        {
            BiconvexLens lens = new BiconvexLens();
            lens.ApertureRadius = 2;
            lens.CurvatureRadius = 4;

            Sampler sampler = new Sampler();
            int sampleCount = 64;
            int sqrtSampleCount = (int)Math.Sqrt(sampleCount);
            Vector3d objectPos = new Vector3d(10, 0, 100);
            foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount))
            {
                Vector3d lensPos = lens.GetBackSurfaceSample(sample);
                //Vector3d objectPos = lensPos + 10 * Vector3d.UnitZ + 2 * Vector3d.UnitX;
                Ray result = lens.Transfer(objectPos, lensPos);
            }
        }
Ejemplo n.º 9
0
        public void TraceParallelRays()
        {
            BiconvexLens lens = new BiconvexLens();

            lens.ApertureRadius  = 2;
            lens.CurvatureRadius = 4;

            Sampler  sampler         = new Sampler();
            int      sampleCount     = 64;
            int      sqrtSampleCount = (int)Math.Sqrt(sampleCount);
            Vector3d objectPos       = new Vector3d(10, 0, 100);

            foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount))
            {
                Vector3d lensPos = lens.GetBackSurfaceSample(sample);
                //Vector3d objectPos = lensPos + 10 * Vector3d.UnitZ + 2 * Vector3d.UnitX;
                Ray result = lens.Transfer(objectPos, lensPos);
            }
        }
Ejemplo n.º 10
0
        public FloatMapImage RenderImage(Size imageSize)
        {
            int           height      = imageSize.Height;
            int           width       = imageSize.Width;
            FloatMapImage outputImage = new FloatMapImage((uint)width, (uint)height, PixelFormat.Greyscale);

            Sensor.RasterSize = imageSize;

            Sampler sampler         = new Sampler();
            int     SqrtSampleCount = (int)Math.Sqrt(SampleCount);

            foreach (Vector2d sample in sampler.GenerateJitteredSamples(SqrtSampleCount))
            {
                // generate a sample at the lens surface
                Vector3d lensPos = Lens.GetBackSurfaceSample(sample);
                lensPos.Z = 0;
                // make an incoming ray from the light source to the lens sample and
                // transfer the incoming ray through the lens creating the outgoing ray
                Ray outgoingRay = Lens.Transfer(LightSourcePosition, lensPos);
                if (outgoingRay == null)
                {
                    continue;
                }
                // intersect the senzor with the outgoing ray
                Intersection intersection = Sensor.Intersect(outgoingRay);
                if (intersection == null)
                {
                    continue;
                }
                Vector3d intersectionPoint      = intersection.Position;
                Vector2d intersectionPixelPoint = Sensor.CameraToImage(intersectionPoint);
                // put a splat on the senzor at the intersection
                Splat(outputImage, LightIntensity, intersectionPixelPoint);
            }

            return(outputImage);
        }
Ejemplo n.º 11
0
        public void IntersectSphere()
        {
            Sphere sphere = new Sphere()
            {
                Radius = 2
            };
            double biggerSphereFactor = 3;

            Sampler sampler = new Sampler();
            int sampleCount = 64;
            int sqrtSampleCount = (int)Math.Sqrt(sampleCount);
            foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount))
            {
                // shoot rays at the sphere center from a bigger concontric sphere
                Vector3d unitSphereSample = Sampler.UniformSampleSphereWithEqualArea(sample, -1, 1);
                Vector3d sourcePos = biggerSphereFactor * sphere.Radius * unitSphereSample;
                Ray ray = new Ray(sourcePos, sphere.Center - sourcePos);
                Intersection intersection = sphere.Intersect(ray);
                Assert.NotNull(intersection);
                Vector3d intPos = intersection.Position;
                Console.WriteLine("Black, {0},", ray.ToLine());
                Console.WriteLine(String.Format("Red, {0},", intPos.ToPoint()));
            }
        }
Ejemplo n.º 12
0
        public FloatMapImage RenderImagePreview(Size imageSize, Rectangle preview, FloatMapImage outputImage)
        {
            int height = imageSize.Height;
            int width  = imageSize.Width;

            if ((outputImage == null) ||
                (outputImage.Width != width) ||
                (outputImage.Height != height))
            {
                outputImage = new FloatMapImage((uint)width, (uint)height);
            }

            Camera.Sensor.RasterSize = imageSize;

            Sampler sampler             = new Sampler();
            int     sqrtSampleCount     = (int)Math.Sqrt(SampleCount);
            int     totalSampleCount    = sqrtSampleCount * sqrtSampleCount;
            float   totalSampleCountInv = 1 / (float)totalSampleCount;

            // NOTE: It is not useful to directly use the same lens samples
            // for each pixel in the whole image. This leads to ugly artifacts
            // and surprisigly there is only an insignificant performance
            // benefit.

            int minX = preview.Left;
            int maxX = preview.Right;
            int minY = preview.Top;
            int maxY = preview.Bottom;

            float[] color = new float[outputImage.ColorChannelsCount];
            for (int y = minY; y < maxY; y++)
            {
                for (int x = minX; x < maxX; x++)
                {
                    foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount))
                    {
                        // generate a ray from the senzor and lens towards the scene
                        Vector2d imagePos    = GenerateImageSample(new Point(x, y));
                        Ray      outgoingRay = Camera.GenerateRay(imagePos, sample);
                        if (outgoingRay == null)
                        {
                            continue;
                        }
                        Ray outgoingRayWorld = outgoingRay.Transform(Camera.CameraToWorld);

                        // intersect the scene

                        Intersection intersection = Scene.Intersect(outgoingRayWorld);

                        if (intersection == null)
                        {
                            continue;
                        }

                        // get the color stored in the scene point

                        for (int i = 0; i < outputImage.ColorChannelsCount; i++)
                        {
                            color[i] += intersection.Color[i];
                        }
                    }
                    for (int i = 0; i < outputImage.ColorChannelsCount; i++)
                    {
                        outputImage.Image[x, y, i] = color[i] * totalSampleCountInv;
                        color[i] = 0;
                    }
                }
            }
            return(outputImage);
        }
Ejemplo n.º 13
0
        private static Func <int, IEnumerable <Vector2d> > GetJitteredSampler()
        {
            Sampler sampler = new Sampler();

            return((sampleCount) => sampler.GenerateJitteredSamples(sampleCount));
        }
Ejemplo n.º 14
0
 private static Func<int, IEnumerable<Vector2d>> GetJitteredSampler()
 {
     Sampler sampler = new Sampler();
     return (sampleCount) => sampler.GenerateJitteredSamples(sampleCount);
 }
Ejemplo n.º 15
0
        private void cocClippingPanel_Paint(object sender, PaintEventArgs e)
        {
            if (layerBitmaps.Count <= 0)
            {
                return;
            }

            var g = e.Graphics;

            g.DrawImage(layerBitmaps[lightSourceLayer], 0, 0, heightField.Width, heightField.Height);

            int cocSize = 2 * cocRadius + 1;
            // The light source cannot be at the pixel edge as it will not be
            // easy to test if there was only a single intersection - with the
            // light source. If the light source is within the pixel it is easier.
            Vector3d lightSource = new Vector3d(cocCenter.X + 0.5f, cocCenter.Y + 0.5f,
                                                heightField.GetDepth((int)cocCenter.X, (int)cocCenter.Y, lightSourceLayer));

            if (lightSource.Z == 1)
            {
                return;
            }
            Rectangle coc = new Rectangle(
                (int)cocCenter.X - cocRadius,
                (int)cocCenter.Y - cocRadius,
                cocSize,
                cocSize);

            g.DrawRectangle(new Pen(new SolidBrush(Color.FromArgb(200, 0, 200, 0))), coc);
            Brush yellowBrush = new SolidBrush(Color.FromArgb(200, 255, 255, 0));
            Brush blueBrush   = new SolidBrush(Color.FromArgb(200, 0, 0, 100));
            float ratio       = cocFootprintRadius / (float)cocRadius;

            for (int y = -cocRadius; y <= cocRadius; y++)
            {
                for (int x = -cocRadius; x <= cocRadius; x++)
                {
                    Vector2d[] jitter = sampler.GenerateJitteredSamples(2).ToArray();

                    int visibleSamples = 0;
                    for (int i = 0; i < jitter.Length; i++)
                    {
                        Vector3d origin = new Vector3d(
                            cocCenter.X + ratio * (x + jitter[i].X),
                            cocCenter.Y + ratio * (y + jitter[i].Y), 0);
                        if ((origin.X >= 0) && (origin.X < heightField.Width) &&
                            (origin.Y >= 0) && (origin.Y < heightField.Height))
                        {
                            Intersection isec = selectedIntersector.Intersect(new Ray(origin, lightSource - origin));
                            if ((isec == null) || (isec.Position.Z >= lightSource.Z - 0.1f))
                            {
                                visibleSamples++;
                            }
                        }
                    }
                    float visibilityRatio = visibleSamples / (float)jitter.Length;
                    int   intensity       = (int)(255 * visibilityRatio);
                    g.FillRectangle(new SolidBrush(Color.FromArgb(200, intensity, intensity, 255 - intensity)), cocCenter.X + x, cocCenter.Y + y, 1, 1);
                }
            }
        }
Ejemplo n.º 16
0
            public static IList<Star> GenerateStars(int count, float intensity, bool colorize, int seed)
            {
                Sampler sampler = new Sampler(seed);
                Random random = new Random(seed);
                var starPositions = sampler.GenerateJitteredSamples((int)Math.Sqrt(count)).ToList();
                List<Star> stars = new List<Star>(starPositions.Count());

                foreach (var starPosition in starPositions)
                {
                    Vector3 color = new Vector3(intensity, intensity, intensity);
                    if (colorize)
                    {
                        color = Vector3.Multiply(color, new Vector3(
                            (float)random.NextDouble(),
                            (float)random.NextDouble(),
                            (float)random.NextDouble()));
                    }
                    else
                    {
                        color = Vector3.Multiply(color, (float)random.NextDouble());
                    }
                    Vector2 position = new Vector2((float)starPosition.X, (float)starPosition.Y);
                    stars.Add(new Star() { Position = position, Color = color });
                }
                return stars;
            }
Ejemplo n.º 17
0
        private void GenerateLensSamplesTexture(int textureId, int tileSize, int sqrtSampleCount, int totalSampleCount, float lensApertureRadius)
        {
            GL.BindTexture(TextureTarget.Texture3D, textureId);
            // size of a group of samples for a single pixel
            int bands = 2;
            int groupSize = bands * totalSampleCount;
            int textureSize = groupSize * tileSize * tileSize;

            Sampler sampler = new Sampler();
            IntPtr texturePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(float)) * textureSize);
            unsafe
            {
                int zStride = bands * tileSize * tileSize;
                for (int y = 0; y < tileSize; y++)
                {
                    for (int x = 0; x < tileSize; x++)
                    {
                        float* row = (float*)texturePtr + bands * (y * tileSize + x);
                        int index = 0;
                        // Z dimension, totalSampleCount times
                        foreach (Vector2d sample in
                            sampler.GenerateJitteredSamples(sqrtSampleCount))
                        {
                            Vector2d lensPos = lensApertureRadius *
                                //2 * (sample - new Vector2d(0.5, 0.5));
                            Sampler.ConcentricSampleDisk(sample);
                            row[index] = (float)lensPos.X;
                            row[index + 1] = (float)lensPos.Y;
                            index += zStride;
                        }
                    }
                }
            }

            // TODO: could be an unsigned byte instead of a float
            // TODO: two sample pair could be stored in one 4-channel value
            GL.TexImage3D(TextureTarget.Texture3D, 0, PixelInternalFormat.Rg32f,
                tileSize, tileSize, totalSampleCount, 0,
                PixelFormat.Rg, PixelType.Float, texturePtr);

            GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
            GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
            GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
            GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
            GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapR, (int)TextureWrapMode.Clamp);
        }
Ejemplo n.º 18
0
        public FloatMapImage RenderImagePreview(Size imageSize, Rectangle preview, FloatMapImage outputImage)
        {
            int height = imageSize.Height;
            int width = imageSize.Width;
            if ((outputImage == null) ||
                (outputImage.Width != width) ||
                (outputImage.Height != height))
            {
                outputImage = new FloatMapImage((uint)width, (uint)height);
            }

            Camera.Sensor.RasterSize = imageSize;

            Sampler sampler = new Sampler();
            int sqrtSampleCount = (int)Math.Sqrt(SampleCount);
            int totalSampleCount = sqrtSampleCount * sqrtSampleCount;
            float totalSampleCountInv = 1 / (float)totalSampleCount;

            // NOTE: It is not useful to directly use the same lens samples
            // for each pixel in the whole image. This leads to ugly artifacts
            // and surprisigly there is only an insignificant performance
            // benefit.

            int minX = preview.Left;
            int maxX = preview.Right;
            int minY = preview.Top;
            int maxY = preview.Bottom;
            float[] color = new float[outputImage.ColorChannelsCount];
            for (int y = minY; y < maxY; y++)
            {
                for (int x = minX; x < maxX; x++)
                {
                    foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount))
                    {
                        // generate a ray from the senzor and lens towards the scene
                        Vector2d imagePos = GenerateImageSample(new Point(x, y));
                        Ray outgoingRay = Camera.GenerateRay(imagePos, sample);
                        if (outgoingRay == null)
                        {
                            continue;
                        }
                        Ray outgoingRayWorld = outgoingRay.Transform(Camera.CameraToWorld);

                        // intersect the scene

                        Intersection intersection = Scene.Intersect(outgoingRayWorld);

                        if (intersection == null)
                        {
                            continue;
                        }

                        // get the color stored in the scene point

                        for (int i = 0; i < outputImage.ColorChannelsCount; i++)
                        {
                            color[i] += intersection.Color[i];
                        }
                    }
                    for (int i = 0; i < outputImage.ColorChannelsCount; i++)
                    {
                        outputImage.Image[x, y, i] = color[i] * totalSampleCountInv;
                        color[i] = 0;
                    }
                }
            }
            return outputImage;
        }
Ejemplo n.º 19
0
        //private IEnumerable<Vector2d> GenerateLensSamples(int tileSize, int sqrtSampleCount)
        //{
        //    int pixelCount = tileSize * tileSize;
        //    IEnumerator<Vector2d>[] jitteredSamplers = new IEnumerator<Vector2d>[pixelCount];
        //    Sampler sampler = new Sampler();
        //    for (int i = 0; i < pixelCount; i++)
        //    {
        //        jitteredSamplers[i] = sampler.GenerateJitteredSamples(MaxTotalSampleCount).GetEnumerator();
        //    }
        //    for (int sample = 0; sample < MaxTotalSampleCount; sample++)
        //    {
        //        for (int i = 0; i < pixelCount; i++)
        //        {
        //            jitteredSamplers[i].MoveNext();
        //            yield return jitteredSamplers[i].Current;
        //        }
        //    }
        //}
        private void GeneratePixelSamplesTexture(int textureId, int sqrtSampleCount, int sampleCount)
        {
            GL.BindTexture(TextureTarget.Texture1D, textureId);
            // size of a group of samples for a single pixel
            int bands = 2;
            int textureSize = bands * sampleCount;

            Sampler sampler = new Sampler();
            IntPtr texturePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Half)) * textureSize);
            unsafe
            {
                Half* row = (Half*)texturePtr;
                int index = 0;
                foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount))
                {
                    row[index] = (Half)(sample.X - 0.5f);
                    index++;
                    row[index] = (Half)(sample.Y - 0.5f);
                    index++;
                }
            }

            // TODO: could be an half float or unsigned byte instead of a float
            // TODO: two sample pair could be stored in one 4-channel value
            GL.TexImage1D(TextureTarget.Texture1D, 0, PixelInternalFormat.Rg16f,
                sampleCount, 0,
                PixelFormat.Rg, PixelType.HalfFloat, texturePtr);

            Marshal.FreeHGlobal(texturePtr);

            GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
            GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
            GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
        }