public Spectrum UniformSampleAllLights(Interaction inter, Scene scene, Sampler sampler) { var L = Spectrum.Zero; for (var l = 0; l < scene.Lights.Count; ++l) { var light = scene.Lights[l]; // Estimate direct lighting using the requested sample arrays var lightPointArray = sampler.Get2DArray(lightSampleCounts[l]); var scatteringArray = sampler.Get2DArray(lightSampleCounts[l]); if (lightPointArray != null && scatteringArray != null) { var Ld = Spectrum.Zero; for (var sample = 0; sample < light.SampleCount; ++sample) { Ld += EstimateDirect(inter, scatteringArray[sample], light, lightPointArray[sample], scene, sampler); } L += Ld / light.SampleCount; } // If not available, fall back to single sample estimates else { var lightPoint = sampler.Get2D(); var scattering = sampler.Get2D(); L += EstimateDirect(inter, scattering, light, lightPoint, scene, sampler); } } return(L); }
public Spectrum UniformSampleOneLight(Interaction inter, Scene scene, Sampler sampler) { if (!scene.Lights.Any()) { return(Spectrum.Zero); } // Randomly choose a light var light = scene.Lights[Window.Random.Next(scene.Lights.Count)]; // Compensate sampling a single light by multiplying the result by the light count // (will average the contribution of each light over enough samples) var lightPoint = sampler.Get2D(); var scattering = sampler.Get2D(); return(EstimateDirect(inter, scattering, light, lightPoint, scene, sampler) * scene.Lights.Count); }
public Spectrum SpecularTransmit( RayDifferential ray, SurfaceInteraction isect, Scene scene, Sampler sampler, int depth) { Vector3D wo = isect.Wo; double pdf; Point3D p = isect.P; Normal3D ns = isect.ShadingN; Bsdf bsdf = isect.Bsdf; Spectrum f = bsdf.Sample_f(wo, out Vector3D wi, sampler.Get2D(), out pdf, out BxdfType sampledType, BxdfType.Transmission | BxdfType.Specular); Spectrum L = Spectrum.Create(0.0); if (pdf > 0.0 && !f.IsBlack() && wi.AbsDot(ns) != 0.0) { // Compute ray differential _rd_ for specular transmission RayDifferential rd = new RayDifferential(isect.SpawnRay(wi)); if (ray.HasDifferentials) { rd.HasDifferentials = true; rd.RxOrigin = p + isect.Dpdx.ToPoint3D(); rd.RyOrigin = p + isect.Dpdy.ToPoint3D(); double eta = bsdf.Eta; Vector3D w = -wo; if (wo.Dot(ns) < 0.0) { eta = 1.0 / eta; } Normal3D dndx = isect.ShadingDndu * isect.Dudx + isect.ShadingDndv * isect.Dvdx; Normal3D dndy = isect.ShadingDndu * isect.Dudy + isect.ShadingDndv * isect.Dvdy; Vector3D dwodx = -ray.RxDirection - wo, dwody = -ray.RyDirection - wo; double dDNdx = dwodx.Dot(ns) + wo.Dot(dndx); double dDNdy = dwody.Dot(ns) + wo.Dot(dndy); double mu = eta * w.Dot(ns) - wi.Dot(ns); double dmudx = (eta - (eta * eta * w.Dot(ns)) / wi.Dot(ns)) * dDNdx; double dmudy = (eta - (eta * eta * w.Dot(ns)) / wi.Dot(ns)) * dDNdy; rd.RxDirection = wi + eta * dwodx - (mu * dndx + dmudx * ns).ToVector3D(); rd.RyDirection = wi + eta * dwody - (mu * dndy + dmudy * ns).ToVector3D(); } L = f * Li(rd, scene, sampler, depth + 1) * wi.AbsDot(ns) / pdf; } return(L); }
/// <inheritdoc /> public override Spectrum Li(RayDifferential ray, Scene scene, Sampler sampler, int depth = 0) { Spectrum L = Spectrum.Create(0.0); // Find closest ray intersection or return background radiance if (!scene.Intersect(ray, out SurfaceInteraction isect)) { foreach (var light in scene.Lights) { L += light.Le(ray); } return(L); } // Compute emitted and reflected light at ray intersection point // Initialize common variables for Whitted integrator Normal3D n = isect.ShadingN; Vector3D wo = isect.Wo; // Compute scattering functions for surface interaction isect.ComputeScatteringFunctions(ray); if (isect.Bsdf == null) { return(Li(new RayDifferential(isect.SpawnRay(ray.Direction)), scene, sampler, depth)); } // Compute emitted light if ray hit an area light source L += isect.Le(wo); // Add contribution of each light source foreach (var light in scene.Lights) { Spectrum Li = light.Sample_Li(isect, sampler.Get2D(), out Vector3D wi, out double pdf, out VisibilityTester visibility); if (Li.IsBlack() || pdf == 0.0) { continue; } Spectrum f = isect.Bsdf.f(wo, wi); if (!f.IsBlack() && visibility.Unoccluded(scene)) { L += f * Li * wi.AbsDot(n) / pdf; } } if (depth + 1 < _maxDepth) { // Trace rays for specular reflection and refraction L += SpecularReflect(ray, isect, scene, sampler, depth); L += SpecularTransmit(ray, isect, scene, sampler, depth); } return(L); }
public Spectrum SpecularReflect( RayDifferential ray, SurfaceInteraction isect, Scene scene, Sampler sampler, int depth) { // Compute specular reflection direction _wi_ and BSDF value Vector3D wo = isect.Wo; BxdfType type = BxdfType.Reflection | BxdfType.Specular; Spectrum f = isect.Bsdf.Sample_f(wo, out Vector3D wi, sampler.Get2D(), out double pdf, out BxdfType sampledType, type); // Return contribution of specular reflection Normal3D ns = isect.ShadingN; if (pdf > 0.0 && !f.IsBlack() && wi.AbsDot(ns) != 0.0) { // Compute ray differential _rd_ for specular reflection RayDifferential rd = new RayDifferential(isect.SpawnRay(wi)); if (ray.HasDifferentials) { rd.HasDifferentials = true; rd.RxOrigin = isect.P + isect.Dpdx.ToPoint3D(); rd.RyOrigin = isect.P + isect.Dpdy.ToPoint3D(); // Compute differential reflected directions Normal3D dndx = isect.ShadingDndu * isect.Dudx + isect.ShadingDndv * isect.Dvdx; Normal3D dndy = isect.ShadingDndu * isect.Dudy + isect.ShadingDndv * isect.Dvdy; Vector3D dwodx = -ray.RxDirection - wo, dwody = -ray.RyDirection - wo; double dDNdx = dwodx.Dot(ns) + wo.Dot(dndx); double dDNdy = dwody.Dot(ns) + wo.Dot(dndy); rd.RxDirection = wi - dwodx + 2.0 * (wo.Dot(ns) * dndx + dDNdx * ns).ToVector3D(); rd.RyDirection = wi - dwody + 2.0 * (wo.Dot(ns) * dndy + dDNdy * ns).ToVector3D(); } return(f * Li(rd, scene, sampler, depth + 1) * wi.AbsDot(ns) / pdf); } else { return(Spectrum.Create(0.0)); } }
private Spectrum SpecularReflect(RayDifferential ray, SurfaceInteraction inter, Scene scene, Camera camera, Sampler sampler, int depth) { // Sample a direction with the BSDF var type = BxDFType.Reflection | BxDFType.Specular; var f = inter.Bsdf.Sample_f(inter.Wo, out Vector3 <float> wi, sampler.Get2D(), out float pdf, type, out BxDF.BxDFType sampledType); // Add the contribution of this reflection if (pdf > 0 && !f.IsBlack() && Vector3 <float> .AbsDot(wi, inter.Shading.N) != 0) { var newRay = inter.SpawnRay(wi).ToDiff(); if (ray.HasDifferentials) { // TODO } return(f * Li(newRay, scene, camera, sampler, depth + 1) * Vector3 <float> .AbsDot(wi, inter.Shading.N) * (1.0f / pdf)); } return(Spectrum.Zero); }
public override Spectrum Li(RayDifferential ray, Scene scene, Camera camera, Sampler sampler, int depth = 0) { var L = Spectrum.Zero; // If the ray doesn't intersect the scene, return the background radiance if (!scene.Intersect(ray, out SurfaceInteraction inter) || inter == null) { foreach (var light in scene.Lights) { L += light.Le(ray); } return(L); } // If the ray intersects something, we need to compute how the light is scattered var n = inter.Shading.N; var wo = inter.Wo; inter.ComputeScatteringFunctions(ray); // Add the emissive contribution of the intersected object L += inter.Le(wo); // Add the direct contribution of each light source foreach (var light in scene.Lights) { // Sample the light source var Li = light.Sample_Li(inter, sampler.Get2D(), out Vector3 <float> wi, out float pdf, out VisibilityTester visibility); if (Li.IsBlack() || pdf == 0) { continue; } // Evaluate the scattering at the interaction point var f = inter.Bsdf.f(wo, wi); // Trace a shadow ray to check that the point receives light if (!f.IsBlack()) { if (visibility.Unoccluded(scene)) { L += f * Li * Vector3 <float> .AbsDot(wi, n.ToVector3()) * (1.0f / pdf); } /*else * L = new Spectrum(0, 0, 50);*/ } else { } } // Recursively trace new rays if (depth + 1 < maxDepth) { L += SpecularReflect(ray, inter, scene, camera, sampler, depth); //L += SpecularTransmit(ray, inter, scene, sampler, depth); } return(L); }