本文整理汇总了C++中SurfaceInteraction::ComputeScatteringFunctions方法的典型用法代码示例。如果您正苦于以下问题:C++ SurfaceInteraction::ComputeScatteringFunctions方法的具体用法?C++ SurfaceInteraction::ComputeScatteringFunctions怎么用?C++ SurfaceInteraction::ComputeScatteringFunctions使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SurfaceInteraction
的用法示例。
在下文中一共展示了SurfaceInteraction::ComputeScatteringFunctions方法的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: 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;
}
示例5: 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);
//.........这里部分代码省略.........
示例6: RandomWalk
int RandomWalk(const Scene &scene, RayDifferential ray, Sampler &sampler,
MemoryArena &arena, Spectrum beta, Float pdf, int maxDepth,
TransportMode mode, Vertex *path) {
if (maxDepth == 0) return 0;
int bounces = 0;
// Declare variables for forward and reverse probability densities
Float pdfFwd = pdf, pdfRev = 0;
while (true) {
// Attempt to create the next subpath vertex in _path_
MediumInteraction mi;
VLOG(2) << "Random walk. Bounces " << bounces << ", beta " << beta <<
", pdfFwd " << pdfFwd << ", pdfRev " << pdfRev;
// Trace a ray and sample the medium, if any
SurfaceInteraction isect;
bool foundIntersection = scene.Intersect(ray, &isect);
if (ray.medium) beta *= ray.medium->Sample(ray, sampler, arena, &mi);
if (beta.IsBlack()) break;
Vertex &vertex = path[bounces], &prev = path[bounces - 1];
if (mi.IsValid()) {
// Record medium interaction in _path_ and compute forward density
vertex = Vertex::CreateMedium(mi, beta, pdfFwd, prev);
if (++bounces >= maxDepth) break;
// Sample direction and compute reverse density at preceding vertex
Vector3f wi;
pdfFwd = pdfRev = mi.phase->Sample_p(-ray.d, &wi, sampler.Get2D());
ray = mi.SpawnRay(wi);
} else {
// Handle surface interaction for path generation
if (!foundIntersection) {
// Capture escaped rays when tracing from the camera
if (mode == TransportMode::Radiance) {
vertex = Vertex::CreateLight(EndpointInteraction(ray), beta,
pdfFwd);
++bounces;
}
break;
}
// Compute scattering functions for _mode_ and skip over medium
// boundaries
isect.ComputeScatteringFunctions(ray, arena, true, mode);
if (!isect.bsdf) {
ray = isect.SpawnRay(ray.d);
continue;
}
// Initialize _vertex_ with surface intersection information
vertex = Vertex::CreateSurface(isect, beta, pdfFwd, prev);
if (++bounces >= maxDepth) break;
// Sample BSDF at current vertex and compute reverse probability
Vector3f wi, wo = isect.wo;
BxDFType type;
Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdfFwd,
BSDF_ALL, &type);
VLOG(2) << "Random walk sampled dir " << wi << " f: " << f <<
", pdfFwd: " << pdfFwd;
if (f.IsBlack() || pdfFwd == 0.f) break;
beta *= f * AbsDot(wi, isect.shading.n) / pdfFwd;
VLOG(2) << "Random walk beta now " << beta;
pdfRev = isect.bsdf->Pdf(wi, wo, BSDF_ALL);
if (type & BSDF_SPECULAR) {
vertex.delta = true;
pdfRev = pdfFwd = 0;
}
beta *= CorrectShadingNormal(isect, wo, wi, mode);
VLOG(2) << "Random walk beta after shading normal correction " << beta;
ray = isect.SpawnRay(wi);
}
// Compute reverse area density at preceding vertex
prev.pdfRev = vertex.ConvertDensity(pdfRev, prev);
}
return bounces;
}
示例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: 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());
//.........这里部分代码省略.........
示例9: RandomWalk
int RandomWalk(const Scene &scene, RayDifferential ray, Sampler &sampler,
MemoryArena &arena, Spectrum weight, Float pdfFwd, int maxdepth,
TransportMode mode, Vertex *path) {
int bounces = 0;
if (maxdepth == 0) return 0;
SurfaceInteraction isect;
MediumInteraction mi;
while (true) {
// Trace a ray and sample the medium, if any
bool foundIntersection = scene.Intersect(ray, &isect);
if (ray.medium) weight *= ray.medium->Sample(ray, sampler, arena, &mi);
if (weight.IsBlack()) break;
Vertex &vertex = path[bounces], &prev = path[bounces - 1];
Float pdfRev;
if (mi.IsValid()) {
// Handle the medium case
// Record medium interaction in _path_ and compute forward density
vertex = Vertex(mi, weight);
vertex.pdfFwd = ConvertDensity(prev, pdfFwd, vertex);
if (++bounces >= maxdepth) break;
// Sample direction and compute reverse density at preceding vertex
Vector3f wi;
pdfFwd = pdfRev = mi.phase->Sample_p(-ray.d, &wi, sampler.Get2D());
ray = mi.SpawnRay(wi);
} else {
// Handle the surface case
if (!foundIntersection) {
// Capture escaped rays when tracing from the camera
if (mode == TransportMode::Radiance) {
vertex = Vertex(VertexType::Light, EndpointInteraction(ray),
weight);
vertex.pdfFwd = pdfFwd;
++bounces;
}
break;
}
// Compute scattering functions for _mode_ and skip over medium
// boundaries
isect.ComputeScatteringFunctions(ray, arena, true, mode);
if (!isect.bsdf) {
ray = isect.SpawnRay(ray.d);
continue;
}
// Fill _vertex_ with intersection information
vertex = Vertex(isect, weight);
vertex.pdfFwd = ConvertDensity(prev, pdfFwd, vertex);
if (++bounces >= maxdepth) break;
// Sample BSDF at current vertex and compute reverse probability
Vector3f wi, wo = isect.wo;
BxDFType flags;
Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdfFwd,
BSDF_ALL, &flags);
if (f.IsBlack() || pdfFwd == 0.f) break;
weight *= f * AbsDot(wi, isect.shading.n) / pdfFwd;
pdfRev = isect.bsdf->Pdf(wi, wo, BSDF_ALL);
if (flags & BSDF_SPECULAR) {
vertex.delta = true;
pdfRev = pdfFwd = 0;
}
weight *= ShadingNormalCorrection(isect, wo, wi, mode);
ray = isect.SpawnRay(wi);
}
// Compute reverse area density at preceding vertex
prev.pdfRev = ConvertDensity(vertex, pdfRev, prev);
}
return bounces;
}