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 virtual Spectrum Rho(Vector wo, int numSamples, float[] samples) { Spectrum r = Spectrum.CreateBlack(); for (int i = 0; i < numSamples; ++i) { // Estimate one term of $\rho_\roman{hd}$ Vector wi; float pdf; Spectrum f = SampleF(wo, out wi, samples[2 * i], samples[2 * i + 1], out pdf); if (pdf > 0.0f) { r += f * ReflectionUtilities.AbsCosTheta(ref wi) / pdf; } } return(r / numSamples); }
public Spectrum Rho(Vector wo, Random rng, BxdfType flags = BxdfType.All, int sqrtSamples = 6) { int nSamples = sqrtSamples * sqrtSamples; var s1 = new float[2 * nSamples]; SamplingUtilities.StratifiedSample2D(s1, sqrtSamples, sqrtSamples, rng); Spectrum ret = Spectrum.CreateBlack(); foreach (var bxdf in _bxdfs) { if (bxdf.MatchesFlags(flags)) { ret += bxdf.Rho(wo, nSamples, s1); } } return(ret); }
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 virtual Spectrum Rho(int numSamples, float[] samples1, float[] samples2) { Spectrum r = Spectrum.CreateBlack(); for (int i = 0; i < numSamples; ++i) { // Estimate one term of $\rho_\roman{hh}$ Vector wo, wi; wo = MonteCarloUtilities.UniformSampleHemisphere(samples1[2 * i], samples1[2 * i + 1]); float pdf_o = MathUtility.InvTwoPi, pdf_i; Spectrum f = SampleF(wo, out wi, samples2[2 * i], samples2[2 * i + 1], out pdf_i); if (pdf_i > 0.0f) { r += f * ReflectionUtilities.AbsCosTheta(ref wi) * ReflectionUtilities.AbsCosTheta(ref wo) / (pdf_o * pdf_i); } } return(r / (MathUtility.Pi * numSamples)); }
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 Spectrum F(Vector woW, Vector wiW, BxdfType flags = BxdfType.All) { Vector wi = WorldToLocal(wiW), wo = WorldToLocal(woW); if (Vector.Dot(wiW, _ng) * Vector.Dot(woW, _ng) > 0) // ignore BTDFs { flags &= ~BxdfType.Transmission; } else // ignore BRDFs { flags &= ~BxdfType.Reflection; } Spectrum f = Spectrum.CreateBlack(); foreach (var bxdf in _bxdfs) { if (bxdf.MatchesFlags(flags)) { f += bxdf.F(wo, wi); } } return(f); }
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 virtual Spectrum Le(RayDifferential r) { return(Spectrum.CreateBlack()); }
public Spectrum SampleF(Vector woW, out Vector wiW, BsdfSample bsdfSample, out float pdf, out BxdfType sampledType, BxdfType flags = BxdfType.All) { // Choose which _BxDF_ to sample int matchingComps = NumComponents(flags); if (matchingComps == 0) { wiW = Vector.Zero; pdf = 0.0f; sampledType = 0; return(Spectrum.CreateBlack()); } int which = Math.Min( MathUtility.Floor(bsdfSample.UComponent * matchingComps), matchingComps - 1); Bxdf bxdf = null; int count = which; foreach (var eachBxdf in _bxdfs) { if (eachBxdf.MatchesFlags(flags) && count-- == 0) { bxdf = eachBxdf; break; } } Debug.Assert(bxdf != null); // Sample chosen _BxDF_ Vector wo = WorldToLocal(woW); Vector wi; pdf = 0.0f; Spectrum f = bxdf.SampleF(wo, out wi, bsdfSample.UDir0, bsdfSample.UDir1, out pdf); if (pdf == 0.0f) { wiW = Vector.Zero; sampledType = 0; return(Spectrum.CreateBlack()); } sampledType = bxdf.Type; wiW = LocalToWorld(wi); // Compute overall PDF with all matching _BxDF_s if (!bxdf.Type.HasFlag(BxdfType.Specular) && matchingComps > 1) { foreach (var eachBxdf in _bxdfs) { if (eachBxdf != bxdf && eachBxdf.MatchesFlags(flags)) { pdf += bxdf.Pdf(wo, wi); } } } if (matchingComps > 1) { pdf /= matchingComps; } // Compute value of BSDF for sampled direction if (!bxdf.Type.HasFlag(BxdfType.Specular)) { f = Spectrum.CreateBlack(); if (Vector.Dot(wiW, _ng) * Vector.Dot(woW, _ng) > 0) // ignore BTDFs { flags &= ~BxdfType.Transmission; } else // ignore BRDFs { flags &= ~BxdfType.Reflection; } foreach (var eachBxdf in _bxdfs) { if (eachBxdf.MatchesFlags(flags)) { f += eachBxdf.F(wo, wi); } } } return(f); }