public void Render() { Scene scene = Scene; Camera camera = Camera; Sampler sampler = Sampler; Buffer buf = PBuffer; (int w, int h) = (buf.W, buf.H); int spp = SamplesPerPixel; int sppRoot = (int)(Math.Sqrt(SamplesPerPixel)); scene.Compile(); scene.rays = 0; Random rand = new Random(); double fu, fv; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { if (StratifiedSampling) { for (int u = 0; u < sppRoot; u++) { for (int v = 0; v < sppRoot; v++) { fu = (u + 0.5) / sppRoot; fv = (v + 0.5) / sppRoot; Ray ray = camera.CastRay(x, y, w, h, fu, fv, rand); Colour sample = sampler.Sample(scene, ray, rand); buf.AddSample(x, y, sample); } } } else { // Random subsampling for (int ii = 0; ii < spp; ii++) { fu = rand.NextDouble(); fv = rand.NextDouble(); Ray ray = camera.CastRay(x, y, w, h, fu, fv, rand); Colour sample = sampler.Sample(scene, ray, rand); buf.AddSample(x, y, sample); } } // Adaptive Sampling if (AdaptiveSamples > 0) { double v = buf.StandardDeviation(x, y).MaxComponent(); v = Util.Clamp(v / AdaptiveThreshold, 0, 1); v = Math.Pow(v, AdaptiveExponent); int samples = (int)(v * AdaptiveSamples); for (int d = 0; d < samples; d++) { fu = rand.NextDouble(); fv = rand.NextDouble(); Ray ray = camera.CastRay(x, y, w, h, fu, fv, rand); Colour sample = sampler.Sample(scene, ray, rand); buf.AddSample(x, y, sample); } } if (FireflySamples > 0) { if (PBuffer.StandardDeviation(x, y).MaxComponent() > FireflyThreshold) { for (int e = 0; e < FireflySamples; e++) { fu = rand.NextDouble(); fv = rand.NextDouble(); Ray ray = camera.CastRay(x, y, w, h, fu, fv, rand); Colour sample = sampler.Sample(scene, ray, rand); PBuffer.AddSample(x, y, sample); } } } } } }
public static Material LightMaterial(Colour color, double emittance) { return(new Material(color, null, null, null, null, 1, emittance, 1, 0, 0, -1, false)); }
public void RenderParallel() { Scene scene = Scene; Camera camera = Camera; Sampler sampler = Sampler; Buffer buf = PBuffer; (int w, int h) = (buf.W, buf.H); int spp = SamplesPerPixel; int sppRoot = (int)(Math.Sqrt(SamplesPerPixel)); scene.Compile(); scene.rays = 0; // Stop watch timer Stopwatch sw = new Stopwatch(); sw.Start(); // Random Number Generator from on Math.Numerics System.Random rand = new SystemRandomSource(sw.Elapsed.Milliseconds, true); // Frame resolution int totalPixels = h * w; // Create a cancellation token for Parallel.For loop control CancellationTokenSource cts = new CancellationTokenSource(); // ParallelOptions for Parallel.For ParallelOptions po = new ParallelOptions(); po.CancellationToken = cts.Token; // Set number of cores/threads po.MaxDegreeOfParallelism = Environment.ProcessorCount; Console.WriteLine("{0} x {1} pixels, {2} spp, {3} core(s)", w, h, spp, po.MaxDegreeOfParallelism); if (StratifiedSampling) { _ = Parallel.For(0, w * h, po, (i, loopState) => { int y = i / w, x = i % w; for (int u = 0; u < sppRoot; u++) { for (int v = 0; v < sppRoot; v++) { var fu = (u + 0.5) / sppRoot; var fv = (v + 0.5) / sppRoot; Ray ray = camera.CastRay(x, y, w, h, fu, fv, rand); Colour sample = sampler.Sample(scene, ray, rand); buf.AddSample(x, y, sample); } } }); Console.WriteLine("time elapsed:" + sw.Elapsed); } else { //Random subsampling _ = Parallel.ForEach(Partitioner.Create(0, totalPixels), po, (range) => { for (int i = range.Item1; i < range.Item2; i++) { for (int s = 0; s < spp; s++) { int y = i / w, x = i % w; var fu = ThreadSafeRandom.NextDouble(rand); var fv = ThreadSafeRandom.NextDouble(rand); var ray = camera.CastRay(x, y, w, h, fu, fv, rand); var sample = sampler.Sample(scene, ray, rand); buf.AddSample(x, y, sample); } } }); Console.WriteLine("time elapsed:" + sw.Elapsed); } if (AdaptiveSamples > 0) { _ = Parallel.For(0, w * h, po, (i, loopState) => { int y = i / w, x = i % w; double v = buf.StandardDeviation(x, y).MaxComponent(); v = Util.Clamp(v / AdaptiveThreshold, 0, 1); v = Math.Pow(v, AdaptiveExponent); int samples = (int)(v * AdaptiveSamples); for (int s = 0; s < samples; s++) { var fu = rand.NextDouble(); var fv = rand.NextDouble(); Ray ray = camera.CastRay(x, y, w, h, fu, fv, rand); Colour sample = sampler.Sample(scene, ray, rand); buf.AddSample(x, y, sample); } }); } if (FireflySamples > 0) { _ = Parallel.For(0, w * h, po, (i, loopState) => { int y = i / w, x = i % w; if (PBuffer.StandardDeviation(x, y).MaxComponent() > FireflyThreshold) { Parallel.For(0, FireflySamples, po, (e, loop) => { var fu = rand.NextDouble(); var fv = rand.NextDouble(); Ray ray = camera.CastRay(x, y, w, h, fu, fv, rand); Colour sample = sampler.Sample(scene, ray, rand); buf.AddSample(x, y, sample); }); } }); } sw.Stop(); }
public static Material TransparentMaterial(Colour color, double index, double gloss, double tint) { return(new Material(color, null, null, null, null, 1, 0, index, gloss, tint, -1, true)); }
public static Material MetallicMaterial(Colour color, double gloss, double tint) { return(new Material(color, null, null, null, null, 1, 0, 1, gloss, tint, 1, false)); }
public static Material GlossyMaterial(Colour color, double index, double gloss) { return(new Material(color, null, null, null, null, 1, 0, index, gloss, 0, -1, false)); }
public static Material SpecularMaterial(Colour color, double index) { return(new Material(color, null, null, null, null, 1, 0, index, 0, 0, -1, false)); }
public static Material DiffuseMaterial(Colour color) { return(new Material(color, null, null, null, null, 1, 0, 1, 0, 0, -1, false)); }
public void AddSample(int x, int y, Colour sample) => Pixels[y * W + x].AddSample(sample);
public Pixel(int Samples, Colour M, Colour V) { this.Samples = Samples; this.M = M; this.V = V; }