// DiffusionReflectance Public Methods DiffusionReflectance(const Spectrum &sigma_a, const Spectrum &sigmap_s, float eta) { A = (1.f + Fdr(eta)) / (1.f - Fdr(eta)); sigmap_t = sigma_a + sigmap_s; sigma_tr = Sqrt(3.f * sigma_a * sigmap_t); alphap = sigmap_s / sigmap_t; zpos = Spectrum(1.f) / sigmap_t; zneg = zpos * (1.f + (4.f/3.f) * A); }
void SubsurfaceFromDiffuse(const Spectrum &Kd, float meanPathLength, float eta, Spectrum *sigma_a, Spectrum *sigma_prime_s) { float A = (1.f + Fdr(eta)) / (1.f - Fdr(eta)); float rgb[3]; Kd.ToRGB(rgb); float sigma_prime_s_rgb[3], sigma_a_rgb[3]; for (int i = 0; i < 3; ++i) { float alphap = RdToAlphap(rgb[i], A); float sigma_tr = 1.f / meanPathLength; float sigma_prime_t = sigma_tr / sqrtf(3.f * 1.f - alphap); sigma_prime_s_rgb[i] = alphap * sigma_prime_t; sigma_a_rgb[i] = sigma_prime_t - sigma_prime_s_rgb[i]; } *sigma_a = Spectrum::FromRGB(sigma_a_rgb); *sigma_prime_s = Spectrum::FromRGB(sigma_prime_s_rgb); }
void subsurfaceFromDiffuse(const Spectrum &Kd, double meanPathLength, double eta, Spectrum *sigma_a, Spectrum *sigma_prime_s) { double A = (1.f + Fdr(eta)) / (1.f - Fdr(eta)); double rgb[3]; Kd.toRGB(rgb); double sigma_prime_s_rgb[3], sigma_a_rgb[3]; for (int i = 0; i < 3; ++i) { // Compute $\alpha'$ for RGB component, compute scattering properties double alphap = RdToAlphap(rgb[i], A); double sigma_tr = 1.f / meanPathLength; double sigma_prime_t = sigma_tr / sqrtf(3.f * (1.f - alphap)); sigma_prime_s_rgb[i] = alphap * sigma_prime_t; sigma_a_rgb[i] = sigma_prime_t - sigma_prime_s_rgb[i]; } *sigma_a = Spectrum::fromRGB(sigma_a_rgb); *sigma_prime_s = Spectrum::fromRGB(sigma_prime_s_rgb); }
Spectrum DipoleSubsurfaceIntegrator::Li(const Scene *scene, const Renderer *renderer, const RayDifferential &ray, const Intersection &isect, const Sample *sample, RNG &rng, MemoryArena &arena) 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); const Point &p = bsdf->dgShading.p; const Normal &n = bsdf->dgShading.nn; Spectrum rho_dr = Spectrum(1.0f); // Evaluate BSSRDF and possibly compute subsurface scattering BSSRDF *bssrdf = isect.GetBSSRDF(ray, arena); if (bssrdf && octree) { Spectrum sigma_a = bssrdf->sigma_a(); Spectrum sigmap_s = bssrdf->sigma_prime_s(); Spectrum sigmap_t = sigmap_s + sigma_a; if (!sigmap_t.IsBlack()) { // Use hierarchical integration to evaluate reflection from dipole model PBRT_SUBSURFACE_STARTED_OCTREE_LOOKUP(const_cast<Point *>(&p)); DiffusionReflectance Rd(sigma_a, sigmap_s, bssrdf->eta()); Spectrum Mo = octree->Mo(octreeBounds, p, Rd, maxError); FresnelDielectric fresnel(1.f, bssrdf->eta()); Spectrum Ft = Spectrum(1.f) - fresnel.Evaluate(AbsDot(wo, n)); float Fdt = 1.f - Fdr(bssrdf->eta()); // modulate SSS contribution by rho_dr //L += (INV_PI * Ft) * (Fdt * Mo); rho_dr = wet->integrate_BRDF(bsdf, ray.d, 10, BxDFType(BSDF_REFLECTION | BSDF_GLOSSY)); L += (INV_PI * Ft) * (Fdt * Mo) * (Spectrum(1.0f) - rho_dr); //L += (INV_PI * Ft) * (Fdt * Mo) * (Spectrum(0.0f)); PBRT_SUBSURFACE_FINISHED_OCTREE_LOOKUP(); } } L += UniformSampleAllLights(scene, renderer, arena, p, n, wo, isect.rayEpsilon, ray.time, bsdf, sample, rng, lightSampleOffsets, bsdfSampleOffsets); if (ray.depth < maxSpecularDepth) { // Trace rays for specular reflection and refraction. //TODO: this has no effect? L += SpecularReflect(ray, bsdf, rng, isect, renderer, scene, sample, arena); L += SpecularTransmit(ray, bsdf, rng, isect, renderer, scene, sample, arena); } return L; }