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

Update from book source.

Improve filter footprint computation when no differentials are available and Camera's approximations of dpdx and dpdy are used.

Remove RGBConstantTexture and RGBReflectanceConstantTexture; they're not giving any perf. benefit at this point.
上级 26a13e1b
......@@ -54,13 +54,13 @@ class MaterialHandle
template <typename TextureEvaluator>
PBRT_CPU_GPU inline BSDF GetBSDF(TextureEvaluator texEval, MaterialEvalContext ctx,
SampledWavelengths &lambda,
ScratchBuffer &scratchBuffer) const;
ScratchBuffer &buf) const;
template <typename TextureEvaluator>
PBRT_CPU_GPU inline BSSRDFHandle GetBSSRDF(TextureEvaluator texEval,
MaterialEvalContext ctx,
SampledWavelengths &lambda,
ScratchBuffer &scratchBuffer) const;
ScratchBuffer &buf) const;
PBRT_CPU_GPU inline FloatTextureHandle GetDisplacement() const;
......
......@@ -30,10 +30,12 @@ class WrinkledTexture;
// FloatTextureHandle Definition
class FloatTextureHandle
: public TaggedPointer<FloatImageTexture, GPUFloatImageTexture, FloatMixTexture,
FloatScaledTexture, FloatConstantTexture, FloatBilerpTexture,
FloatCheckerboardTexture, FloatDotsTexture, FBmTexture,
FloatPtexTexture, WindyTexture, WrinkledTexture> {
: public TaggedPointer< // FloatTextures
FloatImageTexture, GPUFloatImageTexture, FloatMixTexture, FloatScaledTexture,
FloatConstantTexture, FloatBilerpTexture, FloatCheckerboardTexture,
FloatDotsTexture, FBmTexture, FloatPtexTexture, WindyTexture, WrinkledTexture
> {
public:
// FloatTexture Interface
using TaggedPointer::TaggedPointer;
......@@ -63,11 +65,13 @@ class SpectrumScaledTexture;
// SpectrumTextureHandle Definition
class SpectrumTextureHandle
: public TaggedPointer<
RGBConstantTexture, RGBReflectanceConstantTexture, SpectrumImageTexture,
GPUSpectrumImageTexture, SpectrumMixTexture, SpectrumScaledTexture,
SpectrumConstantTexture, SpectrumBilerpTexture, SpectrumCheckerboardTexture,
MarbleTexture, SpectrumDotsTexture, SpectrumPtexTexture> {
: public TaggedPointer< // SpectrumTextures
SpectrumImageTexture, GPUSpectrumImageTexture, SpectrumMixTexture,
SpectrumScaledTexture, SpectrumConstantTexture, SpectrumBilerpTexture,
SpectrumCheckerboardTexture, MarbleTexture, SpectrumDotsTexture,
SpectrumPtexTexture
> {
public:
// SpectrumTexture Interface
using TaggedPointer::TaggedPointer;
......
......@@ -157,21 +157,32 @@ pstd::optional<CameraRayDifferential> CameraBase::GenerateRayDifferential(
}
void CameraBase::ApproximatedPdxy(SurfaceInteraction &si, int samplesPerPixel) const {
Point3f pc = CameraFromRender(si.p(), si.time);
Float dist = Distance(pc, Point3f(0, 0, 0));
// Compute tangent plane equation for ray differential intersections
Point3f pCamera = CameraFromRender(si.p(), si.time);
Normal3f nCamera = CameraFromRender(si.n, si.time);
Transform DownZFromCamera =
RotateFromTo(Normalize(Vector3f(pCamera)), Vector3f(0, 0, 1));
Point3f pDownZ = DownZFromCamera(pCamera);
Normal3f nDownZ = DownZFromCamera(nCamera);
Float d = Dot(nDownZ, Vector3f(pDownZ));
// Find intersection points for approximated camera differential rays
Ray xRay(Point3f(0, 0, 0) + minPosDifferentialX,
Vector3f(0, 0, 1) + minDirDifferentialX);
Float tx = -(Dot(nDownZ, Vector3f(xRay.o)) - d) / Dot(nDownZ, xRay.d);
Ray yRay(Point3f(0, 0, 0) + minPosDifferentialY,
Vector3f(0, 0, 1) + minDirDifferentialY);
Float ty = -(Dot(nDownZ, Vector3f(yRay.o)) - d) / Dot(nDownZ, yRay.d);
Point3f px = xRay(tx), py = yRay(ty);
// Estimate $\dpdx$ and $\dpdy$ in tangent plane at intersection point
Float sppScale = GetOptions().disablePixelJitter
? 1
: std::max<Float>(.125, 1 / std::sqrt((Float)samplesPerPixel));
Frame f = Frame::FromZ(si.n);
// ray plane:
// (0,0,0) + minPosDifferential + ((0,0,1) + minDirDifferantial)) * t = (x,
// x, dist)
Float tx = (dist - minPosDifferentialX.z) / (1 + minDirDifferentialX.z);
si.dpdx = sppScale * f.FromLocal(minPosDifferentialX + tx * minDirDifferentialX);
Float ty = (dist - minPosDifferentialY.z) / (1 + minDirDifferentialY.z);
si.dpdy = sppScale * f.FromLocal(minPosDifferentialY + ty * minDirDifferentialY);
si.dpdx =
sppScale * RenderFromCamera(DownZFromCamera.ApplyInverse(px - pDownZ), si.time);
si.dpdy =
sppScale * RenderFromCamera(DownZFromCamera.ApplyInverse(py - pDownZ), si.time);
}
void CameraBase::FindMinimumDifferentials(CameraHandle camera) {
......
......@@ -61,6 +61,11 @@ class CameraTransform {
return renderFromCamera(v, time);
}
PBRT_CPU_GPU
Normal3f RenderFromCamera(const Normal3f &n, Float time) const {
return renderFromCamera(n, time);
}
PBRT_CPU_GPU
Ray RenderFromCamera(const Ray &r) const { return renderFromCamera(r); }
......@@ -74,6 +79,11 @@ class CameraTransform {
return renderFromCamera.ApplyInverse(v, time);
}
PBRT_CPU_GPU
Normal3f CameraFromRender(const Normal3f &v, Float time) const {
return renderFromCamera.ApplyInverse(v, time);
}
std::string ToString() const;
private:
......@@ -171,6 +181,11 @@ class CameraBase {
return cameraTransform.RenderFromCamera(v, time);
}
PBRT_CPU_GPU
Normal3f RenderFromCamera(const Normal3f &v, Float time) const {
return cameraTransform.RenderFromCamera(v, time);
}
PBRT_CPU_GPU
Point3f RenderFromCamera(const Point3f &p, Float time) const {
return cameraTransform.RenderFromCamera(p, time);
......@@ -181,6 +196,11 @@ class CameraBase {
return cameraTransform.CameraFromRender(v, time);
}
PBRT_CPU_GPU
Normal3f CameraFromRender(const Normal3f &v, Float time) const {
return cameraTransform.CameraFromRender(v, time);
}
PBRT_CPU_GPU
Point3f CameraFromRender(const Point3f &p, Float time) const {
return cameraTransform.CameraFromRender(p, time);
......
......@@ -80,9 +80,17 @@ void SurfaceInteraction::ComputeDifferentials(const RayDifferential &ray,
dvdy = std::isfinite(dvdy) ? Clamp(dvdy, -1e8f, 1e8f) : 0.f;
}
void SurfaceInteraction::SkipIntersection(RayDifferential *ray, Float t) const {
*((Ray *)ray) = SpawnRay(ray->d);
if (ray->hasDifferentials) {
ray->rxOrigin = ray->rxOrigin + t * ray->rxDirection;
ray->ryOrigin = ray->ryOrigin + t * ray->ryDirection;
}
}
RayDifferential SurfaceInteraction::SpawnRay(const RayDifferential &rayi,
const BSDF &bsdf, const Vector3f &wi,
int /*BxDFFlags*/ flags) const {
const BSDF &bsdf, Vector3f wi,
int flags) const {
RayDifferential rd(SpawnRay(wi));
if (rayi.hasDifferentials) {
// Compute ray differentials for specular reflection or transmission
......@@ -92,52 +100,47 @@ RayDifferential SurfaceInteraction::SpawnRay(const RayDifferential &rayi,
Normal3f dndy = shading.dndu * dudy + shading.dndv * dvdy;
Vector3f dwodx = -rayi.rxDirection - wo, dwody = -rayi.ryDirection - wo;
if (flags == (BxDFFlags::Reflection | BxDFFlags::Specular)) {
if (flags == BxDFFlags::SpecularReflection) {
// Initialize origins of specular differential rays
rd.hasDifferentials = true;
rd.rxOrigin = p() + dpdx;
rd.ryOrigin = p() + dpdy;
// Compute differential reflected directions
Float dDNdx = Dot(dwodx, ns) + Dot(wo, dndx);
Float dDNdy = Dot(dwody, ns) + Dot(wo, dndy);
rd.rxDirection = wi - dwodx + 2.f * Vector3f(Dot(wo, ns) * dndx + dDNdx * ns);
rd.ryDirection = wi - dwody + 2.f * Vector3f(Dot(wo, ns) * dndy + dDNdy * ns);
} else if (flags == (BxDFFlags::Transmission | BxDFFlags::Specular)) {
Float dwoDotNdx = Dot(dwodx, ns) + Dot(wo, dndx);
Float dwoDotNdy = Dot(dwody, ns) + Dot(wo, dndy);
rd.rxDirection =
wi - dwodx + 2 * Vector3f(Dot(wo, ns) * dndx + dwoDotNdx * ns);
rd.ryDirection =
wi - dwody + 2 * Vector3f(Dot(wo, ns) * dndy + dwoDotNdy * ns);
} else if (flags == BxDFFlags::SpecularTransmission) {
// Initialize origins of specular differential rays
rd.hasDifferentials = true;
rd.rxOrigin = p() + dpdx;
rd.ryOrigin = p() + dpdy;
// Compute differential transmitted directions
// NOTE: eta coming in is now 1/eta from the derivation below, so
// there's a 1/ here now...
// Find _eta_ and oriented surface normal for transmission
Float eta = 1 / bsdf.eta;
if (Dot(wo, ns) < 0) {
ns = -ns;
dndx = -dndx;
dndy = -dndy;
}
Float dDNdx = Dot(dwodx, ns) + Dot(wo, dndx);
Float dDNdy = Dot(dwody, ns) + Dot(wo, dndy);
// Compute partial derivatives of $\mu$
Float dwoDotNdx = Dot(dwodx, ns) + Dot(wo, dndx);
Float dwoDotNdy = Dot(dwody, ns) + Dot(wo, dndy);
Float mu = eta * Dot(wo, ns) - AbsDot(wi, ns);
Float dmudx = (eta - (eta * eta * Dot(wo, ns)) / AbsDot(wi, ns)) * dDNdx;
Float dmudy = (eta - (eta * eta * Dot(wo, ns)) / AbsDot(wi, ns)) * dDNdy;
Float dmudx = (eta - (eta * eta * Dot(wo, ns)) / AbsDot(wi, ns)) * dwoDotNdx;
Float dmudy = (eta - (eta * eta * Dot(wo, ns)) / AbsDot(wi, ns)) * dwoDotNdy;
rd.rxDirection = wi - eta * dwodx + Vector3f(mu * dndx + dmudx * ns);
rd.ryDirection = wi - eta * dwody + Vector3f(mu * dndy + dmudy * ns);
}
}
// Squash potentially troublesome differentials
// After many specuar bounces (e.g. the Transparent Machines scenes),
// differentials can drift off to have large magnitudes, which ends up
// leaving a trail of Infs and NaNs in their wake. We'll disable the
// differentials when this seems to be happening.
//
// TODO: this is unsatisfying and would be nice to address in a more
// principled way.
if (LengthSquared(rd.rxDirection) > 1e16f || LengthSquared(rd.ryDirection) > 1e16f ||
LengthSquared(Vector3f(rd.rxOrigin)) > 1e16f ||
LengthSquared(Vector3f(rd.ryOrigin)) > 1e16f)
......@@ -146,14 +149,6 @@ RayDifferential SurfaceInteraction::SpawnRay(const RayDifferential &rayi,
return rd;
}
void SurfaceInteraction::SkipIntersection(RayDifferential *ray, Float t) const {
*((Ray *)ray) = SpawnRay(ray->d);
if (ray->hasDifferentials) {
ray->rxOrigin = ray->rxOrigin + t * ray->rxDirection;
ray->ryOrigin = ray->ryOrigin + t * ray->ryDirection;
}
}
BSDF SurfaceInteraction::GetBSDF(const RayDifferential &ray, SampledWavelengths &lambda,
CameraHandle camera, ScratchBuffer &scratchBuffer,
SamplerHandle sampler) {
......
......@@ -248,13 +248,13 @@ class SurfaceInteraction : public Interaction {
void ComputeDifferentials(const RayDifferential &r, CameraHandle camera,
int samplesPerPixel);
using Interaction::SpawnRay;
PBRT_CPU_GPU
RayDifferential SpawnRay(const RayDifferential &rayi, const BSDF &bsdf,
const Vector3f &wi, int /*BxDFFlags*/ flags) const;
void SkipIntersection(RayDifferential *ray, Float t) const;
using Interaction::SpawnRay;
PBRT_CPU_GPU
void SkipIntersection(RayDifferential *ray, Float t) const;
RayDifferential SpawnRay(const RayDifferential &rayi, const BSDF &bsdf, Vector3f wi,
int /*BxDFFlags*/ flags) const;
PBRT_CPU_GPU
BSDF GetBSDF(const RayDifferential &ray, SampledWavelengths &lambda,
......
......@@ -25,6 +25,7 @@ namespace pbrt {
// MaterialEvalContext Definition
struct MaterialEvalContext : public TextureEvalContext {
// MaterialEvalContext Public Methods
MaterialEvalContext() = default;
PBRT_CPU_GPU
MaterialEvalContext(const SurfaceInteraction &si)
......
......@@ -835,13 +835,14 @@ SpectrumTextureHandle TextureParameterDictionary::GetSpectrumTextureOrNull(
ErrorExit(&p->loc,
"Negative value provided for \"rgb\" parameter \"%s\".",
p->name);
SpectrumHandle s;
if (spectrumType == SpectrumType::General)
return alloc.new_object<RGBConstantTexture>(*dict->ColorSpace(), rgb);
s = alloc.new_object<RGBSpectrum>(*dict->ColorSpace(), rgb);
else {
CHECK(spectrumType == SpectrumType::Reflectance);
return alloc.new_object<RGBReflectanceConstantTexture>(
*dict->ColorSpace(), rgb);
s = alloc.new_object<RGBReflectanceSpectrum>(*dict->ColorSpace(), rgb);
}
return alloc.new_object<SpectrumConstantTexture>(s);
} else if (p->type == "spectrum" || p->type == "blackbody") {
SpectrumHandle s = GetOneSpectrum(name, nullptr, spectrumType, alloc);
CHECK(s != nullptr);
......
......@@ -100,14 +100,6 @@ FloatConstantTexture *FloatConstantTexture::Create(
return alloc.new_object<FloatConstantTexture>(parameters.GetOneFloat("value", 1.f));
}
std::string RGBConstantTexture::ToString() const {
return StringPrintf("[ RGBConstantTexture value: %s ]", value);
}
std::string RGBReflectanceConstantTexture::ToString() const {
return StringPrintf("[ RGBReflectanceConstantTexture value: %s ]", value);
}
std::string SpectrumConstantTexture::ToString() const {
return StringPrintf("[ SpectrumConstantTexture value: %s ]", value);
}
......
......@@ -27,6 +27,7 @@ namespace pbrt {
// TextureEvalContext Definition
struct TextureEvalContext {
// TextureEvalContext Public Methods
TextureEvalContext() = default;
PBRT_CPU_GPU
TextureEvalContext(const SurfaceInteraction &si)
......@@ -93,12 +94,12 @@ class SphericalMapping2D {
PBRT_CPU_GPU
Point2f Map(TextureEvalContext ctx, Vector2f *dstdx, Vector2f *dstdy) const {
Point2f st = sphere(ctx.p);
Point2f st = Sphere(ctx.p);
// Compute texture coordinate differentials for sphere $(u,v)$ mapping
const Float delta = .1f;
Point2f stDeltaX = sphere(ctx.p + delta * ctx.dpdx);
Float delta = .1f;
Point2f stDeltaX = Sphere(ctx.p + delta * ctx.dpdx);
*dstdx = (stDeltaX - st) / delta;
Point2f stDeltaY = sphere(ctx.p + delta * ctx.dpdy);
Point2f stDeltaY = Sphere(ctx.p + delta * ctx.dpdy);
*dstdy = (stDeltaY - st) / delta;
// Handle sphere mapping discontinuity for coordinate differentials
......@@ -117,7 +118,7 @@ class SphericalMapping2D {
private:
// SphericalMapping2D Private Methods
PBRT_CPU_GPU
Point2f sphere(const Point3f &p) const {
Point2f Sphere(const Point3f &p) const {
Vector3f vec = Normalize(textureFromRender(p) - Point3f(0, 0, 0));
Float theta = SphericalTheta(vec), phi = SphericalPhi(vec);
return {theta * InvPi, phi * Inv2Pi};
......@@ -137,16 +138,16 @@ class CylindricalMapping2D {
PBRT_CPU_GPU
Point2f Map(TextureEvalContext ctx, Vector2f *dstdx, Vector2f *dstdy) const {
Point2f st = cylinder(ctx.p);
Point2f st = Cylinder(ctx.p);
// Compute texture coordinate differentials for cylinder $(u,v)$ mapping
const Float delta = .01f;
Point2f stDeltaX = cylinder(ctx.p + delta * ctx.dpdx);
Point2f stDeltaX = Cylinder(ctx.p + delta * ctx.dpdx);
*dstdx = (stDeltaX - st) / delta;
if ((*dstdx)[1] > .5)
(*dstdx)[1] = 1.f - (*dstdx)[1];
else if ((*dstdx)[1] < -.5f)
(*dstdx)[1] = -((*dstdx)[1] + 1);
Point2f stDeltaY = cylinder(ctx.p + delta * ctx.dpdy);
Point2f stDeltaY = Cylinder(ctx.p + delta * ctx.dpdy);
*dstdy = (stDeltaY - st) / delta;
if ((*dstdy)[1] > .5)
(*dstdy)[1] = 1.f - (*dstdy)[1];
......@@ -159,7 +160,7 @@ class CylindricalMapping2D {
private:
// CylindricalMapping2D Private Methods
PBRT_CPU_GPU
Point2f cylinder(const Point3f &p) const {
Point2f Cylinder(const Point3f &p) const {
Vector3f vec = Normalize(textureFromRender(p) - Point3f(0, 0, 0));
return Point2f((Pi + std::atan2(vec.y, vec.x)) * Inv2Pi, vec.z);
}
......@@ -172,7 +173,7 @@ class CylindricalMapping2D {
class PlanarMapping2D {
public:
// PlanarMapping2D Public Methods
PlanarMapping2D(const Vector3f &vs, const Vector3f &vt, Float ds = 0, Float dt = 0)
PlanarMapping2D(Vector3f vs, Vector3f vt, Float ds, Float dt)
: vs(vs), vt(vt), ds(ds), dt(dt) {}
PBRT_CPU_GPU
......@@ -263,6 +264,7 @@ inline Point3f TextureMapping3DHandle::Map(TextureEvalContext ctx, Vector3f *dpd
// FloatConstantTexture Definition
class FloatConstantTexture {
public:
// FloatConstantTexture Public Methods
FloatConstantTexture(Float value) : value(value) {}
PBRT_CPU_GPU
......@@ -278,42 +280,10 @@ class FloatConstantTexture {
Float value;
};
// RGBConstantTexture Definition
class RGBConstantTexture {
public:
RGBConstantTexture(const RGBColorSpace &cs, const RGB &rgb) : value(cs, rgb) {}
PBRT_CPU_GPU
SampledSpectrum Evaluate(TextureEvalContext ctx, SampledWavelengths lambda) const {
return value.Sample(lambda);
}
std::string ToString() const;
private:
RGBSpectrum value;
};
// RGBReflectanceConstantTexture Definition
class RGBReflectanceConstantTexture {
public:
RGBReflectanceConstantTexture(const RGBColorSpace &cs, const RGB &rgb)
: value(cs, rgb) {}
PBRT_CPU_GPU
SampledSpectrum Evaluate(TextureEvalContext ctx, SampledWavelengths lambda) const {
return value.Sample(lambda);
}
std::string ToString() const;
private:
RGBReflectanceSpectrum value;
};
// SpectrumConstantTexture Definition
class SpectrumConstantTexture {
public:
// SpectrumConstantTexture Public Methods
SpectrumConstantTexture(SpectrumHandle value) : value(value) { DCHECK(value); }
PBRT_CPU_GPU
......@@ -793,7 +763,7 @@ class MarbleTexture {
// FloatMixTexture Definition
class FloatMixTexture {
public:
// MixTexture Public Methods
// FloatMixTexture Public Methods
FloatMixTexture(FloatTextureHandle tex1, FloatTextureHandle tex2,
FloatTextureHandle amount)
: tex1(tex1), tex2(tex2), amount(amount) {}
......@@ -891,6 +861,7 @@ class SpectrumPtexTexture : public PtexTextureBase {
// FloatScaledTexture Definition
class FloatScaledTexture {
public:
// FloatScaledTexture Public Methods
FloatScaledTexture(FloatTextureHandle tex, FloatTextureHandle scale)
: tex(tex), scale(scale) {}
......@@ -994,6 +965,7 @@ inline SampledSpectrum SpectrumTextureHandle::Evaluate(TextureEvalContext ctx,
return Dispatch(eval);
}
// UniversalTextureEvaluator Definition
class UniversalTextureEvaluator {
public:
PBRT_CPU_GPU
......@@ -1019,9 +991,8 @@ class BasicTextureEvaluator {
return false;
}
for (auto s : stex)
if (s && (!s.Is<SpectrumConstantTexture>() && !s.Is<RGBConstantTexture>() &&
!s.Is<RGBReflectanceConstantTexture>() &&
!s.Is<GPUSpectrumImageTexture>())) {
if (s &&
(!s.Is<SpectrumConstantTexture>() && !s.Is<GPUSpectrumImageTexture>())) {
return false;
}
return true;
......@@ -1042,11 +1013,6 @@ class BasicTextureEvaluator {
SampledWavelengths lambda) {
if (SpectrumConstantTexture *sc = tex.CastOrNullptr<SpectrumConstantTexture>())
return sc->Evaluate(ctx, lambda);
else if (RGBConstantTexture *rgbc = tex.CastOrNullptr<RGBConstantTexture>())
return rgbc->Evaluate(ctx, lambda);
else if (RGBReflectanceConstantTexture *rgbc =
tex.CastOrNullptr<RGBReflectanceConstantTexture>())
return rgbc->Evaluate(ctx, lambda);
else if (GPUSpectrumImageTexture *sg =
tex.CastOrNullptr<GPUSpectrumImageTexture>())
return sg->Evaluate(ctx, lambda);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册