本文整理汇总了C++中SurfaceInteraction::Le方法的典型用法代码示例。如果您正苦于以下问题:C++ SurfaceInteraction::Le方法的具体用法?C++ SurfaceInteraction::Le怎么用?C++ SurfaceInteraction::Le使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SurfaceInteraction
的用法示例。
在下文中一共展示了SurfaceInteraction::Le方法的9个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: Li
Spectrum DirectLightingIntegrator::Li(const RayDifferential &ray,
const Scene &scene, Sampler &sampler,
MemoryArena &arena, int depth) const {
ProfilePhase p(Prof::SamplerIntegratorLi);
Spectrum L(0.f);
// Find closest ray intersection or return background radiance
SurfaceInteraction isect;
if (!scene.Intersect(ray, &isect)) {
for (const auto &light : scene.lights) L += light->Le(ray);
return L;
}
// Compute scattering functions for surface interaction
isect.ComputeScatteringFunctions(ray, arena);
if (!isect.bsdf)
return Li(isect.SpawnRay(ray.d), scene, sampler, arena, depth);
Vector3f wo = isect.wo;
// Compute emitted light if ray hit an area light source
L += isect.Le(wo);
if (scene.lights.size() > 0) {
// Compute direct lighting for _DirectLightingIntegrator_ integrator
if (strategy == LightStrategy::UniformSampleAll)
L += UniformSampleAllLights(isect, scene, arena, sampler,
nLightSamples);
else
L += UniformSampleOneLight(isect, scene, arena, sampler);
}
if (depth + 1 < maxDepth) {
Vector3f wi;
// Trace rays for specular reflection and refraction
L += SpecularReflect(ray, isect, scene, sampler, arena, depth);
L += SpecularTransmit(ray, isect, scene, sampler, arena, depth);
}
return L;
}
示例2: Li
// WhittedIntegrator Method Definitions
Spectrum WhittedIntegrator::Li(const RayDifferential &ray, const Scene &scene,
Sampler &sampler, MemoryArena &arena,
int depth) const {
Spectrum L(0.);
// Find closest ray intersection or return background radiance
SurfaceInteraction isect;
if (!scene.Intersect(ray, &isect)) {
for (const auto &light : scene.lights) L += light->Le(ray);
return L;
}
// Compute emitted and reflected light at ray intersection point
// Initialize common variables for Whitted integrator
const Normal3f &n = isect.shading.n;
Vector3f wo = isect.wo;
// Compute scattering functions for surface interaction
isect.ComputeScatteringFunctions(ray, arena);
if (!isect.bsdf)
return Li(isect.SpawnRay(ray.d), scene, sampler, arena, depth);
// Compute emitted light if ray hit an area light source
L += isect.Le(wo);
// Add contribution of each light source
for (const auto &light : scene.lights) {
Vector3f wi;
Float pdf;
VisibilityTester visibility;
Spectrum Li =
light->Sample_Li(isect, sampler.Get2D(), &wi, &pdf, &visibility);
if (Li.IsBlack() || pdf == 0) continue;
Spectrum f = isect.bsdf->f(wo, wi);
if (!f.IsBlack() && visibility.Unoccluded(scene))
L += f * Li * AbsDot(wi, n) / pdf;
}
if (depth + 1 < maxDepth) {
// Trace rays for specular reflection and refraction
L += SpecularReflect(ray, isect, scene, sampler, arena, depth);
L += SpecularTransmit(ray, isect, scene, sampler, arena, depth);
}
return L;
}
示例3: Li
// VolPathIntegrator Method Definitions
Spectrum VolPathIntegrator::Li(const RayDifferential &r, const Scene &scene,
Sampler &sampler, MemoryArena &arena,
int depth) const {
ProfilePhase p(Prof::SamplerIntegratorLi);
Spectrum L(0.f), alpha(1.f);
RayDifferential ray(r);
bool specularBounce = false;
for (int bounces = 0;; ++bounces) {
// Store intersection into _isect_
SurfaceInteraction isect;
bool foundIntersection = scene.Intersect(ray, &isect);
// Sample the participating medium, if present
MediumInteraction mi;
if (ray.medium) alpha *= ray.medium->Sample(ray, sampler, arena, &mi);
if (alpha.IsBlack()) break;
// Handle an interaction with a medium or a surface
if (mi.IsValid()) {
// Handle medium scattering case
Vector3f wo = -ray.d, wi;
L += alpha * UniformSampleOneLight(mi, scene, sampler, arena, true);
Point2f phaseSample = sampler.Get2D();
mi.phase->Sample_p(wo, &wi, phaseSample);
ray = mi.SpawnRay(wi);
} else {
// Handle surface scattering case
// Possibly add emitted light and terminate
if (bounces == 0 || specularBounce) {
// Add emitted light at path vertex or from the environment
if (foundIntersection)
L += alpha * isect.Le(-ray.d);
else
for (const auto &light : scene.lights)
L += alpha * light->Le(ray);
}
if (!foundIntersection || bounces >= maxDepth) break;
// Compute scattering functions and skip over medium boundaries
isect.ComputeScatteringFunctions(ray, arena, true);
if (!isect.bsdf) {
ray = isect.SpawnRay(ray.d);
bounces--;
continue;
}
// Sample illumination from lights to find attenuated path
// contribution
L += alpha *
UniformSampleOneLight(isect, scene, sampler, arena, true);
// Sample BSDF to get new path direction
Vector3f wo = -ray.d, wi;
Float pdf;
BxDFType flags;
Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdf,
BSDF_ALL, &flags);
if (f.IsBlack() || pdf == 0.f) break;
alpha *= f * AbsDot(wi, isect.shading.n) / pdf;
Assert(std::isinf(alpha.y()) == false);
specularBounce = (flags & BSDF_SPECULAR) != 0;
ray = isect.SpawnRay(wi);
// Account for attenuated subsurface scattering, if applicable
if (isect.bssrdf && (flags & BSDF_TRANSMISSION)) {
// Importance sample the BSSRDF
SurfaceInteraction pi;
Spectrum S = isect.bssrdf->Sample_S(
scene, sampler.Get1D(), sampler.Get2D(), arena, &pi, &pdf);
#ifndef NDEBUG
Assert(std::isinf(alpha.y()) == false);
#endif
if (S.IsBlack() || pdf == 0) break;
alpha *= S / pdf;
// Account for the attenuated direct subsurface scattering
// component
L += alpha *
UniformSampleOneLight(pi, scene, sampler, arena, true);
// Account for the indirect subsurface scattering component
Spectrum f = pi.bsdf->Sample_f(pi.wo, &wi, sampler.Get2D(),
&pdf, BSDF_ALL, &flags);
if (f.IsBlack() || pdf == 0.f) break;
alpha *= f * AbsDot(wi, pi.shading.n) / pdf;
#ifndef NDEBUG
Assert(std::isinf(alpha.y()) == false);
#endif
specularBounce = (flags & BSDF_SPECULAR) != 0;
ray = pi.SpawnRay(wi);
}
}
// Possibly terminate the path
if (bounces > 3) {
Float continueProbability = std::min((Float).5, alpha.y());
if (sampler.Get1D() > continueProbability) break;
alpha /= continueProbability;
//.........这里部分代码省略.........
示例4: L
rose::Spectrum rose::PathTracerIntegrator::IncomingRadiance(const rose::Ray &ray,
const rose::RayInterval &interval,
const rose::Scene &scene,
uint32_t) const {
// Final incoming radiance and accumulation value
Spectrum L(0.f), beta(1.f);
Ray current_ray(ray);
RayInterval current_interval(interval);
bool specular_bounce = false;
uint32_t bounces;
// Keep track of specular bounce
for (bounces = 0;; ++bounces) {
SurfaceInteraction interaction;
bool found_interaction = scene.Intersect(current_ray, current_interval, &interaction);
// Possibly add emission
if (bounces == 0 || specular_bounce) {
// Add emitted light
if (found_interaction) {
L += beta * interaction.Le(Normalize(-current_ray.Direction()));
} else {
for (const auto &light : scene.Lights()) {
L += beta * light->Le(current_ray);
}
}
}
// Terminate path if ray escaped or max depth reached
if (!found_interaction || bounces >= max_depth) { break; }
// Compute scattering function
std::unique_ptr<BSDF> bsdf = interaction.CreateBSDF(true);
// Get shading variables
const Vector3f n = interaction.sh_frame.N();
const Vector3f wo = Normalize(-current_ray.Direction());
// Loop over all lights and add direct contribution
for (const auto &light : scene.Lights()) {
// Sample light
LightSample light_sample;
OcclusionTester occlusion_tester;
Spectrum Li = light->SampleLi(interaction, sampler->Next2D(), &light_sample, &occlusion_tester);
// Check light return
if (Li.IsBlack() || light_sample.pdf == 0.f) { continue; }
// Evaluate BSDF
Spectrum f = bsdf->F(wo, light_sample.wi);
if (!f.IsBlack() && occlusion_tester.Unoccluded(scene)) {
L += beta * f * Li * AbsDotProduct(n, light_sample.wi) / light_sample.pdf;
}
}
// Sample BSDF to get new path
BXDFSample bsdf_sample;
Spectrum f = bsdf->SampleF(wo, sampler->Next2D(), &bsdf_sample);
if (f.IsBlack() || bsdf_sample.pdf == 0.f) { break; }
// Update beta
beta *= f * AbsDotProduct(bsdf_sample.wi, n) / bsdf_sample.pdf;
// Check if bounce is specular
specular_bounce = (bsdf_sample.sampled_type & SPECULAR) != 0;
// Compute new ray
current_ray = interaction.SpawnRay(bsdf_sample.wi);
// Possibly terminate path with Russian roulette
if (bounces > 3) {
float q = std::max(0.05f, 1.f - beta.Norm());
if (sampler->Next1D() < q) { break; }
beta /= 1.f - q;
}
}
return L;
}
示例5: Li
// PathIntegrator Method Definitions
Spectrum PathIntegrator::Li(const RayDifferential &r, const Scene &scene,
Sampler &sampler, MemoryArena &arena) const {
Spectrum L(0.f);
// Declare common path integration variables
RayDifferential ray(r);
Spectrum pathThroughput = Spectrum(1.f);
bool specularBounce = false;
for (int bounces = 0;; ++bounces) {
// Store intersection into _isect_
SurfaceInteraction isect;
bool foundIntersection = scene.Intersect(ray, &isect);
// Possibly add emitted light and terminate
if (bounces == 0 || specularBounce) {
// Add emitted light at path vertex or from the environment
if (foundIntersection)
L += pathThroughput * isect.Le(-ray.d);
else
for (const auto &light : scene.lights)
L += pathThroughput * light->Le(ray);
}
if (!foundIntersection || bounces >= maxDepth) break;
// Compute scattering functions and skip over medium boundaries
isect.ComputeScatteringFunctions(ray, arena, true);
if (!isect.bsdf) {
ray = isect.SpawnRay(ray.d);
bounces--;
continue;
}
// Sample illumination from lights to find path contribution
L += pathThroughput *
UniformSampleOneLight(isect, scene, sampler, arena);
// Sample BSDF to get new path direction
Vector3f wo = -ray.d, wi;
Float pdf;
BxDFType flags;
Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdf,
BSDF_ALL, &flags);
if (f.IsBlack() || pdf == 0.f) break;
pathThroughput *= f * AbsDot(wi, isect.shading.n) / pdf;
#ifndef NDEBUG
Assert(std::isinf(pathThroughput.y()) == false);
#endif
specularBounce = (flags & BSDF_SPECULAR) != 0;
ray = isect.SpawnRay(wi);
// Account for subsurface scattering, if applicable
if (isect.bssrdf && (flags & BSDF_TRANSMISSION)) {
// Importance sample the BSSRDF
BSSRDFSample bssrdfSample;
bssrdfSample.uDiscrete = sampler.Get1D();
bssrdfSample.pos = sampler.Get2D();
SurfaceInteraction isect_out = isect;
pathThroughput *= isect.bssrdf->Sample_f(
isect_out, scene, ray.time, bssrdfSample, arena, &isect, &pdf);
#ifndef NDEBUG
Assert(std::isinf(pathThroughput.y()) == false);
#endif
if (pathThroughput.IsBlack()) break;
// Account for the direct subsurface scattering component
isect.wo = Vector3f(isect.shading.n);
// Sample illumination from lights to find path contribution
L += pathThroughput *
UniformSampleOneLight(isect, scene, sampler, arena);
// Account for the indirect subsurface scattering component
Spectrum f = isect.bsdf->Sample_f(isect.wo, &wi, sampler.Get2D(),
&pdf, BSDF_ALL, &flags);
if (f.IsBlack() || pdf == 0.f) break;
pathThroughput *= f * AbsDot(wi, isect.shading.n) / pdf;
#ifndef NDEBUG
Assert(std::isinf(pathThroughput.y()) == false);
#endif
specularBounce = (flags & BSDF_SPECULAR) != 0;
ray = isect.SpawnRay(wi);
}
// Possibly terminate the path
if (bounces > 3) {
Float continueProbability = std::min((Float).5, pathThroughput.y());
if (sampler.Get1D() > continueProbability) break;
pathThroughput /= continueProbability;
Assert(std::isinf(pathThroughput.y()) == false);
}
}
return L;
}
示例6: Li
Spectrum VolPathIntegrator::Li(const RayDifferential &r, const Scene &scene,
Sampler &sampler, MemoryArena &arena,
int depth) const {
ProfilePhase p(Prof::SamplerIntegratorLi);
Spectrum L(0.f), beta(1.f);
RayDifferential ray(r);
bool specularBounce = false;
int bounces;
// Added after book publication: etaScale tracks the accumulated effect
// of radiance scaling due to rays passing through refractive
// boundaries (see the derivation on p. 527 of the third edition). We
// track this value in order to remove it from beta when we apply
// Russian roulette; this is worthwhile, since it lets us sometimes
// avoid terminating refracted rays that are about to be refracted back
// out of a medium and thus have their beta value increased.
Float etaScale = 1;
for (bounces = 0;; ++bounces) {
// Intersect _ray_ with scene and store intersection in _isect_
SurfaceInteraction isect;
bool foundIntersection = scene.Intersect(ray, &isect);
// Sample the participating medium, if present
MediumInteraction mi;
if (ray.medium) beta *= ray.medium->Sample(ray, sampler, arena, &mi);
if (beta.IsBlack()) break;
// Handle an interaction with a medium or a surface
if (mi.IsValid()) {
// Terminate path if ray escaped or _maxDepth_ was reached
if (bounces >= maxDepth) break;
++volumeInteractions;
// Handle scattering at point in medium for volumetric path tracer
const Distribution1D *lightDistrib =
lightDistribution->Lookup(mi.p);
L += beta * UniformSampleOneLight(mi, scene, arena, sampler, true,
lightDistrib);
Vector3f wo = -ray.d, wi;
mi.phase->Sample_p(wo, &wi, sampler.Get2D());
ray = mi.SpawnRay(wi);
} else {
++surfaceInteractions;
// Handle scattering at point on surface for volumetric path tracer
// Possibly add emitted light at intersection
if (bounces == 0 || specularBounce) {
// Add emitted light at path vertex or from the environment
if (foundIntersection)
L += beta * isect.Le(-ray.d);
else
for (const auto &light : scene.infiniteLights)
L += beta * light->Le(ray);
}
// Terminate path if ray escaped or _maxDepth_ was reached
if (!foundIntersection || bounces >= maxDepth) break;
// Compute scattering functions and skip over medium boundaries
isect.ComputeScatteringFunctions(ray, arena, true);
if (!isect.bsdf) {
ray = isect.SpawnRay(ray.d);
bounces--;
continue;
}
// Sample illumination from lights to find attenuated path
// contribution
const Distribution1D *lightDistrib =
lightDistribution->Lookup(isect.p);
L += beta * UniformSampleOneLight(isect, scene, arena, sampler,
true, lightDistrib);
// Sample BSDF to get new path direction
Vector3f wo = -ray.d, wi;
Float pdf;
BxDFType flags;
Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdf,
BSDF_ALL, &flags);
if (f.IsBlack() || pdf == 0.f) break;
beta *= f * AbsDot(wi, isect.shading.n) / pdf;
DCHECK(std::isinf(beta.y()) == false);
specularBounce = (flags & BSDF_SPECULAR) != 0;
if ((flags & BSDF_SPECULAR) && (flags & BSDF_TRANSMISSION)) {
Float eta = isect.bsdf->eta;
// Update the term that tracks radiance scaling for refraction
// depending on whether the ray is entering or leaving the
// medium.
etaScale *=
(Dot(wo, isect.n) > 0) ? (eta * eta) : 1 / (eta * eta);
}
ray = isect.SpawnRay(ray, wi, flags, isect.bsdf->eta);
// Account for attenuated subsurface scattering, if applicable
if (isect.bssrdf && (flags & BSDF_TRANSMISSION)) {
// Importance sample the BSSRDF
SurfaceInteraction pi;
Spectrum S = isect.bssrdf->Sample_S(
scene, sampler.Get1D(), sampler.Get2D(), arena, &pi, &pdf);
//.........这里部分代码省略.........
示例7: Li
// PathIntegrator Method Definitions
Spectrum PathIntegrator::Li(const RayDifferential &r, const Scene &scene,
Sampler &sampler, MemoryArena &arena,
int depth) const {
ProfilePhase p(Prof::SamplerIntegratorLi);
Spectrum L(0.f), beta(1.f);
RayDifferential ray(r);
bool specularBounce = false;
for (int bounces = 0;; ++bounces) {
// Find next path vertex and accumulate contribution
// Intersect _ray_ with scene and store intersection in _isect_
SurfaceInteraction isect;
bool foundIntersection = scene.Intersect(ray, &isect);
// Possibly add emitted light at intersection
if (bounces == 0 || specularBounce) {
// Add emitted light at path vertex or from the environment
if (foundIntersection)
L += beta * isect.Le(-ray.d);
else
for (const auto &light : scene.lights)
L += beta * light->Le(ray);
}
// Terminate path if ray escaped or _maxDepth_ was reached
if (!foundIntersection || bounces >= maxDepth) break;
// Compute scattering functions and skip over medium boundaries
isect.ComputeScatteringFunctions(ray, arena, true);
if (!isect.bsdf) {
ray = isect.SpawnRay(ray.d);
bounces--;
continue;
}
// Sample illumination from lights to find path contribution
L += beta * UniformSampleOneLight(isect, scene, arena, sampler);
// Sample BSDF to get new path direction
Vector3f wo = -ray.d, wi;
Float pdf;
BxDFType flags;
Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdf,
BSDF_ALL, &flags);
if (f.IsBlack() || pdf == 0.f) break;
beta *= f * AbsDot(wi, isect.shading.n) / pdf;
Assert(std::isinf(beta.y()) == false);
specularBounce = (flags & BSDF_SPECULAR) != 0;
ray = isect.SpawnRay(wi);
// Account for subsurface scattering, if applicable
if (isect.bssrdf && (flags & BSDF_TRANSMISSION)) {
// Importance sample the BSSRDF
SurfaceInteraction pi;
Spectrum S = isect.bssrdf->Sample_S(
scene, sampler.Get1D(), sampler.Get2D(), arena, &pi, &pdf);
#ifndef NDEBUG
Assert(std::isinf(beta.y()) == false);
#endif
if (S.IsBlack() || pdf == 0) break;
beta *= S / pdf;
// Account for the direct subsurface scattering component
L += beta * UniformSampleOneLight(pi, scene, arena, sampler);
// Account for the indirect subsurface scattering component
Spectrum f = pi.bsdf->Sample_f(pi.wo, &wi, sampler.Get2D(), &pdf,
BSDF_ALL, &flags);
if (f.IsBlack() || pdf == 0) break;
beta *= f * AbsDot(wi, pi.shading.n) / pdf;
#ifndef NDEBUG
Assert(std::isinf(beta.y()) == false);
#endif
specularBounce = (flags & BSDF_SPECULAR) != 0;
ray = pi.SpawnRay(wi);
}
// Possibly terminate the path with Russian roulette
if (bounces > 3) {
Float continueProbability = std::min((Float).95, beta.y());
if (sampler.Get1D() > continueProbability) break;
beta /= continueProbability;
Assert(std::isinf(beta.y()) == false);
}
}
return L;
}
示例8: EstimateDirect
Spectrum EstimateDirect(const Interaction &it, const Point2f &uScattering,
const Light &light, const Point2f &uLight,
const Scene &scene, Sampler &sampler,
MemoryArena &arena, bool handleMedia, bool specular) {
BxDFType bsdfFlags =
specular ? BSDF_ALL : BxDFType(BSDF_ALL & ~BSDF_SPECULAR);
Spectrum Ld(0.f);
// Sample light source with multiple importance sampling
Vector3f wi;
Float lightPdf = 0, scatteringPdf = 0;
VisibilityTester visibility;
Spectrum Li = light.Sample_Li(it, uLight, &wi, &lightPdf, &visibility);
if (lightPdf > 0 && !Li.IsBlack()) {
// Compute BSDF or phase function's value for light sample
Spectrum f;
if (it.IsSurfaceInteraction()) {
// Evaluate BSDF for light sampling strategy
const SurfaceInteraction &isect = (const SurfaceInteraction &)it;
f = isect.bsdf->f(isect.wo, wi, bsdfFlags) *
AbsDot(wi, isect.shading.n);
scatteringPdf = isect.bsdf->Pdf(isect.wo, wi, bsdfFlags);
} else {
// Evaluate phase function for light sampling strategy
const MediumInteraction &mi = (const MediumInteraction &)it;
Float p = mi.phase->p(mi.wo, wi);
f = Spectrum(p);
scatteringPdf = p;
}
if (!f.IsBlack()) {
// Compute effect of visibility for light source sample
if (handleMedia)
Li *= visibility.Tr(scene, sampler);
else if (!visibility.Unoccluded(scene))
Li = Spectrum(0.f);
// Add light's contribution to reflected radiance
if (!Li.IsBlack()) {
if (IsDeltaLight(light.flags))
Ld += f * Li / lightPdf;
else {
Float weight =
PowerHeuristic(1, lightPdf, 1, scatteringPdf);
Ld += f * Li * weight / lightPdf;
}
}
}
}
// Sample BSDF with multiple importance sampling
if (!IsDeltaLight(light.flags)) {
Spectrum f;
bool sampledSpecular = false;
if (it.IsSurfaceInteraction()) {
// Sample scattered direction for surface interactions
BxDFType sampledType;
const SurfaceInteraction &isect = (const SurfaceInteraction &)it;
f = isect.bsdf->Sample_f(isect.wo, &wi, uScattering, &scatteringPdf,
bsdfFlags, &sampledType);
f *= AbsDot(wi, isect.shading.n);
sampledSpecular = sampledType & BSDF_SPECULAR;
} else {
// Sample scattered direction for medium interactions
const MediumInteraction &mi = (const MediumInteraction &)it;
Float p = mi.phase->Sample_p(mi.wo, &wi, uScattering);
f = Spectrum(p);
scatteringPdf = p;
}
if (!f.IsBlack() && scatteringPdf > 0) {
// Account for light contributions along sampled direction _wi_
Float weight = 1;
if (!sampledSpecular) {
lightPdf = light.Pdf_Li(it, wi);
if (lightPdf == 0) return Ld;
weight = PowerHeuristic(1, scatteringPdf, 1, lightPdf);
}
// Find intersection and compute transmittance
SurfaceInteraction lightIsect;
Ray ray = it.SpawnRay(wi);
Spectrum Tr(1.f);
bool foundSurfaceInteraction =
handleMedia ? scene.IntersectTr(ray, sampler, &lightIsect, &Tr)
: scene.Intersect(ray, &lightIsect);
// Add light contribution from material sampling
Spectrum Li(0.f);
if (foundSurfaceInteraction) {
if (lightIsect.primitive->GetAreaLight() == &light)
Li = lightIsect.Le(-wi);
} else
Li = light.Le(ray);
if (!Li.IsBlack()) Ld += f * Li * Tr * weight / scatteringPdf;
}
}
return Ld;
}
示例9: Li
Spectrum PathIntegrator::Li(const RayDifferential &r, const Scene &scene,
Sampler &sampler, MemoryArena &arena,
int depth) const {
ProfilePhase p(Prof::SamplerIntegratorLi);
Spectrum L(0.f), beta(1.f);
RayDifferential ray(r);
bool specularBounce = false;
int bounces;
for (bounces = 0;; ++bounces) {
// Find next path vertex and accumulate contribution
VLOG(2) << "Path tracer bounce " << bounces << ", current L = " << L <<
", beta = " << beta;
// Intersect _ray_ with scene and store intersection in _isect_
SurfaceInteraction isect;
bool foundIntersection = scene.Intersect(ray, &isect);
// Possibly add emitted light at intersection
if (bounces == 0 || specularBounce) {
// Add emitted light at path vertex or from the environment
if (foundIntersection) {
L += beta * isect.Le(-ray.d);
VLOG(2) << "Added Le -> L = " << L;
} else {
for (const auto &light : scene.infiniteLights)
L += beta * light->Le(ray);
VLOG(2) << "Added infinite area lights -> L = " << L;
}
}
// Terminate path if ray escaped or _maxDepth_ was reached
if (!foundIntersection || bounces >= maxDepth) break;
// Compute scattering functions and skip over medium boundaries
isect.ComputeScatteringFunctions(ray, arena, true);
if (!isect.bsdf) {
VLOG(2) << "Skipping intersection due to null bsdf";
ray = isect.SpawnRay(ray.d);
bounces--;
continue;
}
const Distribution1D *distrib = lightDistribution->Lookup(isect.p);
// Sample illumination from lights to find path contribution.
// (But skip this for perfectly specular BSDFs.)
if (isect.bsdf->NumComponents(BxDFType(BSDF_ALL & ~BSDF_SPECULAR)) >
0) {
++totalPaths;
Spectrum Ld =
beta * UniformSampleOneLight(isect, scene, arena, sampler, false,
distrib);
VLOG(2) << "Sampled direct lighting Ld = " << Ld;
if (Ld.IsBlack()) ++zeroRadiancePaths;
CHECK_GE(Ld.y(), 0.f);
L += Ld;
}
// Sample BSDF to get new path direction
Vector3f wo = -ray.d, wi;
Float pdf;
BxDFType flags;
Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdf,
BSDF_ALL, &flags);
VLOG(2) << "Sampled BSDF, f = " << f << ", pdf = " << pdf;
if (f.IsBlack() || pdf == 0.f) break;
beta *= f * AbsDot(wi, isect.shading.n) / pdf;
VLOG(2) << "Updated beta = " << beta;
CHECK_GE(beta.y(), 0.f);
DCHECK(!std::isinf(beta.y()));
specularBounce = (flags & BSDF_SPECULAR) != 0;
ray = isect.SpawnRay(wi);
// Account for subsurface scattering, if applicable
if (isect.bssrdf && (flags & BSDF_TRANSMISSION)) {
// Importance sample the BSSRDF
SurfaceInteraction pi;
Spectrum S = isect.bssrdf->Sample_S(
scene, sampler.Get1D(), sampler.Get2D(), arena, &pi, &pdf);
DCHECK(!std::isinf(beta.y()));
if (S.IsBlack() || pdf == 0) break;
beta *= S / pdf;
// Account for the direct subsurface scattering component
L += beta * UniformSampleOneLight(pi, scene, arena, sampler, false,
lightDistribution->Lookup(pi.p));
// Account for the indirect subsurface scattering component
Spectrum f = pi.bsdf->Sample_f(pi.wo, &wi, sampler.Get2D(), &pdf,
BSDF_ALL, &flags);
if (f.IsBlack() || pdf == 0) break;
beta *= f * AbsDot(wi, pi.shading.n) / pdf;
DCHECK(!std::isinf(beta.y()));
specularBounce = (flags & BSDF_SPECULAR) != 0;
ray = pi.SpawnRay(wi);
}
// Possibly terminate the path with Russian roulette
if (beta.y() < rrThreshold && bounces > 3) {
Float q = std::max((Float).05, 1 - beta.MaxComponentValue());
//.........这里部分代码省略.........