//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); }
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; }
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())); } }
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); }
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); } }
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); }
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); } }
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); }
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); }
private static Func <int, IEnumerable <Vector2d> > GetJitteredSampler() { Sampler sampler = new Sampler(); return((sampleCount) => sampler.GenerateJitteredSamples(sampleCount)); }
private static Func<int, IEnumerable<Vector2d>> GetJitteredSampler() { Sampler sampler = new Sampler(); return (sampleCount) => sampler.GenerateJitteredSamples(sampleCount); }
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); } } }
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; }
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); }
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; }
//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); }