本文整理汇总了C++中SurfaceInteraction::SpawnRay方法的典型用法代码示例。如果您正苦于以下问题:C++ SurfaceInteraction::SpawnRay方法的具体用法?C++ SurfaceInteraction::SpawnRay怎么用?C++ SurfaceInteraction::SpawnRay使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SurfaceInteraction
的用法示例。
在下文中一共展示了SurfaceInteraction::SpawnRay方法的12个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的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: SpecularTransmit
Spectrum SamplerIntegrator::SpecularTransmit(
const RayDifferential &ray, const SurfaceInteraction &isect,
const Scene &scene, Sampler &sampler, MemoryArena &arena, int depth) const {
Vector3f wo = isect.wo, wi;
Float pdf;
const Point3f &p = isect.p;
const Normal3f &ns = isect.shading.n;
const BSDF &bsdf = *isect.bsdf;
Spectrum f = bsdf.Sample_f(wo, &wi, sampler.Get2D(), &pdf,
BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR));
Spectrum L = Spectrum(0.f);
if (pdf > 0.f && !f.IsBlack() && AbsDot(wi, ns) != 0.f) {
// Compute ray differential _rd_ for specular transmission
RayDifferential rd = isect.SpawnRay(wi);
if (ray.hasDifferentials) {
rd.hasDifferentials = true;
rd.rxOrigin = p + isect.dpdx;
rd.ryOrigin = p + isect.dpdy;
Float eta = bsdf.eta;
Vector3f w = -wo;
if (Dot(wo, ns) < 0) eta = 1.f / eta;
Normal3f dndx = isect.shading.dndu * isect.dudx +
isect.shading.dndv * isect.dvdx;
Normal3f dndy = isect.shading.dndu * isect.dudy +
isect.shading.dndv * isect.dvdy;
Vector3f dwodx = -ray.rxDirection - wo,
dwody = -ray.ryDirection - wo;
Float dDNdx = Dot(dwodx, ns) + Dot(wo, dndx);
Float dDNdy = Dot(dwody, ns) + Dot(wo, dndy);
Float mu = eta * Dot(w, ns) - Dot(wi, ns);
Float dmudx =
(eta - (eta * eta * Dot(w, ns)) / Dot(wi, ns)) * dDNdx;
Float dmudy =
(eta - (eta * eta * Dot(w, ns)) / Dot(wi, ns)) * dDNdy;
rd.rxDirection =
wi + eta * dwodx - Vector3f(mu * dndx + dmudx * ns);
rd.ryDirection =
wi + eta * dwody - Vector3f(mu * dndy + dmudy * ns);
}
L = f * Li(rd, scene, sampler, arena, depth + 1) * AbsDot(wi, ns) / pdf;
}
return L;
}
示例3: 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;
}
示例4: SpecularReflect
Spectrum SamplerIntegrator::SpecularReflect(
const RayDifferential &ray, const SurfaceInteraction &isect,
const Scene &scene, Sampler &sampler, MemoryArena &arena, int depth) const {
// Compute specular reflection direction _wi_ and BSDF value
Vector3f wo = isect.wo, wi;
Float pdf;
BxDFType type = BxDFType(BSDF_REFLECTION | BSDF_SPECULAR);
Spectrum f = isect.bsdf->Sample_f(wo, &wi, sampler.Get2D(), &pdf, type);
// Return contribution of specular reflection
const Normal3f &ns = isect.shading.n;
if (pdf > 0.f && !f.IsBlack() && AbsDot(wi, ns) != 0.f) {
// Compute ray differential _rd_ for specular reflection
RayDifferential rd = isect.SpawnRay(wi);
if (ray.hasDifferentials) {
rd.hasDifferentials = true;
rd.rxOrigin = isect.p + isect.dpdx;
rd.ryOrigin = isect.p + isect.dpdy;
// Compute differential reflected directions
Normal3f dndx = isect.shading.dndu * isect.dudx +
isect.shading.dndv * isect.dvdx;
Normal3f dndy = isect.shading.dndu * isect.dudy +
isect.shading.dndv * isect.dvdy;
Vector3f dwodx = -ray.rxDirection - wo,
dwody = -ray.ryDirection - wo;
Float dDNdx = Dot(dwodx, ns) + Dot(wo, dndx);
Float dDNdy = Dot(dwody, ns) + Dot(wo, dndy);
rd.rxDirection =
wi - dwodx + 2.f * Vector3f(Dot(wo, ns) * dndx + dDNdx * ns);
rd.ryDirection =
wi - dwody + 2.f * Vector3f(Dot(wo, ns) * dndy + dDNdy * ns);
}
return f * Li(rd, scene, sampler, arena, depth + 1) * AbsDot(wi, ns) /
pdf;
} else
return Spectrum(0.f);
}
示例5: 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;
//.........这里部分代码省略.........
示例6: 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;
}
示例7: 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;
}
示例8: 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);
//.........这里部分代码省略.........
示例9: 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;
}
示例10: 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;
}
示例11: 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());
//.........这里部分代码省略.........
示例12: 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;
}