提交 452bb7cc 编写于 作者: M Matt Pharr

GPU/wavefront integrator: don't hard-code HenyeyGreenstein as the only phase function.

Now a MultiWorkQueue templated on the phase function type is used for
enqueuing work items for sampling direct/indirect lighting in media.  With
Henyey-Greenstein as the only phase function currently available, this
reduces to the previous behavior, but it makes it easier to add new phase
functions in the future.

Also piped through time in a few places it was missing in the
medium-related work queues.
上级 e33843b4
...@@ -59,6 +59,8 @@ class HGPhaseFunction { ...@@ -59,6 +59,8 @@ class HGPhaseFunction {
PBRT_CPU_GPU PBRT_CPU_GPU
Float PDF(Vector3f wo, Vector3f wi) const { return p(wo, wi); } Float PDF(Vector3f wo, Vector3f wi) const { return p(wo, wi); }
static const char *Name() { return "Henyey-Greenstein"; }
std::string ToString() const; std::string ToString() const;
private: private:
......
...@@ -285,7 +285,14 @@ WavefrontPathIntegrator::WavefrontPathIntegrator(Allocator alloc, ParsedScene &s ...@@ -285,7 +285,14 @@ WavefrontPathIntegrator::WavefrontPathIntegrator(Allocator alloc, ParsedScene &s
if (haveMedia) { if (haveMedia) {
mediumSampleQueue = alloc.new_object<MediumSampleQueue>(maxQueueSize, alloc); mediumSampleQueue = alloc.new_object<MediumSampleQueue>(maxQueueSize, alloc);
mediumScatterQueue = alloc.new_object<MediumScatterQueue>(maxQueueSize, alloc);
// TODO: in the presence of multiple PhaseFunction implementations,
// it could be worthwhile to see which are present in the scene and
// then initialize havePhase accordingly...
pstd::array<bool, PhaseFunction::NumTags()> havePhase;
havePhase.fill(true);
mediumScatterQueue =
alloc.new_object<MediumScatterQueue>(maxQueueSize, alloc, havePhase);
} }
stats = alloc.new_object<Stats>(maxDepth, alloc); stats = alloc.new_object<Stats>(maxDepth, alloc);
......
...@@ -67,6 +67,8 @@ class WavefrontPathIntegrator { ...@@ -67,6 +67,8 @@ class WavefrontPathIntegrator {
void TraceShadowRays(int depth); void TraceShadowRays(int depth);
void SampleMediumInteraction(int depth); void SampleMediumInteraction(int depth);
template <typename PhaseFunction>
void SampleMediumScattering(int depth);
void SampleSubsurface(int depth); void SampleSubsurface(int depth);
void HandleEscapedRays(int depth); void HandleEscapedRays(int depth);
......
...@@ -32,6 +32,16 @@ static inline void rescale(SampledSpectrum &T_hat, SampledSpectrum &lightPathPDF ...@@ -32,6 +32,16 @@ static inline void rescale(SampledSpectrum &T_hat, SampledSpectrum &lightPathPDF
} }
} }
struct SampleMediumScatteringCallback {
int depth;
WavefrontPathIntegrator *integrator;
template <typename PhaseFunction>
void operator()() {
integrator->SampleMediumScattering<PhaseFunction>(depth);
}
};
// WavefrontPathIntegrator Participating Media Methods // WavefrontPathIntegrator Participating Media Methods
void WavefrontPathIntegrator::SampleMediumInteraction(int depth) { void WavefrontPathIntegrator::SampleMediumInteraction(int depth) {
RayQueue *nextRayQueue = NextRayQueue(depth); RayQueue *nextRayQueue = NextRayQueue(depth);
...@@ -114,13 +124,16 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -114,13 +124,16 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) {
T_hat *= T_maj * sigma_s; T_hat *= T_maj * sigma_s;
uniPathPDF *= T_maj * sigma_s; uniPathPDF *= T_maj * sigma_s;
// TODO: don't hard code a phase function.
const HGPhaseFunction *phase =
intr.phase.CastOrNullptr<HGPhaseFunction>();
// Enqueue medium scattering work. // Enqueue medium scattering work.
mediumScatterQueue->Push(MediumScatterWorkItem{ auto enqueue = [=](auto ptr) {
intr.p(), lambda, T_hat, uniPathPDF, *phase, -ray.d, using PhaseFunction =
w.etaScale, ray.medium, w.pixelIndex}); typename std::remove_reference_t<decltype(*ptr)>;
mediumScatterQueue->Push(MediumScatterWorkItem<PhaseFunction>{
intr.p(), lambda, T_hat, uniPathPDF, ptr, -ray.d,
ray.time, w.etaScale, ray.medium, w.pixelIndex});
};
intr.phase.Dispatch(enqueue);
scattered = true; scattered = true;
return false; return false;
...@@ -183,7 +196,7 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -183,7 +196,7 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) {
const MixMaterial *mix = material.CastOrNullptr<MixMaterial>(); const MixMaterial *mix = material.CastOrNullptr<MixMaterial>();
while (mix) { while (mix) {
SurfaceInteraction intr(w.pi, w.uv, w.wo, w.dpdus, w.dpdvs, w.dndus, SurfaceInteraction intr(w.pi, w.uv, w.wo, w.dpdus, w.dpdvs, w.dndus,
w.dndvs, 0. /* time */, false /* flip normal */); w.dndvs, ray.time, false /* flip normal */);
intr.faceIndex = w.faceIndex; intr.faceIndex = w.faceIndex;
MaterialEvalContext ctx(intr); MaterialEvalContext ctx(intr);
material = mix->ChooseMaterial(BasicTextureEvaluator(), ctx); material = mix->ChooseMaterial(BasicTextureEvaluator(), ctx);
...@@ -236,15 +249,20 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -236,15 +249,20 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) {
if (depth == maxDepth) if (depth == maxDepth)
return; return;
ForEachType(SampleMediumScatteringCallback{depth, this}, PhaseFunction::Types());
}
template <typename Phase>
void WavefrontPathIntegrator::SampleMediumScattering(int depth) {
RayQueue *currentRayQueue = CurrentRayQueue(depth); RayQueue *currentRayQueue = CurrentRayQueue(depth);
RayQueue *nextRayQueue = NextRayQueue(depth);
using PhaseFunction = HGPhaseFunction; std::string desc = std::string("Sample direct/indirect - ") + Phase::Name();
std::string desc = std::string("Sample direct/indirect - Henyey Greenstein"); ForAllQueued(desc.c_str(),
ForAllQueued( mediumScatterQueue->Get<MediumScatterWorkItem<Phase>>(),
desc.c_str(), mediumScatterQueue, maxQueueSize, maxQueueSize,
PBRT_CPU_GPU_LAMBDA(MediumScatterWorkItem w) { PBRT_CPU_GPU_LAMBDA(const MediumScatterWorkItem<Phase> w) {
RaySamples raySamples = pixelSampleState.samples[w.pixelIndex]; RaySamples raySamples = pixelSampleState.samples[w.pixelIndex];
Float time = 0; // TODO: FIXME
Vector3f wo = w.wo; Vector3f wo = w.wo;
// Sample direct lighting at medium scattering event. First, // Sample direct lighting at medium scattering event. First,
...@@ -260,7 +278,7 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -260,7 +278,7 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) {
ctx, raySamples.direct.u, w.lambda, LightSamplingMode::WithMIS); ctx, raySamples.direct.u, w.lambda, LightSamplingMode::WithMIS);
if (ls && ls->L && ls->pdf > 0) { if (ls && ls->L && ls->pdf > 0) {
Vector3f wi = ls->wi; Vector3f wi = ls->wi;
SampledSpectrum T_hat = w.T_hat * w.phase.p(wo, wi); SampledSpectrum T_hat = w.T_hat * w.phase->p(wo, wi);
PBRT_DBG("Phase phase T_hat %f %f %f %f\n", T_hat[0], T_hat[1], PBRT_DBG("Phase phase T_hat %f %f %f %f\n", T_hat[0], T_hat[1],
T_hat[2], T_hat[3]); T_hat[2], T_hat[3]);
...@@ -268,12 +286,12 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -268,12 +286,12 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) {
// Compute PDFs for direct lighting MIS calculation. // Compute PDFs for direct lighting MIS calculation.
Float lightPDF = ls->pdf * sampledLight->pdf; Float lightPDF = ls->pdf * sampledLight->pdf;
Float phasePDF = Float phasePDF =
IsDeltaLight(light.Type()) ? 0.f : w.phase.PDF(wo, wi); IsDeltaLight(light.Type()) ? 0.f : w.phase->PDF(wo, wi);
SampledSpectrum uniPathPDF = w.uniPathPDF * phasePDF; SampledSpectrum uniPathPDF = w.uniPathPDF * phasePDF;
SampledSpectrum lightPathPDF = w.uniPathPDF * lightPDF; SampledSpectrum lightPathPDF = w.uniPathPDF * lightPDF;
SampledSpectrum Ld = T_hat * ls->L; SampledSpectrum Ld = T_hat * ls->L;
Ray ray(w.p, ls->pLight.p() - w.p, time, w.medium); Ray ray(w.p, ls->pLight.p() - w.p, w.time, w.medium);
// Enqueue shadow ray // Enqueue shadow ray
shadowRayQueue->Push(ray, 1 - ShadowEpsilon, w.lambda, Ld, uniPathPDF, shadowRayQueue->Push(ray, 1 - ShadowEpsilon, w.lambda, Ld, uniPathPDF,
...@@ -291,7 +309,7 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -291,7 +309,7 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) {
// Sample indirect lighting. // Sample indirect lighting.
pstd::optional<PhaseFunctionSample> phaseSample = pstd::optional<PhaseFunctionSample> phaseSample =
w.phase.Sample_p(wo, raySamples.indirect.u); w.phase->Sample_p(wo, raySamples.indirect.u);
if (!phaseSample || phaseSample->pdf == 0) if (!phaseSample || phaseSample->pdf == 0)
return; return;
...@@ -315,7 +333,7 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) { ...@@ -315,7 +333,7 @@ void WavefrontPathIntegrator::SampleMediumInteraction(int depth) {
lightPathPDF *= 1 - q; lightPathPDF *= 1 - q;
} }
Ray ray(w.p, phaseSample->wi, time, w.medium); Ray ray(w.p, phaseSample->wi, w.time, w.medium);
bool isSpecularBounce = false; bool isSpecularBounce = false;
bool anyNonSpecularBounces = true; bool anyNonSpecularBounces = true;
......
...@@ -258,12 +258,14 @@ struct MediumSampleWorkItem { ...@@ -258,12 +258,14 @@ struct MediumSampleWorkItem {
}; };
// MediumScatterWorkItem Definition // MediumScatterWorkItem Definition
template <typename PhaseFunction>
struct MediumScatterWorkItem { struct MediumScatterWorkItem {
Point3f p; Point3f p;
SampledWavelengths lambda; SampledWavelengths lambda;
SampledSpectrum T_hat, uniPathPDF; SampledSpectrum T_hat, uniPathPDF;
HGPhaseFunction phase; const PhaseFunction *phase;
Vector3f wo; Vector3f wo;
Float time;
Float etaScale; Float etaScale;
Medium medium; Medium medium;
int pixelIndex; int pixelIndex;
...@@ -469,7 +471,8 @@ class MediumSampleQueue : public WorkQueue<MediumSampleWorkItem> { ...@@ -469,7 +471,8 @@ class MediumSampleQueue : public WorkQueue<MediumSampleWorkItem> {
}; };
// MediumScatterQueue Definition // MediumScatterQueue Definition
using MediumScatterQueue = WorkQueue<MediumScatterWorkItem>; using MediumScatterQueue = MultiWorkQueue<
typename MapType<MediumScatterWorkItem, typename PhaseFunction::Types>::type>;
// MaterialEvalQueue Definition // MaterialEvalQueue Definition
using MaterialEvalQueue = MultiWorkQueue< using MaterialEvalQueue = MultiWorkQueue<
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
// SPDX: Apache-2.0 // SPDX: Apache-2.0
flat Float; flat Float;
flat HGPhaseFunction; flat PhaseFunction;
flat Light; flat Light;
flat Material; flat Material;
flat Medium; flat Medium;
...@@ -137,12 +137,13 @@ soa MediumSampleWorkItem { ...@@ -137,12 +137,13 @@ soa MediumSampleWorkItem {
MediumInterface mediumInterface; MediumInterface mediumInterface;
}; };
soa MediumScatterWorkItem { soa MediumScatterWorkItem<PhaseFunction> {
Point3f p; Point3f p;
SampledWavelengths lambda; SampledWavelengths lambda;
SampledSpectrum T_hat, uniPathPDF; SampledSpectrum T_hat, uniPathPDF;
HGPhaseFunction phase; const PhaseFunction *phase;
Vector3f wo; Vector3f wo;
Float time;
Float etaScale; Float etaScale;
Medium medium; Medium medium;
int pixelIndex; int pixelIndex;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册