void Light::SHProject(const PbrtPoint &p, float pEpsilon, int lmax, const Scene *scene, bool computeLightVisibility, float time, RNG &rng, Spectrum *coeffs) const { for (int i = 0; i < SHTerms(lmax); ++i) coeffs[i] = 0.f; uint32_t ns = RoundUpPow2(nSamples); uint32_t scramble1D = rng.RandomUInt(); uint32_t scramble2D[2] = { rng.RandomUInt(), rng.RandomUInt() }; float *Ylm = ALLOCA(float, SHTerms(lmax)); for (uint32_t i = 0; i < ns; ++i) { // Compute incident radiance sample from _light_, update SH _coeffs_ float u[2], pdf; Sample02(i, scramble2D, u); LightSample lightSample(u[0], u[1], VanDerCorput(i, scramble1D)); Vector wi; VisibilityTester vis; Spectrum Li = Sample_L(p, pEpsilon, lightSample, time, &wi, &pdf, &vis); if (!Li.IsBlack() && pdf > 0.f && (!computeLightVisibility || vis.Unoccluded(scene))) { // Add light sample contribution to MC estimate of SH coefficients SHEvaluate(wi, lmax, Ylm); for (int j = 0; j < SHTerms(lmax); ++j) coeffs[j] += Li * Ylm[j] / (pdf * ns); } } }
void PointLight::SHProject(const pbrt::Point &p, float pEpsilon, int lmax, const Scene *scene, bool computeLightVisibility, float time, RNG &rng, Spectrum *coeffs) const { for (int i = 0; i < SHTerms(lmax); ++i) coeffs[i] = 0.f; if (computeLightVisibility && scene->IntersectP(Ray(p, Normalize(lightPos - p), pEpsilon, Distance(lightPos, p), time))) return; // Project point light source to SH float *Ylm = ALLOCA(float, SHTerms(lmax)); Vector wi = Normalize(lightPos - p); SHEvaluate(wi, lmax, Ylm); Spectrum Li = Intensity / DistanceSquared(lightPos, p); for (int i = 0; i < SHTerms(lmax); ++i) coeffs[i] = Li * Ylm[i]; }
Spectrum UseRadianceProbes::Li(const Scene *scene, const Renderer *renderer, const RayDifferential &ray, const Intersection &isect, const Sample *sample, RNG &rng, MemoryArena &arena, int wavelength) const { Spectrum L(0.); Vector wo = -ray.d; // Compute emitted light if ray hit an area light source L += isect.Le(wo); // Evaluate BSDF at hit point BSDF *bsdf = isect.GetBSDF(ray, arena, wavelength); const Point &p = bsdf->dgShading.p; const Normal &n = bsdf->dgShading.nn; // Compute reflection for radiance probes integrator if (!includeDirectInProbes) L += UniformSampleAllLights(scene, renderer, arena, p, n, wo, isect.rayEpsilon, ray.time, bsdf, sample, rng, lightSampleOffsets, bsdfSampleOffsets); // Compute reflected lighting using radiance probes // Compute probe coordinates and offsets for lookup point Vector offset = bbox.Offset(p); float voxx = (offset.x * nProbes[0]) - 0.5f; float voxy = (offset.y * nProbes[1]) - 0.5f; float voxz = (offset.z * nProbes[2]) - 0.5f; int vx = Floor2Int(voxx), vy = Floor2Int(voxy), vz = Floor2Int(voxz); float dx = voxx - vx, dy = voxy - vy, dz = voxz - vz; // Get radiance probe coefficients around lookup point const Spectrum *b000 = c_inXYZ(lmax, vx, vy, vz); const Spectrum *b100 = c_inXYZ(lmax, vx+1, vy, vz); const Spectrum *b010 = c_inXYZ(lmax, vx, vy+1, vz); const Spectrum *b110 = c_inXYZ(lmax, vx+1, vy+1, vz); const Spectrum *b001 = c_inXYZ(lmax, vx, vy, vz+1); const Spectrum *b101 = c_inXYZ(lmax, vx+1, vy, vz+1); const Spectrum *b011 = c_inXYZ(lmax, vx, vy+1, vz+1); const Spectrum *b111 = c_inXYZ(lmax, vx+1, vy+1, vz+1); // Compute incident radiance from radiance probe coefficients Spectrum *c_inp = arena.Alloc<Spectrum>(SHTerms(lmax)); for (int i = 0; i < SHTerms(lmax); ++i) { // Do trilinear interpolation to compute SH coefficients at point Spectrum c00 = Lerp(dx, b000[i], b100[i]); Spectrum c10 = Lerp(dx, b010[i], b110[i]); Spectrum c01 = Lerp(dx, b001[i], b101[i]); Spectrum c11 = Lerp(dx, b011[i], b111[i]); Spectrum c0 = Lerp(dy, c00, c10); Spectrum c1 = Lerp(dy, c01, c11); c_inp[i] = Lerp(dz, c0, c1); } // Convolve incident radiance to compute irradiance function Spectrum *c_E = arena.Alloc<Spectrum>(SHTerms(lmax)); SHConvolveCosTheta(lmax, c_inp, c_E); // Evaluate irradiance function and accumulate reflection Spectrum rho = bsdf->rho(wo, rng, BSDF_ALL_REFLECTION); float *Ylm = ALLOCA(float, SHTerms(lmax)); SHEvaluate(Vector(Faceforward(n, wo)), lmax, Ylm); Spectrum E = 0.f; for (int i = 0; i < SHTerms(lmax); ++i) E += c_E[i] * Ylm[i]; L += rho * INV_PI * E.Clamp(); return L; }
Spectrum GlossyPRTIntegrator::Li(const Scene *scene, const Renderer *, const RayDifferential &ray, const Intersection &isect, const Sample *sample, RNG &rng, MemoryArena &arena) const { Spectrum L = 0.f; Vector wo = -ray.d; // Compute emitted light if ray hit an area light source L += isect.Le(wo); // Evaluate BSDF at hit point BSDF *bsdf = isect.GetBSDF(ray, arena); const Point &p = bsdf->dgShading.p; // Compute reflected radiance with glossy PRT at point // Compute SH radiance transfer matrix at point and SH coefficients Spectrum *c_t = arena.Alloc<Spectrum>(SHTerms(lmax)); Spectrum *T = arena.Alloc<Spectrum>(SHTerms(lmax)*SHTerms(lmax)); SHComputeTransferMatrix(p, isect.rayEpsilon, scene, rng, nSamples, lmax, T); SHMatrixVectorMultiply(T, c_in, c_t, lmax); // Rotate incident SH lighting to local coordinate frame Vector r1 = bsdf->LocalToWorld(Vector(1,0,0)); Vector r2 = bsdf->LocalToWorld(Vector(0,1,0)); Normal nl = Normal(bsdf->LocalToWorld(Vector(0,0,1))); Matrix4x4 rot(r1.x, r2.x, nl.x, 0, r1.y, r2.y, nl.y, 0, r1.z, r2.z, nl.z, 0, 0, 0, 0, 1); Spectrum *c_l = arena.Alloc<Spectrum>(SHTerms(lmax)); SHRotate(c_t, c_l, rot, lmax, arena); #if 0 // Sample BSDF and integrate against direct SH coefficients float *Ylm = ALLOCA(float, SHTerms(lmax)); int ns = 1024; for (int i = 0; i < ns; ++i) { Vector wi; float pdf; Spectrum f = bsdf->Sample_f(wo, &wi, BSDFSample(rng), &pdf); if (pdf > 0.f && !f.IsBlack() && !scene->IntersectP(Ray(p, wi))) { f *= fabsf(Dot(wi, n)) / (pdf * ns); SHEvaluate(bsdf->WorldToLocal(wi), lmax, Ylm); Spectrum Li = 0.f; for (int j = 0; j < SHTerms(lmax); ++j) Li += Ylm[j] * c_l[j] * f; L += Li.Clamp(); } } #else // Compute final coefficients _c\_o_ using BSDF matrix Spectrum *c_o = arena.Alloc<Spectrum>(SHTerms(lmax)); SHMatrixVectorMultiply(B, c_l, c_o, lmax); // Evaluate outgoing radiance function for $\wo$ and add to _L_ Vector woLocal = bsdf->WorldToLocal(wo); float *Ylm = ALLOCA(float, SHTerms(lmax)); SHEvaluate(woLocal, lmax, Ylm); Spectrum Li = 0.f; for (int i = 0; i < SHTerms(lmax); ++i) Li += Ylm[i] * c_o[i]; L += Li.Clamp(); #endif return L; }