Spectrum DiffusePRTIntegrator::Li(const Scene *scene, const Renderer *, const RayDifferential &ray, const Intersection &isect, const Sample *sample, 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; const Normal &n = bsdf->dgShading.nn; // Compute reflected radiance using diffuse PRT // Project diffuse transfer function at point to SH Spectrum *c_transfer = arena.Alloc<Spectrum>(SHTerms(lmax)); SHComputeDiffuseTransfer(p, Faceforward(n, wo), isect.rayEpsilon, scene, *sample->rng, nSamples, lmax, c_transfer); // Compute integral of product of incident radiance and transfer function Spectrum LT = 0.f; for (int i = 0; i < SHTerms(lmax); ++i) LT += c_in[i] * c_transfer[i]; // Compute reflectance at point for diffuse transfer const int sqrtRhoSamples = 6; float rhoRSamples[2*sqrtRhoSamples*sqrtRhoSamples]; StratifiedSample2D(rhoRSamples, sqrtRhoSamples, sqrtRhoSamples, *sample->rng); Spectrum Kd = bsdf->rho(wo, sqrtRhoSamples*sqrtRhoSamples, rhoRSamples, BSDF_ALL_REFLECTION) * INV_PI; return L + Kd * LT.Clamp(); }
Spectrum operator()(float d2) const { Spectrum dpos = Sqrt(Spectrum(d2) + zpos * zpos); Spectrum dneg = Sqrt(Spectrum(d2) + zneg * zneg); Spectrum Rd = (1.f / (4.f * M_PI)) * ((zpos * (dpos * sigma_tr + Spectrum(1.f)) * Exp(-sigma_tr * dpos)) / (dpos * dpos * dpos) - (zneg * (dneg * sigma_tr + Spectrum(1.f)) * Exp(-sigma_tr * dneg)) / (dneg * dneg * dneg)); return Rd.Clamp(); }
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; }
COREDLL Spectrum FresnelApproxK(const Spectrum &Fr) { Spectrum reflectance = Fr.Clamp(0.f, .999f); return 2.f * (reflectance / (Spectrum(1.) - reflectance)).Sqrt(); }
COREDLL Spectrum FresnelApproxEta(const Spectrum &Fr) { Spectrum reflectance = Fr.Clamp(0.f, .999f); return (Spectrum(1.) + reflectance.Sqrt()) / (Spectrum(1.) - reflectance.Sqrt()); }
Spectrum FresnelApproxK(const Spectrum &Fr) { const Spectrum reflectance = Fr.Clamp(0.f, .999f); return 2.f * Sqrt(reflectance / (Spectrum(1.f) - reflectance)); }
Spectrum FresnelApproxN(const Spectrum &Fr) { const Spectrum sqrtReflectance = Fr.Clamp(0.f, .999f).Sqrt(); return (Spectrum(1.f) + sqrtReflectance) / (Spectrum(1.f) - sqrtReflectance); }