本文整理汇总了C++中Sampler::Get2D方法的典型用法代码示例。如果您正苦于以下问题:C++ Sampler::Get2D方法的具体用法?C++ Sampler::Get2D怎么用?C++ Sampler::Get2D使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Sampler
的用法示例。
在下文中一共展示了Sampler::Get2D方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: UniformSampleAllLights
// Integrator Utility Functions
Spectrum UniformSampleAllLights(const Interaction &it, const Scene &scene,
MemoryArena &arena, Sampler &sampler,
const std::vector<int> &nLightSamples,
bool handleMedia) {
ProfilePhase p(Prof::DirectLighting);
Spectrum L(0.f);
for (size_t j = 0; j < scene.lights.size(); ++j) {
// Accumulate contribution of _j_th light to _L_
const std::shared_ptr<Light> &light = scene.lights[j];
int nSamples = nLightSamples[j];
const Point2f *uLightArray = sampler.Get2DArray(nSamples);
const Point2f *uScatteringArray = sampler.Get2DArray(nSamples);
if (!uLightArray || !uScatteringArray) {
// Use a single sample for illumination from _light_
Point2f uLight = sampler.Get2D();
Point2f uScattering = sampler.Get2D();
L += EstimateDirect(it, uScattering, *light, uLight, scene, sampler,
arena, handleMedia);
} else {
// Estimate direct lighting using sample arrays
Spectrum Ld(0.f);
for (int k = 0; k < nSamples; ++k)
Ld += EstimateDirect(it, uScatteringArray[k], *light,
uLightArray[k], scene, sampler, arena,
handleMedia);
L += Ld / nSamples;
}
}
return L;
}
示例2: UniformSampleOneLight
Spectrum UniformSampleOneLight(const Interaction &it, const Scene &scene,
MemoryArena &arena, Sampler &sampler,
bool handleMedia) {
ProfilePhase p(Prof::DirectLighting);
// Randomly choose a single light to sample, _light_
int nLights = int(scene.lights.size());
if (nLights == 0) return Spectrum(0.f);
int lightNum = std::min((int)(sampler.Get1D() * nLights), nLights - 1);
const std::shared_ptr<Light> &light = scene.lights[lightNum];
Point2f uLight = sampler.Get2D();
Point2f uScattering = sampler.Get2D();
return (Float)nLights * EstimateDirect(it, uScattering, *light, uLight,
scene, sampler, arena, handleMedia);
}
示例3: GenerateLightSubpath
int GenerateLightSubpath(
const Scene &scene, Sampler &sampler, MemoryArena &arena, int maxDepth,
Float time, const Distribution1D &lightDistr,
const std::unordered_map<const Light *, size_t> &lightToIndex,
Vertex *path) {
if (maxDepth == 0) return 0;
// Sample initial ray for light subpath
Float lightPdf;
int lightNum = lightDistr.SampleDiscrete(sampler.Get1D(), &lightPdf);
const std::shared_ptr<Light> &light = scene.lights[lightNum];
RayDifferential ray;
Normal3f nLight;
Float pdfPos, pdfDir;
Spectrum Le = light->Sample_Le(sampler.Get2D(), sampler.Get2D(), time, &ray,
&nLight, &pdfPos, &pdfDir);
if (pdfPos == 0 || pdfDir == 0 || Le.IsBlack()) return 0;
// Generate first vertex on light subpath and start random walk
path[0] =
Vertex::CreateLight(light.get(), ray, nLight, Le, pdfPos * lightPdf);
Spectrum beta = Le * AbsDot(nLight, ray.d) / (lightPdf * pdfPos * pdfDir);
VLOG(2) << "Starting light subpath. Ray: " << ray << ", Le " << Le <<
", beta " << beta << ", pdfPos " << pdfPos << ", pdfDir " << pdfDir;
int nVertices =
RandomWalk(scene, ray, sampler, arena, beta, pdfDir, maxDepth - 1,
TransportMode::Importance, path + 1);
// Correct subpath sampling densities for infinite area lights
if (path[0].IsInfiniteLight()) {
// Set spatial density of _path[1]_ for infinite area light
if (nVertices > 0) {
path[1].pdfFwd = pdfPos;
if (path[1].IsOnSurface())
path[1].pdfFwd *= AbsDot(ray.d, path[1].ng());
}
// Set spatial density of _path[0]_ for infinite area light
path[0].pdfFwd =
InfiniteLightDensity(scene, lightDistr, lightToIndex, ray.d);
}
return nVertices + 1;
}
示例4: GenerateLightSubpath
int GenerateLightSubpath(const Scene &scene, Sampler &sampler,
MemoryArena &arena, int maxdepth, Float time,
const Distribution1D &lightDistr, Vertex *path) {
if (maxdepth == 0) return 0;
// Sample initial ray for light subpath
Float lightPdf;
int lightNum = lightDistr.SampleDiscrete(sampler.Get1D(), &lightPdf);
const std::shared_ptr<Light> &light = scene.lights[lightNum];
RayDifferential ray;
Normal3f Nl;
Float pdfPos, pdfDir;
Spectrum Le = light->Sample_L(sampler.Get2D(), sampler.Get2D(), time, &ray,
&Nl, &pdfPos, &pdfDir);
if (pdfPos == 0.f || pdfDir == 0.f || Le.IsBlack()) return 0;
// Generate first vertex on light subpath and start random walk
Spectrum weight = Le * AbsDot(Nl, ray.d) / (lightPdf * pdfPos * pdfDir);
path[0] = Vertex(VertexType::Light,
EndpointInteraction(light.get(), ray, Nl), Le);
path[0].pdfFwd = pdfPos * lightPdf;
int nvertices =
RandomWalk(scene, ray, sampler, arena, weight, pdfDir, maxdepth - 1,
TransportMode::Importance, path + 1);
// Correct sampling densities for infinite area lights
if (path[0].IsInfiniteLight()) {
// Set positional density of _path[1]_
if (nvertices > 0) {
path[1].pdfFwd = pdfPos;
if (path[1].IsOnSurface())
path[1].pdfFwd *= AbsDot(ray.d, path[1].GetGeoNormal());
}
// Set positional density of _path[0]_
path[0].pdfFwd = InfiniteLightDensity(scene, lightDistr, ray.d);
}
return nvertices + 1;
}
示例5: 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;
}
示例6: 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;
}
示例7: GenerateCameraSubpath
int GenerateCameraSubpath(const Scene &scene, Sampler &sampler,
MemoryArena &arena, int maxDepth,
const Camera &camera, Point2f &pFilm, Vertex *path) {
if (maxDepth == 0) return 0;
// Sample initial ray for camera subpath
CameraSample cameraSample;
cameraSample.pFilm = pFilm;
cameraSample.time = sampler.Get1D();
cameraSample.pLens = sampler.Get2D();
RayDifferential ray;
Spectrum beta = camera.GenerateRayDifferential(cameraSample, &ray);
ray.ScaleDifferentials(1 / std::sqrt(sampler.samplesPerPixel));
// Generate first vertex on camera subpath and start random walk
Float pdfPos, pdfDir;
path[0] = Vertex::CreateCamera(&camera, ray, beta);
camera.Pdf_We(ray, &pdfPos, &pdfDir);
return RandomWalk(scene, ray, sampler, arena, beta, pdfDir, maxDepth - 1,
TransportMode::Radiance, path + 1) +
1;
}
示例8: GenerateCameraSubpath
int GenerateCameraSubpath(const Scene &scene, Sampler &sampler,
MemoryArena &arena, int maxdepth,
const Camera &camera, Point2f &rasterPos,
Vertex *path) {
if (maxdepth == 0) return 0;
// Sample initial ray for camera subpath
CameraSample cameraSample;
cameraSample.pFilm = rasterPos;
cameraSample.time = sampler.Get1D();
cameraSample.pLens = sampler.Get2D();
RayDifferential ray;
Spectrum rayWeight(camera.GenerateRayDifferential(cameraSample, &ray));
ray.ScaleDifferentials(1.f / std::sqrt(sampler.samplesPerPixel));
// Generate first vertex on camera subpath and start random walk
path[0] = Vertex(VertexType::Camera, EndpointInteraction(&camera, ray),
Spectrum(1.0f));
return RandomWalk(scene, ray, sampler, arena, rayWeight,
camera.Pdf(path[0].ei, ray.d), maxdepth - 1,
TransportMode::Radiance, path + 1) +
1;
}
示例9: 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);
}
示例10: 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;
//.........这里部分代码省略.........
示例11: 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;
}
示例12: 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);
//.........这里部分代码省略.........
示例13: ConnectBDPT
Spectrum ConnectBDPT(const Scene &scene, Vertex *lightSubpath,
Vertex *cameraSubpath, int s, int t,
const Distribution1D &lightDistr, const Camera &camera,
Sampler &sampler, Point2f *rasterPos, Float *misWeight) {
Spectrum weight(0.f);
// Ignore invalid connections related to infinite area lights
if (t > 1 && s != 0 && cameraSubpath[t - 1].type == VertexType::Light)
return Spectrum(0.f);
// Perform connection and write contribution to _weight_
Vertex sampled;
if (s == 0) {
// Interpret the camera subpath as a complete path
const Vertex &pt = cameraSubpath[t - 1];
if (pt.IsLight()) {
const Vertex &ptMinus = cameraSubpath[t - 2];
weight = pt.Le(scene, ptMinus) * pt.weight;
}
} else if (t == 1) {
// Sample a point on the camera and connect it to the light subpath
const Vertex &qs = lightSubpath[s - 1];
if (qs.IsConnectible()) {
VisibilityTester vis;
Vector3f wi;
Float pdf;
Spectrum cameraWeight =
camera.Sample_We(qs.GetInteraction(), sampler.Get2D(), &wi,
&pdf, rasterPos, &vis);
if (pdf > 0 && !cameraWeight.IsBlack()) {
// Initialize dynamically sampled vertex and _weight_
sampled = Vertex(VertexType::Camera,
EndpointInteraction(vis.P1(), &camera),
cameraWeight);
weight = qs.weight * qs.f(sampled) * vis.T(scene, sampler) *
sampled.weight;
if (qs.IsOnSurface())
weight *= AbsDot(wi, qs.GetShadingNormal());
}
}
} else if (s == 1) {
// Sample a point on a light and connect it to the camera subpath
const Vertex &pt = cameraSubpath[t - 1];
if (pt.IsConnectible()) {
Float lightPdf;
VisibilityTester vis;
Vector3f wi;
Float pdf;
int lightNum =
lightDistr.SampleDiscrete(sampler.Get1D(), &lightPdf);
const std::shared_ptr<Light> &light = scene.lights[lightNum];
Spectrum lightWeight = light->Sample_L(
pt.GetInteraction(), sampler.Get2D(), &wi, &pdf, &vis);
if (pdf > 0 && !lightWeight.IsBlack()) {
sampled = Vertex(VertexType::Light,
EndpointInteraction(vis.P1(), light.get()),
lightWeight / (pdf * lightPdf));
sampled.pdfFwd = sampled.PdfLightOrigin(scene, pt, lightDistr);
weight = pt.weight * pt.f(sampled) * vis.T(scene, sampler) *
sampled.weight;
if (pt.IsOnSurface())
weight *= AbsDot(wi, pt.GetShadingNormal());
}
}
} else {
// Handle all other cases
const Vertex &qs = lightSubpath[s - 1], &pt = cameraSubpath[t - 1];
if (qs.IsConnectible() && pt.IsConnectible()) {
weight = qs.weight * qs.f(pt) *
GeometryTerm(scene, sampler, qs, pt) * pt.f(qs) *
pt.weight;
}
}
// Compute MIS weight for connection strategy
*misWeight =
weight.IsBlack() ? 0.f : MISWeight(scene, lightSubpath, cameraSubpath,
sampled, s, t, lightDistr);
return weight;
}
示例14: ConnectBDPT
Spectrum ConnectBDPT(
const Scene &scene, Vertex *lightVertices, Vertex *cameraVertices, int s,
int t, const Distribution1D &lightDistr,
const std::unordered_map<const Light *, size_t> &lightToIndex,
const Camera &camera, Sampler &sampler, Point2f *pRaster,
Float *misWeightPtr) {
Spectrum L(0.f);
// Ignore invalid connections related to infinite area lights
if (t > 1 && s != 0 && cameraVertices[t - 1].type == VertexType::Light)
return Spectrum(0.f);
// Perform connection and write contribution to _L_
Vertex sampled;
if (s == 0) {
// Interpret the camera subpath as a complete path
const Vertex &pt = cameraVertices[t - 1];
if (pt.IsLight()) L = pt.Le(scene, cameraVertices[t - 2]) * pt.beta;
DCHECK(!L.HasNaNs());
} else if (t == 1) {
// Sample a point on the camera and connect it to the light subpath
const Vertex &qs = lightVertices[s - 1];
if (qs.IsConnectible()) {
VisibilityTester vis;
Vector3f wi;
Float pdf;
Spectrum Wi = camera.Sample_Wi(qs.GetInteraction(), sampler.Get2D(),
&wi, &pdf, pRaster, &vis);
if (pdf > 0 && !Wi.IsBlack()) {
// Initialize dynamically sampled vertex and _L_ for $t=1$ case
sampled = Vertex::CreateCamera(&camera, vis.P1(), Wi / pdf);
L = qs.beta * qs.f(sampled, TransportMode::Importance) * sampled.beta;
if (qs.IsOnSurface()) L *= AbsDot(wi, qs.ns());
DCHECK(!L.HasNaNs());
// Only check visibility after we know that the path would
// make a non-zero contribution.
if (!L.IsBlack()) L *= vis.Tr(scene, sampler);
}
}
} else if (s == 1) {
// Sample a point on a light and connect it to the camera subpath
const Vertex &pt = cameraVertices[t - 1];
if (pt.IsConnectible()) {
Float lightPdf;
VisibilityTester vis;
Vector3f wi;
Float pdf;
int lightNum =
lightDistr.SampleDiscrete(sampler.Get1D(), &lightPdf);
const std::shared_ptr<Light> &light = scene.lights[lightNum];
Spectrum lightWeight = light->Sample_Li(
pt.GetInteraction(), sampler.Get2D(), &wi, &pdf, &vis);
if (pdf > 0 && !lightWeight.IsBlack()) {
EndpointInteraction ei(vis.P1(), light.get());
sampled =
Vertex::CreateLight(ei, lightWeight / (pdf * lightPdf), 0);
sampled.pdfFwd =
sampled.PdfLightOrigin(scene, pt, lightDistr, lightToIndex);
L = pt.beta * pt.f(sampled, TransportMode::Radiance) * sampled.beta;
if (pt.IsOnSurface()) L *= AbsDot(wi, pt.ns());
// Only check visibility if the path would carry radiance.
if (!L.IsBlack()) L *= vis.Tr(scene, sampler);
}
}
} else {
// Handle all other bidirectional connection cases
const Vertex &qs = lightVertices[s - 1], &pt = cameraVertices[t - 1];
if (qs.IsConnectible() && pt.IsConnectible()) {
L = qs.beta * qs.f(pt, TransportMode::Importance) * pt.f(qs, TransportMode::Radiance) * pt.beta;
VLOG(2) << "General connect s: " << s << ", t: " << t <<
" qs: " << qs << ", pt: " << pt << ", qs.f(pt): " << qs.f(pt, TransportMode::Importance) <<
", pt.f(qs): " << pt.f(qs, TransportMode::Radiance) << ", G: " << G(scene, sampler, qs, pt) <<
", dist^2: " << DistanceSquared(qs.p(), pt.p());
if (!L.IsBlack()) L *= G(scene, sampler, qs, pt);
}
}
++totalPaths;
if (L.IsBlack()) ++zeroRadiancePaths;
ReportValue(pathLength, s + t - 2);
// Compute MIS weight for connection strategy
Float misWeight =
L.IsBlack() ? 0.f : MISWeight(scene, lightVertices, cameraVertices,
sampled, s, t, lightDistr, lightToIndex);
VLOG(2) << "MIS weight for (s,t) = (" << s << ", " << t << ") connection: "
<< misWeight;
DCHECK(!std::isnan(misWeight));
L *= misWeight;
if (misWeightPtr) *misWeightPtr = misWeight;
return L;
}
示例15: 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;
}