本文整理汇总了C++中Sampler::Get1D方法的典型用法代码示例。如果您正苦于以下问题:C++ Sampler::Get1D方法的具体用法?C++ Sampler::Get1D怎么用?C++ Sampler::Get1D使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Sampler
的用法示例。
在下文中一共展示了Sampler::Get1D方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: Sample
Spectrum GridDensityMedium::Sample(const Ray &_ray, Sampler &sampler,
MemoryArena &arena,
MediumInteraction *mi) const {
// Transform the ray into local coordinates and determine overlap interval
// [_tMin, tMax_]
const Bounds3f dataBounds(Point3f(0.f, 0.f, 0.f), Point3f(1.f, 1.f, 1.f));
Ray ray = WorldToMedium(
Ray(_ray.o, Normalize(_ray.d), _ray.tMax * _ray.d.Length()));
Float tMin, tMax;
if (!dataBounds.IntersectP(ray, &tMin, &tMax)) return Spectrum(1.f);
tMin = std::max(tMin, (Float)0.f);
tMax = std::min(tMax, ray.tMax);
if (tMin >= tMax) return Spectrum(1.f);
// Run Delta-Tracking iterations to sample a medium interaction
Float t = tMin;
while (true) {
t -= std::log(1 - sampler.Get1D()) * invMaxDensity;
if (t >= tMax) break;
Float density = Density(ray(t));
if (density * invMaxDensity * sigma_t > sampler.Get1D()) {
// Populate _mi_ with medium interaction information and return
PhaseFunction *phase = ARENA_ALLOC(arena, HenyeyGreenstein)(g);
*mi = MediumInteraction(_ray(t), -_ray.d, _ray.time, this, phase);
return sigma_s / sigma_t;
}
}
return Spectrum(1.0f);
}
示例2: Sample
Spectrum GridDensityMedium::Sample(const Ray &rWorld, Sampler &sampler,
MemoryArena &arena,
MediumInteraction *mi) const {
Ray ray = WorldToMedium(
Ray(rWorld.o, Normalize(rWorld.d), rWorld.tMax * rWorld.d.Length()));
// Compute $[\tmin, \tmax]$ interval of _ray_'s overlap with medium bounds
const Bounds3f b(Point3f(0, 0, 0), Point3f(1, 1, 1));
Float tMin, tMax;
if (!b.IntersectP(ray, &tMin, &tMax)) return Spectrum(1.f);
// Run delta-tracking iterations to sample a medium interaction
Float t = tMin;
while (true) {
t -= std::log(1 - sampler.Get1D()) * invMaxDensity;
if (t >= tMax) break;
if (Density(ray(t)) * invMaxDensity * sigma_t > sampler.Get1D()) {
// Populate _mi_ with medium interaction information and return
PhaseFunction *phase = ARENA_ALLOC(arena, HenyeyGreenstein)(g);
*mi = MediumInteraction(rWorld(t), -rWorld.d, rWorld.time, this,
phase);
return sigma_s / sigma_t;
}
}
return Spectrum(1.f);
}
示例3: 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);
}
示例4: Tr
Spectrum GridDensityMedium::Tr(const Ray &rWorld, Sampler &sampler) const {
Ray ray = WorldToMedium(
Ray(rWorld.o, Normalize(rWorld.d), rWorld.tMax * rWorld.d.Length()));
// Compute $[\tmin, \tmax]$ interval of _ray_'s overlap with medium bounds
const Bounds3f b(Point3f(0, 0, 0), Point3f(1, 1, 1));
Float tMin, tMax;
if (!b.IntersectP(ray, &tMin, &tMax)) return Spectrum(1.f);
// Perform ratio tracking to estimate the transmittance value
Float Tr = 1, t = tMin;
while (true) {
t += -std::log(1 - sampler.Get1D()) * invMaxDensity;
if (t >= tMax) break;
Float density = Density(ray(t));
Tr *= 1 - std::max((Float)0, sigma_t * density * invMaxDensity);
}
return Spectrum(Tr);
}
示例5: 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;
}
示例6: 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;
}
示例7: 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;
}
示例8: T
Spectrum GridDensityMedium::T(const Ray &_ray, Sampler &sampler) const {
// Transform the ray into local coordinates and determine overlap interval
// [_tMin, tMax_]
const Bounds3f dataBounds(Point3f(0.f, 0.f, 0.f), Point3f(1.f, 1.f, 1.f));
Ray ray = WorldToMedium(
Ray(_ray.o, Normalize(_ray.d), _ray.tMax * _ray.d.Length()));
Float tMin, tMax;
if (!dataBounds.IntersectP(ray, &tMin, &tMax)) return Spectrum(1.f);
tMin = std::max(tMin, (Float)0.f);
tMax = std::min(tMax, ray.tMax);
if (tMin >= tMax) return Spectrum(1.f);
Float tr = 1.f;
// Perform ratio tracking to estimate the transmittance value
Float t = tMin;
while (true) {
t -= std::log(1 - sampler.Get1D()) * invMaxDensity;
if (t >= tMax) break;
Float density = Density(ray(t));
tr *= 1.f - std::max((Float)0, sigma_t * density * invMaxDensity);
}
return Spectrum(tr);
}
示例9: 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;
}
示例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: ConnectBDPT
Spectrum ConnectBDPT(const Scene &scene, Vertex *lightVertices,
Vertex *cameraVertices, int s, int t,
const Distribution1D &lightDistr, 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;
} 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) * vis.Tr(scene, sampler) *
sampled.beta;
if (qs.IsOnSurface()) L *= AbsDot(wi, qs.ns());
}
}
} 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);
L = pt.beta * pt.f(sampled) * vis.Tr(scene, sampler) *
sampled.beta;
if (pt.IsOnSurface()) L *= AbsDot(wi, pt.ns());
}
}
} 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) * pt.f(qs) * pt.beta;
if (!L.IsBlack()) L *= G(scene, sampler, qs, pt);
}
}
// Compute MIS weight for connection strategy
Float misWeight =
L.IsBlack() ? 0.f : MISWeight(scene, lightVertices, cameraVertices,
sampled, s, t, lightDistr);
L *= misWeight;
if (misWeightPtr) *misWeightPtr = misWeight;
return L;
}