提交 251754af 编写于 作者: M Matt Pharr

Update from book source. No meaningful changes to functionality.

上级 262d4ceb
......@@ -24,7 +24,7 @@ class TabulatedBSSRDF;
class BSSRDFHandle : public TaggedPointer<TabulatedBSSRDF> {
public:
// BSSRDFHandle Public Interface
// BSSRDF Interface
using TaggedPointer::TaggedPointer;
PBRT_CPU_GPU inline SampledSpectrum S(const Point3f &p, const Vector3f &wi);
......
......@@ -75,11 +75,9 @@ class LightHandle : public TaggedPointer< // Light Source Types
std::string ToString() const;
PBRT_CPU_GPU inline SampledSpectrum L(const Point3f &p, const Normal3f &n,
const Point2f &uv, const Vector3f &w,
// AreaLights only
PBRT_CPU_GPU inline SampledSpectrum L(Point3f p, Normal3f n, Point2f uv, Vector3f w,
const SampledWavelengths &lambda) const;
PBRT_CPU_GPU
void PDF_Le(const Interaction &intr, Vector3f &w, Float *pdfPos, Float *pdfDir) const;
// InfiniteAreaLights only
PBRT_CPU_GPU inline SampledSpectrum Le(const Ray &ray,
......@@ -96,6 +94,10 @@ class LightHandle : public TaggedPointer< // Light Source Types
// Note shouldn't be called for area lights..
PBRT_CPU_GPU
void PDF_Le(const Ray &ray, Float *pdfPos, Float *pdfDir) const;
// AreaLights only
PBRT_CPU_GPU
void PDF_Le(const Interaction &intr, Vector3f &w, Float *pdfPos, Float *pdfDir) const;
};
} // namespace pbrt
......
......@@ -70,6 +70,9 @@ class Interaction {
Interaction(const Point3f &p, Float time, MediumHandle medium)
: pi(p), time(time), medium(medium) {}
PBRT_CPU_GPU
Interaction(const Point3f &p, const MediumInterface *mediumInterface)
: pi(p), mediumInterface(mediumInterface) {}
PBRT_CPU_GPU
Interaction(const Point3f &p, Float time, const MediumInterface *mediumInterface)
: pi(p), time(time), mediumInterface(mediumInterface) {}
PBRT_CPU_GPU
......
......@@ -200,8 +200,8 @@ DistantLight *DistantLight::Create(const Transform &renderFromLight,
STAT_MEMORY_COUNTER("Memory/Light image and distributions", imageBytes);
// ProjectionLight Method Definitions
ProjectionLight::ProjectionLight(const Transform &renderFromLight,
const MediumInterface &mediumInterface, Image im,
ProjectionLight::ProjectionLight(Transform renderFromLight,
MediumInterface mediumInterface, Image im,
const RGBColorSpace *imageColorSpace, Float lscale,
Float fov, Float phi_v, Allocator alloc)
: LightBase(LightType::DeltaPosition, renderFromLight, mediumInterface),
......@@ -209,26 +209,20 @@ ProjectionLight::ProjectionLight(const Transform &renderFromLight,
imageColorSpace(imageColorSpace),
scale(lscale),
distrib(alloc) {
// Initialize ProjectionLight projection matrix
// _ProjectionLight_ constructor implementation
// Initialize _ProjectionLight_ projection matrix
Float aspect = Float(image.Resolution().x) / Float(image.Resolution().y);
if (aspect > 1)
screenBounds = Bounds2f(Point2f(-aspect, -1), Point2f(aspect, 1));
else
screenBounds = Bounds2f(Point2f(-1, -1 / aspect), Point2f(1, 1 / aspect));
hither = 1e-3f;
Float yon = 1e30f;
ScreenFromLight = Perspective(fov, hither, yon);
LightFromScreen = Inverse(ScreenFromLight);
screenFromLight = Perspective(fov, hither, 1e30f /* yon */);
lightFromScreen = Inverse(screenFromLight);
// Compute cosine of cone surrounding projection directions
// Compute projection image area _A_
Float opposite = std::tan(Radians(fov) / 2.f);
// Area of the image on projection plane.
A = 4 * opposite * opposite * (aspect > 1 ? aspect : 1 / aspect);
Point3f pCorner(screenBounds.pMax.x, screenBounds.pMax.y, 0);
Vector3f wCorner = Normalize(Vector3f(LightFromScreen(pCorner)));
cosTotalWidth = wCorner.z;
// Compute sampling distribution for _ProjectionLight_
ImageChannelDesc channelDesc = image.GetChannelDesc({"R", "G", "B"});
if (!channelDesc)
......@@ -236,31 +230,30 @@ ProjectionLight::ProjectionLight(const Transform &renderFromLight,
CHECK_EQ(3, channelDesc.size());
CHECK(channelDesc.IsIdentity());
auto dwdA = [&](const Point2f &p) {
Vector3f w = Vector3f(LightFromScreen(Point3f(p.x, p.y, 0)));
Vector3f w = Vector3f(lightFromScreen(Point3f(p.x, p.y, 0)));
w = Normalize(w);
return Pow<3>(w.z);
};
Array2D<Float> d = image.GetSamplingDistribution(dwdA, screenBounds);
distrib = PiecewiseConstant2D(d, screenBounds);
// scale radiance to 1 nit
// Set _ProjectionLight::scale_ based on photometric settings
scale /= SpectrumToPhotometric(&imageColorSpace->illuminant);
// scale to target photometric power if requested
if (phi_v > 0) {
// Update _scale_ for target photometric power
Float sum = 0;
RGB luminance = imageColorSpace->LuminanceVector();
for (int v = 0; v < image.Resolution().y; ++v)
for (int u = 0; u < image.Resolution().x; ++u) {
for (int y = 0; y < image.Resolution().y; ++y)
for (int x = 0; x < image.Resolution().x; ++x) {
Point2f ps = screenBounds.Lerp(
{(u + .5f) / image.Resolution().x, (v + .5f) / image.Resolution().y});
Vector3f w = Vector3f(LightFromScreen(Point3f(ps.x, ps.y, 0)));
{(x + .5f) / image.Resolution().x, (y + .5f) / image.Resolution().y});
Vector3f w = Vector3f(lightFromScreen(Point3f(ps.x, ps.y, 0)));
w = Normalize(w);
Float dwdA = Pow<3>(w.z);
for (int c = 0; c < 3; ++c)
sum += image.GetChannel({u, v}, c) * luminance[c] * dwdA;
sum += image.GetChannel({x, y}, c) * luminance[c] * dwdA;
}
scale *= phi_v / (A * sum / (image.Resolution().x * image.Resolution().y));
}
......@@ -270,11 +263,14 @@ ProjectionLight::ProjectionLight(const Transform &renderFromLight,
pstd::optional<LightLiSample> ProjectionLight::SampleLi(LightSampleContext ctx, Point2f u,
SampledWavelengths lambda,
LightSamplingMode mode) const {
// Return sample for incident radiance from _ProjectionLight_
Point3f p = renderFromLight(Point3f(0, 0, 0));
Vector3f wi = Normalize(p - ctx.p());
Vector3f wl = renderFromLight.ApplyInverse(-wi);
return LightLiSample(Projection(wl, lambda) / DistanceSquared(p, ctx.p()), wi, 1,
Interaction(p, 0 /* time */, &mediumInterface));
SampledSpectrum Li = Projection(wl, lambda) / DistanceSquared(p, ctx.p());
if (!Li)
return {};
return LightLiSample(Li, wi, 1, Interaction(p, &mediumInterface));
}
Float ProjectionLight::PDF_Li(LightSampleContext, Vector3f,
......@@ -282,48 +278,19 @@ Float ProjectionLight::PDF_Li(LightSampleContext, Vector3f,
return 0.f;
}
LightBounds ProjectionLight::Bounds() const {
#if 0
// Along the lines of Phi()
Float sum = 0;
for (int v = 0; v < image.Resolution().y; ++v)
for (int u = 0; u < image.Resolution().x; ++u) {
Point2f ps = screenBounds.Lerp({(u + .5f) / image.Resolution().x,
(v + .5f) / image.Resolution().y});
Vector3f w = Vector3f(LightFromScreen(Point3f(ps.x, ps.y, 0)));
w = Normalize(w);
Float dwdA = Pow<3>(w.z);
sum += image.GetChannels({u, v}, rgbChannelDesc).MaxValue() * dwdA;
}
Float phi = scale * A * sum / (image.Resolution().x * image.Resolution().y);
#else
// See comment in SpotLight::Bounds()
Float sum = 0;
for (int v = 0; v < image.Resolution().y; ++v)
for (int u = 0; u < image.Resolution().x; ++u)
sum += std::max({image.GetChannel({u, v}, 0), image.GetChannel({u, v}, 1),
image.GetChannel({u, v}, 2)});
Float phi = scale * sum / (image.Resolution().x * image.Resolution().y);
#endif
Point3f p = renderFromLight(Point3f(0, 0, 0));
Vector3f w = Normalize(renderFromLight(Vector3f(0, 0, 1)));
return LightBounds(p, w, phi, 0.f, std::acos(cosTotalWidth), false);
}
std::string ProjectionLight::ToString() const {
return StringPrintf("[ ProjectionLight %s scale: %f A: %f cosTotalWidth: %f ]",
BaseToString(), scale, A, cosTotalWidth);
return StringPrintf("[ ProjectionLight %s scale: %f A: %f ]", BaseToString(), scale,
A);
}
// Takes wl already in light coordinate system!
SampledSpectrum ProjectionLight::Projection(const Vector3f &wl,
SampledSpectrum ProjectionLight::Projection(Vector3f wl,
const SampledWavelengths &lambda) const {
// Discard directions behind projection light
if (wl.z < hither)
return SampledSpectrum(0.);
// Project point onto projection plane and compute RGB
Point3f ps = ScreenFromLight(Point3f(wl.x, wl.y, wl.z));
Point3f ps = screenFromLight(Point3f(wl.x, wl.y, wl.z));
if (!Inside(Point2f(ps.x, ps.y), screenBounds))
return SampledSpectrum(0.f);
Point2f st = Point2f(screenBounds.Offset(Point2f(ps.x, ps.y)));
......@@ -331,30 +298,64 @@ SampledSpectrum ProjectionLight::Projection(const Vector3f &wl,
for (int c = 0; c < 3; ++c)
rgb[c] = image.LookupNearestChannel(st, c);
return scale * RGBIlluminantSpectrum(*imageColorSpace, rgb).Sample(lambda);
// Return scaled wavelength samples corresponding to RGB
RGBIlluminantSpectrum s(*imageColorSpace, rgb);
return scale * s.Sample(lambda);
}
SampledSpectrum ProjectionLight::Phi(const SampledWavelengths &lambda) const {
SampledSpectrum sum(0.f);
for (int v = 0; v < image.Resolution().y; ++v)
for (int u = 0; u < image.Resolution().x; ++u) {
Point2f ps = screenBounds.Lerp(
{(u + .5f) / image.Resolution().x, (v + .5f) / image.Resolution().y});
Vector3f w = Vector3f(LightFromScreen(Point3f(ps.x, ps.y, 0)));
for (int y = 0; y < image.Resolution().y; ++y)
for (int x = 0; x < image.Resolution().x; ++x) {
// Add pixel $(x,y)$'s contribution to projection light power
// Compute change of variables factor _dwdA_ for projection light pixel
Point2f ps = screenBounds.Lerp(Point2f((x + .5f) / image.Resolution().x,
(y + .5f) / image.Resolution().y));
Vector3f w = Vector3f(lightFromScreen(Point3f(ps.x, ps.y, 0)));
w = Normalize(w);
Float dwdA = Pow<3>(w.z);
Float dwdA = Pow<3>(CosTheta(w));
// Update _sum_ for projection light pixel
RGB rgb;
for (int c = 0; c < 3; ++c)
rgb[c] = image.GetChannel({u, v}, c);
SampledSpectrum L =
RGBIlluminantSpectrum(*imageColorSpace, rgb).Sample(lambda);
rgb[c] = image.GetChannel({x, y}, c);
RGBIlluminantSpectrum s(*imageColorSpace, rgb);
sum += s.Sample(lambda) * dwdA;
}
// Return final power for projection light
return scale * A * sum / (image.Resolution().x * image.Resolution().y);
}
sum += L * dwdA;
LightBounds ProjectionLight::Bounds() const {
#if 0
// Along the lines of Phi()
Float sum = 0;
for (int v = 0; v < image.Resolution().y; ++v)
for (int u = 0; u < image.Resolution().x; ++u) {
Point2f ps = screenBounds.Lerp({(u + .5f) / image.Resolution().x,
(v + .5f) / image.Resolution().y});
Vector3f w = Vector3f(lightFromScreen(Point3f(ps.x, ps.y, 0)));
w = Normalize(w);
Float dwdA = Pow<3>(w.z);
sum += image.GetChannels({u, v}, rgbChannelDesc).MaxValue() * dwdA;
}
Float phi = scale * A * sum / (image.Resolution().x * image.Resolution().y);
#else
// See comment in SpotLight::Bounds()
Float sum = 0;
for (int v = 0; v < image.Resolution().y; ++v)
for (int u = 0; u < image.Resolution().x; ++u)
sum += std::max({image.GetChannel({u, v}, 0), image.GetChannel({u, v}, 1),
image.GetChannel({u, v}, 2)});
Float phi = scale * sum / (image.Resolution().x * image.Resolution().y);
#endif
Point3f pCorner(screenBounds.pMax.x, screenBounds.pMax.y, 0);
Vector3f wCorner = Normalize(Vector3f(lightFromScreen(pCorner)));
Float cosTotalWidth = CosTheta(wCorner);
return scale * A * sum / (image.Resolution().x * image.Resolution().y);
Point3f p = renderFromLight(Point3f(0, 0, 0));
Vector3f w = Normalize(renderFromLight(Vector3f(0, 0, 1)));
return LightBounds(p, w, phi, 0.f, std::acos(cosTotalWidth), false);
}
LightLeSample ProjectionLight::SampleLe(const Point2f &u1, const Point2f &u2,
......@@ -364,7 +365,7 @@ LightLeSample ProjectionLight::SampleLe(const Point2f &u1, const Point2f &u2,
if (pdf == 0)
return {};
Vector3f w = Vector3f(LightFromScreen(Point3f(ps.x, ps.y, 0)));
Vector3f w = Vector3f(lightFromScreen(Point3f(ps.x, ps.y, 0)));
Ray ray = renderFromLight(
Ray(Point3f(0, 0, 0), Normalize(w), time, mediumInterface.outside));
......@@ -391,7 +392,7 @@ void ProjectionLight::PDF_Le(const Ray &ray, Float *pdfPos, Float *pdfDir) const
*pdfDir = 0;
return;
}
Point3f ps = ScreenFromLight(Point3f(w));
Point3f ps = screenFromLight(Point3f(w));
if (!Inside(Point2f(ps.x, ps.y), screenBounds)) {
*pdfDir = 0;
return;
......@@ -458,7 +459,7 @@ pstd::optional<LightLiSample> GoniometricLight::SampleLi(LightSampleContext ctx,
Vector3f wi = Normalize(p - ctx.p());
SampledSpectrum L =
Scale(renderFromLight.ApplyInverse(-wi), lambda) / DistanceSquared(p, ctx.p());
return LightLiSample(L, wi, 1, Interaction(p, 0 /* time */, &mediumInterface));
return LightLiSample(L, wi, 1, Interaction(p, &mediumInterface));
}
Float GoniometricLight::PDF_Li(LightSampleContext, Vector3f,
......@@ -466,6 +467,18 @@ Float GoniometricLight::PDF_Li(LightSampleContext, Vector3f,
return 0.f;
}
SampledSpectrum GoniometricLight::Phi(const SampledWavelengths &lambda) const {
// integrate over speherical coordinates [0,Pi], [0,2pi]
Float sumY = 0;
int width = image.Resolution().x, height = image.Resolution().y;
for (int v = 0; v < height; ++v) {
Float sinTheta = std::sin(Pi * Float(v + .5f) / Float(height));
for (int u = 0; u < width; ++u)
sumY += sinTheta * image.GetChannels({u, v}, wrapMode).Average();
}
return scale * I.Sample(lambda) * 2 * Pi * Pi * sumY / (width * height);
}
LightBounds GoniometricLight::Bounds() const {
// Like Phi() method, but compute the weighted max component value of
// the image map.
......@@ -485,18 +498,6 @@ LightBounds GoniometricLight::Bounds() const {
return LightBounds(p, Vector3f(0, 0, 1), phi, Pi, Pi / 2, false);
}
SampledSpectrum GoniometricLight::Phi(const SampledWavelengths &lambda) const {
// integrate over speherical coordinates [0,Pi], [0,2pi]
Float sumY = 0;
int width = image.Resolution().x, height = image.Resolution().y;
for (int v = 0; v < height; ++v) {
Float sinTheta = std::sin(Pi * Float(v + .5f) / Float(height));
for (int u = 0; u < width; ++u)
sumY += sinTheta * image.GetChannels({u, v}, wrapMode).Average();
}
return scale * I.Sample(lambda) * 2 * Pi * Pi * sumY / (width * height);
}
LightLeSample GoniometricLight::SampleLe(const Point2f &u1, const Point2f &u2,
SampledWavelengths &lambda, Float time) const {
Float pdf;
......@@ -816,9 +817,8 @@ pstd::optional<LightLiSample> UniformInfiniteLight::SampleLi(
LightSamplingMode mode) const {
Vector3f wi = SampleUniformSphere(u);
Float pdf = UniformSpherePDF();
return LightLiSample(
scale * Lemit.Sample(lambda), wi, pdf,
Interaction(ctx.p() + wi * (2 * sceneRadius), 0 /* time */, &mediumInterface));
return LightLiSample(scale * Lemit.Sample(lambda), wi, pdf,
Interaction(ctx.p() + wi * (2 * sceneRadius), &mediumInterface));
}
Float UniformInfiniteLight::PDF_Li(LightSampleContext ctx, Vector3f w,
......@@ -1094,9 +1094,8 @@ pstd::optional<LightLiSample> PortalImageInfiniteLight::SampleLi(
SampledSpectrum L = ImageLookup(uv, lambda);
return LightLiSample(
L, wi, pdf,
Interaction(ctx.p() + wi * (2 * sceneRadius), 0 /* time */, &mediumInterface));
return LightLiSample(L, wi, pdf,
Interaction(ctx.p() + wi * (2 * sceneRadius), &mediumInterface));
}
Float PortalImageInfiniteLight::PDF_Li(LightSampleContext ctx, Vector3f w,
......@@ -1202,28 +1201,17 @@ SpotLight::SpotLight(const Transform &renderFromLight,
CHECK_LE(falloffStart, totalWidth);
}
pstd::optional<LightLiSample> SpotLight::SampleLi(LightSampleContext ctx, Point2f u,
SampledWavelengths lambda,
LightSamplingMode mode) const {
Point3f p = renderFromLight(Point3f(0, 0, 0));
Vector3f wi = Normalize(p - ctx.p());
Vector3f wl = Normalize(renderFromLight.ApplyInverse(-wi));
SampledSpectrum L =
scale * I.Sample(lambda) * Falloff(wl) / DistanceSquared(p, ctx.p());
if (!L)
return {};
return LightLiSample(L, wi, 1, Interaction(p, 0 /* time */, &mediumInterface));
}
Float SpotLight::PDF_Li(LightSampleContext, Vector3f, LightSamplingMode mode) const {
return 0.f;
}
Float SpotLight::Falloff(const Vector3f &wl) const {
Float cosTheta = CosTheta(wl);
if (cosTheta >= cosFalloffStart)
return 1;
return SmoothStep(cosTheta, cosFalloffEnd, cosFalloffStart);
return SmoothStep(CosTheta(wl), cosFalloffEnd, cosFalloffStart);
}
SampledSpectrum SpotLight::Phi(const SampledWavelengths &lambda) const {
return scale * I.Sample(lambda) * 2 * Pi *
((1 - cosFalloffStart) + (cosFalloffStart - cosFalloffEnd) / 2);
}
LightBounds SpotLight::Bounds() const {
......@@ -1246,15 +1234,6 @@ LightBounds SpotLight::Bounds() const {
return LightBounds(p, w, phi, 0.f, std::acos(cosFalloffEnd), false);
}
SampledSpectrum SpotLight::Phi(const SampledWavelengths &lambda) const {
// int_0^start sin theta dtheta = 1 - cosFalloffStart
// See notes/sample-spotlight.nb for the falloff part:
// int_start^end smoothstep(cost, end, start) sin theta dtheta =
// (cosStart - cosEnd) / 2
return scale * I.Sample(lambda) * 2 * Pi *
((1 - cosFalloffStart) + (cosFalloffStart - cosFalloffEnd) / 2);
}
LightLeSample SpotLight::SampleLe(const Point2f &u1, const Point2f &u2,
SampledWavelengths &lambda, Float time) const {
// Unnormalized probabilities of sampling each part.
......
......@@ -36,7 +36,6 @@ PBRT_CPU_GPU inline bool IsDeltaLight(LightType type) {
// LightLiSample Definition
struct LightLiSample {
public:
// LightLiSample Public Methods
LightLiSample() = default;
PBRT_CPU_GPU
......@@ -225,18 +224,19 @@ LightBounds Union(const LightBounds &a, const LightBounds &b);
class LightBase {
public:
// LightBase Public Methods
LightBase(LightType flags, const Transform &renderFromLight,
LightBase(LightType type, const Transform &renderFromLight,
const MediumInterface &mediumInterface);
PBRT_CPU_GPU
LightType Type() const { return type; }
PBRT_CPU_GPU
SampledSpectrum L(const Point3f &p, const Normal3f &n, const Point2f &uv,
const Vector3f &w, const SampledWavelengths &lambda) const {
SampledSpectrum L(Point3f p, Normal3f n, Point2f uv, Vector3f w,
const SampledWavelengths &lambda) const {
return SampledSpectrum(0.f);
}
PBRT_CPU_GPU
SampledSpectrum Le(const Ray &ray, const SampledWavelengths &lambda) const {
SampledSpectrum Le(const Ray &, const SampledWavelengths &) const {
return SampledSpectrum(0.f);
}
......@@ -244,15 +244,15 @@ class LightBase {
std::string BaseToString() const;
// LightBase Protected Members
LightType type;
MediumInterface mediumInterface;
Transform renderFromLight;
MediumInterface mediumInterface;
};
// PointLight Definition
class PointLight : public LightBase {
public:
// PointLight Public Methods
PointLight(const Transform &renderFromLight, const MediumInterface &mediumInterface,
PointLight(Transform renderFromLight, MediumInterface mediumInterface,
SpectrumHandle I, Float scale, Allocator alloc)
: LightBase(LightType::DeltaPosition, renderFromLight, mediumInterface),
I(I, alloc),
......@@ -286,8 +286,8 @@ class PointLight : public LightBase {
LightSamplingMode mode) const {
Point3f p = renderFromLight(Point3f(0, 0, 0));
Vector3f wi = Normalize(p - ctx.p());
return LightLiSample(scale * I.Sample(lambda) / DistanceSquared(p, ctx.p()), wi,
1, Interaction(p, 0 /* time */, &mediumInterface));
SampledSpectrum Li = scale * I.Sample(lambda) / DistanceSquared(p, ctx.p());
return LightLiSample(Li, wi, 1, Interaction(p, &mediumInterface));
}
PBRT_CPU_GPU
......@@ -342,7 +342,7 @@ class DistantLight : public LightBase {
Vector3f wi = Normalize(renderFromLight(Vector3f(0, 0, 1)));
Point3f pOutside = ctx.p() + wi * (2 * sceneRadius);
return LightLiSample(scale * Lemit.Sample(lambda), wi, 1,
Interaction(pOutside, 0 /* time */, &mediumInterface));
Interaction(pOutside, &mediumInterface));
}
private:
......@@ -357,9 +357,9 @@ class DistantLight : public LightBase {
class ProjectionLight : public LightBase {
public:
// ProjectionLight Public Methods
ProjectionLight(const Transform &renderFromLight, const MediumInterface &medium,
Image image, const RGBColorSpace *colorSpace, Float scale, Float fov,
Float power, Allocator alloc);
ProjectionLight(Transform renderFromLight, MediumInterface medium, Image image,
const RGBColorSpace *colorSpace, Float scale, Float fov, Float power,
Allocator alloc);
static ProjectionLight *Create(const Transform &renderFromLight, MediumHandle medium,
const ParameterDictionary &parameters,
......@@ -372,7 +372,7 @@ class ProjectionLight : public LightBase {
SampledWavelengths lambda,
LightSamplingMode mode) const;
PBRT_CPU_GPU
SampledSpectrum Projection(const Vector3f &w, const SampledWavelengths &lambda) const;
SampledSpectrum Projection(Vector3f w, const SampledWavelengths &lambda) const;
SampledSpectrum Phi(const SampledWavelengths &lambda) const;
......@@ -400,9 +400,9 @@ class ProjectionLight : public LightBase {
const RGBColorSpace *imageColorSpace;
Float scale;
Bounds2f screenBounds;
Float hither;
Transform ScreenFromLight, LightFromScreen;
Float A, cosTotalWidth;
Float hither = 1e-3f;
Transform screenFromLight, lightFromScreen;
Float A;
PiecewiseConstant2D distrib;
};
......@@ -499,8 +499,8 @@ class DiffuseAreaLight : public LightBase {
std::string ToString() const;
PBRT_CPU_GPU
SampledSpectrum L(const Point3f &p, const Normal3f &n, const Point2f &uv,
const Vector3f &w, const SampledWavelengths &lambda) const {
SampledSpectrum L(Point3f p, Normal3f n, Point2f uv, Vector3f w,
const SampledWavelengths &lambda) const {
if (!twoSided && Dot(n, w) < 0)
return SampledSpectrum(0.f);
......@@ -656,9 +656,8 @@ class ImageInfiniteLight : public LightBase {
// Return radiance value for infinite light direction
SampledSpectrum L = LookupLe(uv, lambda);
return LightLiSample(L, wi, pdf,
Interaction(ctx.p() + wi * (2 * sceneRadius), 0 /* time */,
&mediumInterface));
return LightLiSample(
L, wi, pdf, Interaction(ctx.p() + wi * (2 * sceneRadius), &mediumInterface));
}
LightBounds Bounds() const { return {}; }
......@@ -799,10 +798,6 @@ class SpotLight : public LightBase {
void Preprocess(const Bounds3f &sceneBounds) {}
PBRT_CPU_GPU
pstd::optional<LightLiSample> SampleLi(LightSampleContext ctx, Point2f u,
SampledWavelengths lambda,
LightSamplingMode mode) const;
PBRT_CPU_GPU
Float Falloff(const Vector3f &w) const;
......@@ -826,11 +821,26 @@ class SpotLight : public LightBase {
std::string ToString() const;
PBRT_CPU_GPU
pstd::optional<LightLiSample> SampleLi(LightSampleContext ctx, Point2f u,
SampledWavelengths lambda,
LightSamplingMode mode) const {
Point3f p = renderFromLight(Point3f(0, 0, 0));
Vector3f wi = Normalize(p - ctx.p());
// Compute incident radiance _Li_ for _SpotLight_
Vector3f wl = Normalize(renderFromLight.ApplyInverse(-wi));
SampledSpectrum Li =
scale * I.Sample(lambda) * Falloff(wl) / DistanceSquared(p, ctx.p());
if (!Li)
return {};
return LightLiSample(Li, wi, 1, Interaction(p, &mediumInterface));
}
private:
// SpotLight Private Members
DenselySampledSpectrum I;
Float scale;
Float cosFalloffStart, cosFalloffEnd;
Float scale, cosFalloffStart, cosFalloffEnd;
};
inline pstd::optional<LightLiSample> LightHandle::SampleLi(LightSampleContext ctx,
......@@ -847,8 +857,7 @@ inline Float LightHandle::PDF_Li(LightSampleContext ctx, Vector3f wi,
return Dispatch(pdf);
}
inline SampledSpectrum LightHandle::L(const Point3f &p, const Normal3f &n,
const Point2f &uv, const Vector3f &w,
inline SampledSpectrum LightHandle::L(Point3f p, Normal3f n, Point2f uv, Vector3f w,
const SampledWavelengths &lambda) const {
CHECK(Type() == LightType::Area);
auto l = [&](auto ptr) { return ptr->L(p, n, uv, w, lambda); };
......
......@@ -248,22 +248,22 @@ class CuboidMedium {
if (t >= t1)
break;
// Report scattering event in grid to callback function
if (t < tMax) {
Point3f p = ray(t);
// Compute medium properties at sampled point in grid
SampledSpectrum Tmaj = FastExp(-sigma_maj * (t - t0));
// Compute _density_ and _Le_ at sampled point in grid
SampledSpectrum density = provider->Density(p, lambda);
Point3f p = ray(t);
SampledSpectrum d = provider->Density(p, lambda);
SampledSpectrum Le = provider->Le(p, lambda);
SampledSpectrum sigmap_a = sigma_a * d, sigmap_s = sigma_s * d;
MediumInteraction intr(renderFromMedium(p), -Normalize(rRender.d),
rRender.time, sigma_a * density,
sigma_s * density, sigma_maj, Le, this,
&phase);
// Report scattering event in grid to callback function
Point3f pRender = renderFromMedium(p);
MediumInteraction intr(pRender, -Normalize(rRender.d),
rRender.time, sigmap_a, sigmap_s,
sigma_maj, Le, this, &phase);
if (!callback(MediumSample(intr, Tmaj)))
return;
}
// Update _t0_ after medium interaction
t0 = t;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册