提交 a7d44bb1 编写于 作者: M Matt Pharr

Update from book source. No meaningful changes to functionality.

上级 ca917943
......@@ -580,10 +580,9 @@ void LightPathIntegrator::EvaluatePixelSample(const Point2i &pPixel, int sampleI
// Sample point on light source for light path
Float time = camera.SampleTime(sampler.Get1D());
const Point2f uv0Light(sampler.Get2D());
const Point2f uv1Light(sampler.Get2D());
pstd::optional<LightLeSample> les =
light.SampleLe(uv0Light, uv1Light, lambda, time);
Point2f ul0 = sampler.Get2D();
Point2f ul1 = sampler.Get2D();
pstd::optional<LightLeSample> les = light.SampleLe(ul0, ul1, lambda, time);
if (!les || les->pdfPos == 0 || les->pdfDir == 0 || !les->L)
return;
......@@ -898,9 +897,9 @@ SampledSpectrum SimpleVolPathIntegrator::Li(RayDifferential ray,
bool scattered = false, terminated = false;
if (ray.medium) {
// Sample medium scattering using delta tracking
const Float h0 = Hash(sampler.Get1D());
const Float h1 = Hash(sampler.Get1D());
RNG rng(h0, h1);
uint64_t hash0 = Hash(sampler.Get1D());
uint64_t hash1 = Hash(sampler.Get1D());
RNG rng(hash0, hash1);
Float tMax = si ? si->tHit : Infinity;
ray.medium.SampleTmaj(ray, tMax, rng, lambda, [&](const MediumSample &ms) {
const MediumInteraction &intr = ms.intr;
......@@ -964,9 +963,9 @@ SampledSpectrum SimpleVolPathIntegrator::Li(RayDifferential ray,
if (!bsdf)
si->intr.SkipIntersection(&ray, si->tHit);
else {
const Float uBSDF = sampler.Get1D();
const Point2f vwBSDF = sampler.Get2D();
if (bsdf.Sample_f(-ray.d, uBSDF, vwBSDF))
Float uc = sampler.Get1D();
Point2f u = sampler.Get2D();
if (bsdf.Sample_f(-ray.d, uc, u))
ErrorExit("SimpleVolPathIntegrator doesn't support surface scattering.");
else
break;
......@@ -1014,9 +1013,9 @@ SampledSpectrum VolPathIntegrator::Li(RayDifferential ray, SampledWavelengths &l
// Sample the participating medium
bool scattered = false, terminated = false;
Float tMax = si ? si->tHit : Infinity;
const Float h0 = Hash(sampler.Get1D());
const Float h1 = Hash(sampler.Get1D());
RNG rng(h0, h1);
uint64_t hash0 = Hash(sampler.Get1D());
uint64_t hash1 = Hash(sampler.Get1D());
RNG rng(hash0, hash1);
SampledSpectrum Tmaj = ray.medium.SampleTmaj(
ray, tMax, rng, lambda, [&](const MediumSample &mediumSample) {
// Handle medium scattering event for ray
......@@ -1227,10 +1226,9 @@ SampledSpectrum VolPathIntegrator::Li(RayDifferential ray, SampledWavelengths &l
BSSRDFHandle bssrdf = isect.GetBSSRDF(ray, lambda, camera, scratchBuffer);
if (bssrdf && bs->IsTransmission()) {
// Sample BSSRDF probe segment to find exit point
const Float uBSSRDF = sampler.Get1D();
const Point2f vwBSSRDF = sampler.Get2D();
pstd::optional<BSSRDFProbeSegment> probeSeg =
bssrdf.SampleSp(sampler.Get1D(), sampler.Get2D());
Float uc = sampler.Get1D();
Point2f up = sampler.Get2D();
pstd::optional<BSSRDFProbeSegment> probeSeg = bssrdf.SampleSp(uc, up);
if (!probeSeg)
break;
......@@ -1963,10 +1961,9 @@ int GenerateLightSubpath(const Integrator &integrator, SampledWavelengths &lambd
LightHandle light = sampledLight->light;
Float lightSamplePDF = sampledLight->pdf;
const Point2f uv0Light(sampler.Get2D());
const Point2f uv1Light(sampler.Get2D());
pstd::optional<LightLeSample> les =
light.SampleLe(uv0Light, uv1Light, lambda, time);
Point2f ul0 = sampler.Get2D();
Point2f ul1 = sampler.Get2D();
pstd::optional<LightLeSample> les = light.SampleLe(ul0, ul1, lambda, time);
if (!les || les->pdfPos == 0 || les->pdfDir == 0 || !les->L)
return 0;
RayDifferential ray(les->ray);
......
......@@ -178,10 +178,10 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) {
Interaction intr(w.pi, w.n);
intr.mediumInterface = &w.mediumInterface;
Ray newRay = intr.SpawnRay(ray.d);
nextRayQueue->PushIndirect(newRay, w.prevIntrCtx, T_hat, uniPathPDF,
lightPathPDF, lambda, w.etaScale,
w.isSpecularBounce, w.anyNonSpecularBounces,
w.pixelIndex);
nextRayQueue->PushIndirectRay(newRay, w.prevIntrCtx, T_hat, uniPathPDF,
lightPathPDF, lambda, w.etaScale,
w.isSpecularBounce, w.anyNonSpecularBounces,
w.pixelIndex);
return;
}
......@@ -303,9 +303,9 @@ void GPUPathIntegrator::SampleMediumInteraction(int depth) {
bool anyNonSpecularBounces = true;
// Spawn indirect ray.
nextRayQueue->PushIndirect(ray, ctx, T_hat, uniPathPDF, lightPathPDF,
w.lambda, w.etaScale, isSpecularBounce,
anyNonSpecularBounces, w.pixelIndex);
nextRayQueue->PushIndirectRay(ray, ctx, T_hat, uniPathPDF, lightPathPDF,
w.lambda, w.etaScale, isSpecularBounce,
anyNonSpecularBounces, w.pixelIndex);
PBRT_DBG("Enqueuing indirect medium ray at depth %d pixel index %d\n",
depth + 1, w.pixelIndex);
});
......
......@@ -346,7 +346,7 @@ void GPUPathIntegrator::Render() {
// Trace rays and estimate radiance up to maximum ray depth
for (int depth = 0; true; ++depth) {
// Reset ray queues before tracing rays
// Reset queues before tracing rays
RayQueue *nextQueue = NextRayQueue(depth);
GPUDo(
"Reset queues before tracing rays", PBRT_GPU_LAMBDA() {
......@@ -476,7 +476,6 @@ void GPUPathIntegrator::HandleRayFoundEmission(int depth) {
"Handle emitters hit by indirect rays", hitAreaLightQueue, maxQueueSize,
PBRT_GPU_LAMBDA(const HitAreaLightWorkItem w, int index) {
// Find emitted radiance from surface that ray hit
LightHandle areaLight = w.areaLight;
SampledSpectrum Le = areaLight.L(w.p, w.n, w.uv, w.wo, w.lambda);
if (!Le)
return;
......@@ -490,16 +489,13 @@ void GPUPathIntegrator::HandleRayFoundEmission(int depth) {
} else {
// Compute MIS-weighted radiance contribution from area light
Vector3f wi = -w.wo;
LightSampleContext ctx = w.prevIntrCtx;
Float lightChoicePDF = lightSampler.PDF(ctx, areaLight);
Float lightChoicePDF = lightSampler.PDF(ctx, w.areaLight);
Float lightPDF = lightChoicePDF *
areaLight.PDF_Li(ctx, wi, LightSamplingMode::WithMIS);
w.areaLight.PDF_Li(ctx, wi, LightSamplingMode::WithMIS);
SampledSpectrum uniPathPDF = w.uniPathPDF;
SampledSpectrum lightPathPDF = w.lightPathPDF * lightPDF;
L = w.T_hat * Le / (uniPathPDF + lightPathPDF).Average();
}
L = SafeDiv(L, w.lambda.PDF());
......@@ -518,14 +514,12 @@ void GPUPathIntegrator::TraceShadowRays(int depth) {
accel->IntersectShadowTr(maxQueueSize, shadowRayQueue);
else
accel->IntersectShadow(maxQueueSize, shadowRayQueue);
// Add contribution if light was visible
// Add shadow ray radiance contributions to pixels
ForAllQueued(
"Incorporate shadow ray contribution", shadowRayQueue, maxQueueSize,
PBRT_GPU_LAMBDA(const ShadowRayWorkItem sr, int index) {
if (!sr.Ld)
return;
SampledSpectrum Lpixel = pixelSampleState.L[sr.pixelIndex];
PBRT_DBG("Adding shadow ray Ld %f %f %f %f at pixel index %d \n", sr.Ld[0],
......@@ -534,6 +528,7 @@ void GPUPathIntegrator::TraceShadowRays(int depth) {
pixelSampleState.L[sr.pixelIndex] = Lpixel + sr.Ld;
});
// Reset shadow ray queue
GPUDo(
"Reset shadowRayQueue", PBRT_GPU_LAMBDA() {
stats->shadowRays[depth] += shadowRayQueue->Size();
......
......@@ -96,6 +96,9 @@ class GPUPathIntegrator {
LightHandle envLight;
LightSamplerHandle lightSampler;
int maxDepth;
bool regularize;
int scanlinesPerPass, maxQueueSize;
SOA<PixelSampleState> pixelSampleState;
......@@ -105,9 +108,6 @@ class GPUPathIntegrator {
MediumSampleQueue *mediumSampleQueue = nullptr;
MediumScatterQueue *mediumScatterQueue = nullptr;
int maxDepth;
bool regularize;
EscapedRayQueue *escapedRayQueue = nullptr;
HitAreaLightQueue *hitAreaLightQueue = nullptr;
......
......@@ -24,7 +24,9 @@ void GPUPathIntegrator::GenerateRaySamples(int depth, int sampleIndex) {
template <typename Sampler>
void GPUPathIntegrator::GenerateRaySamples(int depth, int sampleIndex) {
// Generate description string _desc_ for ray sample generation
std::string desc = std::string("Generate ray samples - ") + Sampler::Name();
RayQueue *rayQueue = CurrentRayQueue(depth);
ForAllQueued(
desc.c_str(), rayQueue, maxQueueSize,
......
......@@ -125,10 +125,10 @@ void GPUPathIntegrator::SampleSubsurface(int depth) {
bool anyNonSpecularBounces = true;
LightSampleContext ctx(intr.pi, intr.n, intr.ns);
nextRayQueue->PushIndirect(ray, ctx, T_hat, uniPathPDF,
lightPathPDF, lambda, etaScale,
bsdfSample->IsSpecular(),
anyNonSpecularBounces, s.pixelIndex);
nextRayQueue->PushIndirectRay(
ray, ctx, T_hat, uniPathPDF, lightPathPDF, lambda, etaScale,
bsdfSample->IsSpecular(), anyNonSpecularBounces,
s.pixelIndex);
PBRT_DBG(
"Spawned indirect ray at depth %d. "
......
......@@ -192,10 +192,10 @@ void GPUPathIntegrator::EvaluateMaterialAndBSDF(TextureEvaluator texEval,
LightSampleContext ctx(
w.pi, w.n,
ns); // Note: slightly different than context below. Problem?
nextRayQueue->PushIndirect(ray, ctx, T_hat, uniPathPDF,
lightPathPDF, lambda, etaScale,
bsdfSample->IsSpecular(),
anyNonSpecularBounces, w.pixelIndex);
nextRayQueue->PushIndirectRay(
ray, ctx, T_hat, uniPathPDF, lightPathPDF, lambda, etaScale,
bsdfSample->IsSpecular(), anyNonSpecularBounces,
w.pixelIndex);
PBRT_DBG(
"Spawned indirect ray at depth %d from w.index %d. "
......@@ -214,7 +214,7 @@ void GPUPathIntegrator::EvaluateMaterialAndBSDF(TextureEvaluator texEval,
// Sample light and enqueue shadow ray at intersection point
if (bsdf.IsNonSpecular()) {
// Choose a light source using the LightSampler.
// Choose a light source using the _LightSampler_
LightSampleContext ctx(w.pi, w.n, ns);
if (bsdf.HasReflection() && !bsdf.HasTransmission())
ctx.pi = OffsetRayOrigin(ctx.pi, w.n, wo);
......@@ -229,18 +229,17 @@ void GPUPathIntegrator::EvaluateMaterialAndBSDF(TextureEvaluator texEval,
// Remarkably, this substantially improves L1 cache hits with
// CoatedDiffuseBxDF and gives about a 60% perf. benefit.
__syncthreads();
// And now sample the light source itself.
// Sample light source and evaluate BSDF for direct lighting
pstd::optional<LightLiSample> ls = light.SampleLi(
ctx, raySamples.direct.u, lambda, LightSamplingMode::WithMIS);
if (!ls || !ls->L || ls->pdf == 0)
return;
Vector3f wi = ls->wi;
SampledSpectrum f = bsdf.f<BxDF>(wo, wi);
if (!f)
return;
// Compute path throughput and path PDFs for light sample
SampledSpectrum T_hat = w.T_hat * f * AbsDot(wi, ns);
PBRT_DBG("w.T_hat %f %f %f %f f %f %f %f %f dot %f\n", w.T_hat[0],
w.T_hat[1], w.T_hat[2], w.T_hat[3], f[0], f[1], f[2], f[3],
......@@ -252,7 +251,6 @@ void GPUPathIntegrator::EvaluateMaterialAndBSDF(TextureEvaluator texEval,
index, depth, T_hat[0], T_hat[1], T_hat[2], T_hat[3], f[0], f[1],
f[2], f[3], ls->L[0], ls->L[1], ls->L[2], ls->L[3], ls->pdf);
// Compute light and BSDF PDFs for MIS.
Float lightPDF = ls->pdf * sampledLight->pdf;
// This causes uniPathPDF to be zero for the shadow ray, so that
// part of MIS just becomes a no-op.
......@@ -260,13 +258,12 @@ void GPUPathIntegrator::EvaluateMaterialAndBSDF(TextureEvaluator texEval,
SampledSpectrum uniPathPDF = w.uniPathPDF * bsdfPDF;
SampledSpectrum lightPathPDF = w.uniPathPDF * lightPDF;
// Enqueue shadow ray with tentative radiance contribution
SampledSpectrum Ld = SafeDiv(T_hat * ls->L, lambda.PDF());
Ray ray = SpawnRayTo(w.pi, w.n, w.time, ls->pLight.pi, ls->pLight.n);
if (haveMedia)
ray.medium = Dot(ray.d, w.n) > 0 ? w.mediumInterface.outside
: w.mediumInterface.inside;
shadowRayQueue->Push(ray, 1 - ShadowEpsilon, lambda, Ld, uniPathPDF,
lightPathPDF, w.pixelIndex);
......
......@@ -102,9 +102,9 @@ struct SOA<RaySamples> {
struct PixelSampleState {
// PixelSampleState Public Members
Point2i pPixel;
Float filterWeight;
SampledWavelengths lambda;
SampledSpectrum L;
SampledWavelengths lambda;
Float filterWeight;
VisibleSurface visibleSurface;
SampledSpectrum cameraRayWeight;
RaySamples samples;
......@@ -125,13 +125,14 @@ struct RayWorkItem {
// EscapedRayWorkItem Definition
struct EscapedRayWorkItem {
SampledSpectrum T_hat, uniPathPDF, lightPathPDF;
SampledWavelengths lambda;
// EscapedRayWorkItem Public Members
Point3f rayo;
Vector3f rayd;
LightSampleContext prevIntrCtx;
int specularBounce;
SampledWavelengths lambda;
int pixelIndex;
int specularBounce;
SampledSpectrum T_hat, uniPathPDF, lightPathPDF;
LightSampleContext prevIntrCtx;
};
// EscapedRayQueue Definition
......@@ -139,13 +140,14 @@ using EscapedRayQueue = WorkQueue<EscapedRayWorkItem>;
// HitAreaLightWorkItem Definition
struct HitAreaLightWorkItem {
// HitAreaLightWorkItem Public Members
LightHandle areaLight;
SampledWavelengths lambda;
SampledSpectrum T_hat, uniPathPDF, lightPathPDF;
Point3f p;
Normal3f n;
Point2f uv;
Vector3f wo;
SampledWavelengths lambda;
SampledSpectrum T_hat, uniPathPDF, lightPathPDF;
LightSampleContext prevIntrCtx;
int isSpecularBounce;
int pixelIndex;
......@@ -285,12 +287,13 @@ struct MaterialEvalWorkItem {
Point2f uv;
SampledWavelengths lambda;
int anyNonSpecularBounces;
SampledSpectrum T_hat, uniPathPDF;
Vector3f wo;
int pixelIndex;
SampledSpectrum T_hat, uniPathPDF;
MediumInterface mediumInterface;
Float time;
Float etaScale;
MediumInterface mediumInterface;
int pixelIndex;
Float time;
};
#include "gpu_workitems_soa.h"
......@@ -304,25 +307,12 @@ class RayQueue : public WorkQueue<RayWorkItem> {
int PushCameraRay(const Ray &ray, const SampledWavelengths &lambda, int pixelIndex);
PBRT_CPU_GPU
int PushIndirect(const Ray &ray, const LightSampleContext &prevIntrCtx,
const SampledSpectrum &T_hat, const SampledSpectrum &uniPathPDF,
const SampledSpectrum &lightPathPDF,
const SampledWavelengths &lambda, Float etaScale,
bool isSpecularBounce, bool anyNonSpecularBounces, int pixelIndex) {
int index = AllocateEntry();
DCHECK(!ray.HasNaN());
this->ray[index] = ray;
this->pixelIndex[index] = pixelIndex;
this->prevIntrCtx[index] = prevIntrCtx;
this->T_hat[index] = T_hat;
this->uniPathPDF[index] = uniPathPDF;
this->lightPathPDF[index] = lightPathPDF;
this->lambda[index] = lambda;
this->anyNonSpecularBounces[index] = anyNonSpecularBounces;
this->isSpecularBounce[index] = isSpecularBounce;
this->etaScale[index] = etaScale;
return index;
}
int PushIndirectRay(const Ray &ray, const LightSampleContext &prevIntrCtx,
const SampledSpectrum &T_hat, const SampledSpectrum &uniPathPDF,
const SampledSpectrum &lightPathPDF,
const SampledWavelengths &lambda, Float etaScale,
bool isSpecularBounce, bool anyNonSpecularBounces,
int pixelIndex);
};
// RayQueue Inline Methods
......@@ -342,11 +332,32 @@ inline int RayQueue::PushCameraRay(const Ray &ray, const SampledWavelengths &lam
return index;
}
PBRT_CPU_GPU
inline int RayQueue::PushIndirectRay(
const Ray &ray, const LightSampleContext &prevIntrCtx, const SampledSpectrum &T_hat,
const SampledSpectrum &uniPathPDF, const SampledSpectrum &lightPathPDF,
const SampledWavelengths &lambda, Float etaScale, bool isSpecularBounce,
bool anyNonSpecularBounces, int pixelIndex) {
int index = AllocateEntry();
DCHECK(!ray.HasNaN());
this->ray[index] = ray;
this->pixelIndex[index] = pixelIndex;
this->prevIntrCtx[index] = prevIntrCtx;
this->T_hat[index] = T_hat;
this->uniPathPDF[index] = uniPathPDF;
this->lightPathPDF[index] = lightPathPDF;
this->lambda[index] = lambda;
this->anyNonSpecularBounces[index] = anyNonSpecularBounces;
this->isSpecularBounce[index] = isSpecularBounce;
this->etaScale[index] = etaScale;
return index;
}
// ShadowRayQueue Definition
class ShadowRayQueue : public WorkQueue<ShadowRayWorkItem> {
public:
using WorkQueue::WorkQueue;
// ShadowRayQueue Public Methods
PBRT_CPU_GPU
void Push(const Ray &ray, Float tMax, SampledWavelengths lambda, SampledSpectrum Ld,
SampledSpectrum uniPathPDF, SampledSpectrum lightPathPDF, int pixelIndex) {
......
......@@ -105,7 +105,7 @@ class MultiWorkQueue;
template <>
class MultiWorkQueue<TypePack<>> {
public:
MultiWorkQueue(int n, Allocator alloc, pstd::span<const bool> haveType) {}
MultiWorkQueue(int, Allocator, pstd::span<const bool>) {}
};
template <typename T, typename... Ts>
......@@ -139,12 +139,12 @@ class MultiWorkQueue<TypePack<T, Ts...>> : public MultiWorkQueue<TypePack<Ts...>
return MultiWorkQueue<TypePack<Ts...>>::template Get<Tg>();
}
template <typename Tq>
PBRT_CPU_GPU int Push(Tq item) {
if constexpr (std::is_same_v<Tq, T>)
template <typename Tp>
PBRT_CPU_GPU int Push(Tp item) {
if constexpr (std::is_same_v<Tp, T>)
return q.Push(item);
else
return MultiWorkQueue<TypePack<Ts...>>::template Push<Tq>(item);
return MultiWorkQueue<TypePack<Ts...>>::template Push(item);
}
private:
......
......@@ -373,7 +373,7 @@ class SobolSampler {
Point2f Get2D() {
if (dimension + 1 >= NSobolDimensions)
dimension = 2;
Point2f u{SampleDimension(dimension), SampleDimension(dimension + 1)};
Point2f u(SampleDimension(dimension), SampleDimension(dimension + 1));
if (dimension == 0) {
// Remap Sobol$'$ dimensions used for pixel samples
for (int dim = 0; dim < 2; ++dim) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册