提交 6d1e06ce 编写于 作者: M Matt Pharr

Go back to pstd::optional for PhaseFunction Sample_p() return values

上级 232b4fdb
......@@ -19,10 +19,9 @@ namespace pbrt {
// PhaseFunctionSample Definition
struct PhaseFunctionSample {
PBRT_CPU_GPU operator bool() const { return pdf > 0; }
Float p;
Vector3f wi;
Float pdf = 0;
Float pdf;
};
// PhaseFunctionHandle Definition
......@@ -37,8 +36,8 @@ class PhaseFunctionHandle : public TaggedPointer<HGPhaseFunction> {
PBRT_CPU_GPU inline Float p(const Vector3f &wo, const Vector3f &wi) const;
PBRT_CPU_GPU inline PhaseFunctionSample Sample_p(const Vector3f &wo,
const Point2f &u) const;
PBRT_CPU_GPU inline pstd::optional<PhaseFunctionSample> Sample_p(
const Vector3f &wo, const Point2f &u) const;
PBRT_CPU_GPU inline Float PDF(const Vector3f &wo, const Vector3f &wi) const;
};
......
......@@ -820,11 +820,12 @@ beta /= AbsCosTheta(w);
f += beta * albedo * phase.p(-w, -wis->wi) * wt * te * betaExit;
// Sample phase function and update layered path state
PhaseFunctionSample ps = phase.Sample_p(-w, Point2f(r(), r()));
if (!ps || ps.wi.z == 0)
pstd::optional<PhaseFunctionSample> ps =
phase.Sample_p(-w, Point2f(r(), r()));
if (!ps || ps->pdf == 0 || ps->wi.z == 0)
continue;
beta *= albedo * ps.p / ps.pdf;
w = ps.wi;
beta *= albedo * ps->p / ps->pdf;
w = ps->wi;
z = zp;
if (!IsSpecular(exitInterface.Flags())) {
......@@ -833,8 +834,8 @@ beta /= AbsCosTheta(w);
if (fExit) {
Float exitPDF = exitInterface.PDF(
-w, wi, mode, BxDFReflTransFlags::Transmission);
Float weight = PowerHeuristic(1, ps.pdf, 1, exitPDF);
f += beta * Tr(zp - exitZ, ps.wi) * fExit * weight;
Float weight = PowerHeuristic(1, ps->pdf, 1, exitPDF);
f += beta * Tr(zp - exitZ, ps->wi) * fExit * weight;
}
}
......@@ -969,12 +970,13 @@ f *= AbsCosTheta(w) / sigma_t;
// include it when we leave a surface.
f /= AbsCosTheta(w);
#endif
PhaseFunctionSample ps = phase.Sample_p(-w, Point2f(r(), r()));
if (!ps || ps.wi.z == 0)
pstd::optional<PhaseFunctionSample> ps =
phase.Sample_p(-w, Point2f(r(), r()));
if (!ps || ps->pdf == 0 || ps->wi.z == 0)
return {};
f *= albedo * ps.p;
pdf *= ps.pdf;
w = ps.wi;
f *= albedo * ps->p;
pdf *= ps->pdf;
w = ps->wi;
z = zp;
continue;
......
......@@ -1047,20 +1047,20 @@ SampledSpectrum VolPathIntegrator::Li(RayDifferential ray, SampledWavelengths &l
lambda.PDF());
// Sample indirect lighting at volume scattering event
PhaseFunctionSample ps =
pstd::optional<PhaseFunctionSample> ps =
intr.phase.Sample_p(-ray.d, sampler.Get2D());
if (!ps) {
if (!ps || ps->pdf == 0) {
terminated = true;
return false;
}
// Update ray path state for indirect volume scattering
beta *= ps.p;
beta *= ps->p;
pdfNEE = pdfUni;
pdfUni *= ps.pdf;
pdfUni *= ps->pdf;
prevMediumIntr = intr;
prevSurfaceIntr.reset();
scattered = true;
ray = intr.SpawnRay(ps.wi);
ray = intr.SpawnRay(ps->wi);
specularBounce = false;
anyNonSpecularBounces = true;
......@@ -2029,15 +2029,15 @@ int RandomWalk(const Integrator &integrator, SampledWavelengths &lambda,
// Sample direction and compute reverse density at preceding
// vertex
PhaseFunctionSample ps =
pstd::optional<PhaseFunctionSample> ps =
intr.phase.Sample_p(-ray.d, sampler.Get2D());
if (!ps) {
if (!ps || ps->pdf == 0) {
terminated = true;
return false;
}
pdfFwd = pdfRev = ps.pdf;
beta *= ps.p / pdfFwd;
ray = intr.SpawnRay(ps.wi);
pdfFwd = pdfRev = ps->pdf;
beta *= ps->p / pdfFwd;
ray = intr.SpawnRay(ps->wi);
anyNonSpecularBounces = true;
// Compute reverse area density at preceding vertex
......
......@@ -281,13 +281,13 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) {
}
// Sample indirect lighting.
PhaseFunctionSample phaseSample =
pstd::optional<PhaseFunctionSample> phaseSample =
ms.phase.Sample_p(wo, raySamples.indirect.u);
if (!phaseSample)
if (!phaseSample || phaseSample->pdf == 0)
return;
SampledSpectrum beta = ms.beta * phaseSample.p;
SampledSpectrum pdfUni = ms.pdfUni * phaseSample.pdf;
SampledSpectrum beta = ms.beta * phaseSample->p;
SampledSpectrum pdfUni = ms.pdfUni * phaseSample->pdf;
SampledSpectrum pdfNEE = ms.pdfUni;
// Russian roulette
......@@ -306,7 +306,7 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) {
pdfNEE *= 1 - q;
}
Ray ray(ms.p, phaseSample.wi, time, ms.medium);
Ray ray(ms.p, phaseSample->wi, time, ms.medium);
bool isSpecularBounce = false;
bool anyNonSpecularBounces = true;
......
......@@ -50,7 +50,8 @@ class HGPhaseFunction {
}
PBRT_CPU_GPU
PhaseFunctionSample Sample_p(const Vector3f &wo, const Point2f &u) const {
pstd::optional<PhaseFunctionSample> Sample_p(const Vector3f &wo,
const Point2f &u) const {
Float pdf;
Vector3f wi = SampleHenyeyGreenstein(wo, g, u, &pdf);
return PhaseFunctionSample{pdf, wi, pdf};
......@@ -721,8 +722,8 @@ inline Float PhaseFunctionHandle::p(const Vector3f &wo, const Vector3f &wi) cons
return Dispatch(p);
}
inline PhaseFunctionSample PhaseFunctionHandle::Sample_p(const Vector3f &wo,
const Point2f &u) const {
inline pstd::optional<PhaseFunctionSample> PhaseFunctionHandle::Sample_p(
const Vector3f &wo, const Point2f &u) const {
auto sample = [&](auto ptr) { return ptr->Sample_p(wo, u); };
return Dispatch(sample);
}
......
......@@ -21,11 +21,11 @@ TEST(HenyeyGreenstein, SamplingMatch) {
SampleUniformSphere({rng.Uniform<Float>(), rng.Uniform<Float>()});
Point2f u{rng.Uniform<Float>(), rng.Uniform<Float>()};
auto ps = hg.Sample_p(wo, u);
EXPECT_TRUE(ps);
EXPECT_TRUE(ps.has_value());
// Phase function is normalized, and the sampling method should be
// exact.
EXPECT_EQ(ps.p, ps.pdf);
EXPECT_NEAR(ps.p, hg.p(wo, ps.wi), 1e-4f) << "Failure with g = " << g;
EXPECT_EQ(ps->p, ps->pdf);
EXPECT_NEAR(ps->p, hg.p(wo, ps->wi), 1e-4f) << "Failure with g = " << g;
}
}
}
......@@ -36,8 +36,8 @@ TEST(HenyeyGreenstein, SamplingOrientationForward) {
int nForward = 0, nBackward = 0;
for (Point2f u : Uniform2D(100)) {
auto ps = hg.Sample_p(wo, u);
EXPECT_TRUE(ps);
if (ps.wi.x > 0)
EXPECT_TRUE(ps.has_value());
if (ps->wi.x > 0)
++nForward;
else
++nBackward;
......@@ -52,8 +52,8 @@ TEST(HenyeyGreenstein, SamplingOrientationBackward) {
int nForward = 0, nBackward = 0;
for (Point2f u : Uniform2D(100)) {
auto ps = hg.Sample_p(wo, u);
EXPECT_TRUE(ps);
if (ps.wi.x > 0)
EXPECT_TRUE(ps.has_value());
if (ps->wi.x > 0)
++nForward;
else
++nBackward;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册