public Spectrum Transmittance(Scene scene, Renderer renderer, Sample sample, Random rng) { return renderer.Transmittance( scene, RayDifferential.FromRay(Ray), sample, rng); }
public override void Render(Scene scene, CancellationToken cancellationToken) { // Allow integrators to do preprocessing for the scene _surfaceIntegrator.PreProcess(scene, _camera, this); _volumeIntegrator.PreProcess(scene, _camera, this); // Allocate and initialize _sample_ var sample = new Sample(_sampler, _surfaceIntegrator, _volumeIntegrator, scene); // Create and launch _SamplerRendererTask_s for rendering image // Compute number of _SamplerRendererTask_s to create for rendering var numPixels = _camera.Film.XResolution * _camera.Film.YResolution; var numTasks = Math.Max(32 * Environment.ProcessorCount, numPixels / (16 * 16)); numTasks = (int) MathUtility.RoundUpPow2((uint) numTasks); var renderTasks = Enumerable.Range(0, numTasks) .Select(i => CreateRenderTask(scene, sample, cancellationToken, numTasks - 1 - i, numTasks)) .ToArray(); // Organise tasks such that we do several passes over the whole image, // of increasing quality. var groupedRenderTasks = renderTasks.Select((t, i) => new { t, i }) .GroupBy(a => a.i % 6, a => a.t) .ToArray(); foreach (var groupedTasks in groupedRenderTasks) foreach (var task in groupedTasks) task.Start(); Task.WaitAll(renderTasks, cancellationToken); // Clean up after rendering and store final image _camera.Film.WriteImage(); }
private Task CreateRenderTask( Scene scene, Sample origSample, CancellationToken cancellationToken, int taskNumber, int taskCount) { return new Task(() => { var sampler = _sampler.GetSubSampler(taskNumber, taskCount); if (sampler == null) return; var rng = new Random(taskNumber); // Allocate space for samples and intersections int maxSamples = _sampler.MaximumSampleCount; var samples = origSample.Duplicate(maxSamples); var rays = new RayDifferential[maxSamples]; var Ls = new Spectrum[maxSamples]; var Ts = new Spectrum[maxSamples]; var isects = new Intersection[maxSamples]; // Get samples from _Sampler_ and update image int sampleCount; while ((sampleCount = sampler.GetMoreSamples(samples, rng)) > 0) { cancellationToken.ThrowIfCancellationRequested(); // Generate camera rays and compute radiance along rays for (int i = 0; i < sampleCount; ++i) { // Find camera ray for _sample[i]_ float rayWeight = _camera.GenerateRayDifferential(samples[i], out rays[i]); rays[i].ScaleDifferentials(1.0f / MathUtility.Sqrt(sampler.SamplesPerPixel)); // Evaluate radiance along camera ray if (rayWeight > 0.0f) { Ls[i] = rayWeight * Li(scene, rays[i], samples[i], rng, ref isects[i], out Ts[i]); } else { Ls[i] = new Spectrum(0.0f); Ts[i] = new Spectrum(1.0f); } } // Report sample results to _Sampler_, add contributions to image if (sampler.ReportResults(samples, rays, Ls, isects, sampleCount)) for (int i = 0; i < sampleCount; ++i) _camera.Film.AddSample(samples[i], Ls[i]); } _camera.Film.UpdateDisplay( sampler.XStart, sampler.YStart, sampler.XEnd + 1, sampler.YEnd + 1); }, cancellationToken); }
public BsdfSample(Sample sample, BsdfSampleOffsets offsets, int n) { Debug.Assert(n < sample.Num2D[offsets.PosOffset]); Debug.Assert(n < sample.Num1D[offsets.ComponentOffset]); UDir0 = sample.TwoD[offsets.PosOffset][2 * n]; UDir1 = sample.TwoD[offsets.PosOffset][2 * n + 1]; UComponent = sample.OneD[offsets.ComponentOffset][n]; Debug.Assert(UDir0 >= 0.0f && UDir0 < 1.0f); Debug.Assert(UDir1 >= 0.0f && UDir1 < 1.0f); Debug.Assert(UComponent >= 0.0f && UComponent < 1.0f); }
public LightSample(Sample sample, LightSampleOffsets offsets, int n) { Debug.Assert(n < sample.Num2D[offsets.PosOffset]); Debug.Assert(n < sample.Num1D[offsets.ComponentOffset]); UPos0 = sample.TwoD[offsets.PosOffset][2 * n]; UPos1 = sample.TwoD[offsets.PosOffset][2 * n + 1]; UComponent = sample.OneD[offsets.ComponentOffset][n]; Debug.Assert(UPos0 >= 0.0f && UPos0 < 1.0f); Debug.Assert(UPos1 >= 0.0f && UPos1 < 1.0f); Debug.Assert(UComponent >= 0.0f && UComponent < 1.0f); }
public Sample[] Duplicate(int count) { var ret = new Sample[count]; for (var i = 0; i < count; ++i) { ret[i] = new Sample { Num1D = Num1D.Select(x => x).ToList(), Num2D = Num2D.Select(x => x).ToList() }; ret[i].AllocateSampleMemory(); } return ret; }
public override int GetMoreSamples(Sample[] samples, Random rng) { if (_yPos == YEnd) return 0; int nSamples = _xPixelSamples * _yPixelSamples; // Generate stratified camera samples for _(xPos, yPos)_ // Generate initial stratified samples into _sampleBuf_ memory IList<float> imageSamples = new ArraySegment<float>(_sampleBuffer, 0, 2 * nSamples); IList<float> lensSamples = new ArraySegment<float>(_sampleBuffer, 2 * nSamples, 2 * nSamples); IList<float> timeSamples = new ArraySegment<float>(_sampleBuffer, 4 * nSamples, nSamples); SamplingUtilities.StratifiedSample2D(imageSamples, _xPixelSamples, _yPixelSamples, rng, _jitter); SamplingUtilities.StratifiedSample2D(lensSamples, _xPixelSamples, _yPixelSamples, rng, _jitter); SamplingUtilities.StratifiedSample1D(timeSamples, _xPixelSamples * _yPixelSamples, rng, _jitter); // Shift stratified image samples to pixel coordinates for (int o = 0; o < 2 * _xPixelSamples * _yPixelSamples; o += 2) { imageSamples[o] += _xPos; imageSamples[o + 1] += _yPos; } // Decorrelate sample dimensions SamplingUtilities.Shuffle(lensSamples, _xPixelSamples * _yPixelSamples, 2, rng); SamplingUtilities.Shuffle(timeSamples, _xPixelSamples * _yPixelSamples, 1, rng); // Initialize stratified _samples_ with sample values for (int i = 0; i < nSamples; ++i) { samples[i].ImageX = imageSamples[2 * i]; samples[i].ImageY = imageSamples[2 * i + 1]; samples[i].LensU = lensSamples[2 * i]; samples[i].LensV = lensSamples[2 * i + 1]; samples[i].Time = MathUtility.Lerp(timeSamples[i], ShutterOpen, ShutterClose); // Generate stratified samples for integrators for (var j = 0; j < samples[i].Num1D.Count; ++j) MonteCarloUtilities.LatinHypercube(samples[i].OneD[j], samples[i].Num1D[j], 1, rng); for (var j = 0; j < samples[i].Num2D.Count; ++j) MonteCarloUtilities.LatinHypercube(samples[i].TwoD[j], samples[i].Num2D[j], 2, rng); } // Advance to next pixel for stratified sampling if (++_xPos == XEnd) { _xPos = XStart; ++_yPos; } return nSamples; }
public static Spectrum SpecularTransmit(RayDifferential ray, Bsdf bsdf, Random rng, Intersection isect, Renderer renderer, Scene scene, Sample sample) { Vector wo = -ray.Direction, wi; float pdf; Point p = bsdf.DgShading.Point; Normal n = bsdf.DgShading.Normal; Spectrum f = bsdf.SampleF(wo, out wi, new BsdfSample(rng), out pdf, BxdfType.Transmission | BxdfType.Specular); Spectrum L = Spectrum.CreateBlack(); if (pdf > 0.0f && !f.IsBlack && Vector.AbsDot(wi, n) != 0.0f) { // Compute ray differential _rd_ for specular transmission var rd = new RayDifferential(p, wi, ray, isect.RayEpsilon); if (ray.HasDifferentials) { rd.HasDifferentials = true; rd.RxOrigin = p + isect.DifferentialGeometry.DpDx; rd.RyOrigin = p + isect.DifferentialGeometry.DpDy; float eta = bsdf.Eta; Vector w = -wo; if (Vector.Dot(wo, n) < 0) eta = 1.0f / eta; Normal dndx = bsdf.DgShading.DnDu * bsdf.DgShading.DuDx + bsdf.DgShading.DnDv * bsdf.DgShading.DvDx; Normal dndy = bsdf.DgShading.DnDu * bsdf.DgShading.DuDy + bsdf.DgShading.DnDv * bsdf.DgShading.DvDy; Vector dwodx = -ray.RxDirection - wo, dwody = -ray.RyDirection - wo; float dDNdx = Vector.Dot(dwodx, n) + Vector.Dot(wo, dndx); float dDNdy = Vector.Dot(dwody, n) + Vector.Dot(wo, dndy); float mu = eta * Vector.Dot(w, n) - Vector.Dot(wi, n); float dmudx = (eta - (eta * eta * Vector.Dot(w, n)) / Vector.Dot(wi, n)) * dDNdx; float dmudy = (eta - (eta * eta * Vector.Dot(w, n)) / Vector.Dot(wi, n)) * dDNdy; rd.RxDirection = wi + eta * dwodx - (Vector) (mu * dndx + dmudx * n); rd.RyDirection = wi + eta * dwody - (Vector) (mu * dndy + dmudy * n); } Spectrum Li = renderer.Li(scene, rd, sample, rng); L = f * Li * Vector.AbsDot(wi, n) / pdf; } return L; }
public override Spectrum Li(Scene scene, Renderer renderer, RayDifferential ray, Intersection intersection, Sample sample, Random rng) { Spectrum L = Spectrum.CreateBlack(); // Compute emitted and reflected light at ray intersection point // Evaluate BSDF at hit point var bsdf = intersection.GetBsdf(ray); // Initialize common variables for Whitted integrator Point p = bsdf.DgShading.Point; Normal n = bsdf.DgShading.Normal; Vector wo = -ray.Direction; // Compute emitted light if ray hit an area light source L += intersection.Le(wo); // Add contribution of each light source foreach (var light in scene.Lights) { Vector wi; float pdf; VisibilityTester visibility; Spectrum Li = light.SampleL(p, intersection.RayEpsilon, new LightSample(rng), ray.Time, out wi, out pdf, out visibility); if (Li.IsBlack || pdf == 0.0f) continue; Spectrum f = bsdf.F(wo, wi); if (!f.IsBlack && visibility.Unoccluded(scene)) L += f * Li * Vector.AbsDot(wi, n) * visibility.Transmittance(scene, renderer, sample, rng) / pdf; } if (ray.Depth + 1 < _maxDepth) { // Trace rays for specular reflection and refraction L += IntegratorUtilities.SpecularReflect(ray, bsdf, rng, intersection, renderer, scene, sample); L += IntegratorUtilities.SpecularTransmit(ray, bsdf, rng, intersection, renderer, scene, sample); } return L; }
public abstract Spectrum Li(Scene scene, Renderer renderer, RayDifferential ray, Sample sample, Random rng, out Spectrum transmittance);
public virtual bool ReportResults(Sample[] samples, RayDifferential[] rays, Spectrum[] ls, Intersection[] intersections, int count) { return true; }
public abstract int GetMoreSamples(Sample[] samples, Random rng);
public LightSampleOffsets(int numSamples, Sample sample) { NumSamples = numSamples; ComponentOffset = sample.Add1D(numSamples); PosOffset = sample.Add2D(numSamples); }
public Spectrum Li(Scene scene, RayDifferential ray, Sample sample, Random rng) { Intersection intersection = null; Spectrum t; return Li(scene, ray, sample, rng, ref intersection, out t); }
public abstract Spectrum Transmittance(Scene scene, RayDifferential ray, Sample sample, Random rng);
public override Spectrum Li(Scene scene, RayDifferential ray, Sample sample, Random rng, ref Intersection intersection, out Spectrum t) { Debug.Assert(ray.Time == sample.Time); Spectrum Li = Spectrum.CreateBlack(); if (scene.TryIntersect(ray, ref intersection)) Li = _surfaceIntegrator.Li(scene, this, ray, intersection, sample, rng); else { // Handle ray that doesn't intersect any geometry foreach (var light in scene.Lights) Li += light.Le(ray); } Spectrum Lvi = _volumeIntegrator.Li(scene, this, ray, sample, rng, out t); return t * Li + Lvi; }
public abstract Spectrum Li(Scene scene, RayDifferential ray, Sample sample, Random rng, ref Intersection intersection, out Spectrum t);
public virtual void RequestSamples(Sampler sampler, Sample sample, Scene scene) { }
public abstract Spectrum Li(Scene scene, Renderer renderer, RayDifferential ray, Intersection intersection, Sample sample, Random rng);
public override Spectrum Transmittance(Scene scene, Renderer renderer, RayDifferential ray, Sample sample, Random rng) { // TODO return new Spectrum(1.0f); }
public override Spectrum Li(Scene scene, Renderer renderer, RayDifferential ray, Sample sample, Random rng, out Spectrum transmittance) { // TODO transmittance = new Spectrum(1.0f); return Spectrum.CreateBlack(); }
public override Spectrum Transmittance(Scene scene, RayDifferential ray, Sample sample, Random rng) { return _volumeIntegrator.Transmittance(scene, this, ray, sample, rng); }