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

Update from book source. No functional changes.

s/BumpEvalContext/NormalBumpEvalContext/
Factor Bump() into BumpMap() and NormalMap()
上级 f5ad66a5
......@@ -64,10 +64,10 @@ class Material
template <typename TextureEvaluator>
PBRT_CPU_GPU inline bool CanEvaluateTextures(TextureEvaluator texEval) const;
PBRT_CPU_GPU inline FloatTexture GetDisplacement() const;
PBRT_CPU_GPU inline const Image *GetNormalMap() const;
PBRT_CPU_GPU inline FloatTexture GetDisplacement() const;
PBRT_CPU_GPU inline bool HasSubsurfaceScattering() const;
};
......
......@@ -154,7 +154,9 @@ RayDifferential SurfaceInteraction::SpawnRay(const RayDifferential &rayi,
BSDF SurfaceInteraction::GetBSDF(const RayDifferential &ray, SampledWavelengths &lambda,
Camera camera, ScratchBuffer &scratchBuffer,
Sampler sampler) {
// Estimate $(u,v)$ and position differentials at intersection point
ComputeDifferentials(ray, camera, sampler.SamplesPerPixel());
// Resolve _MixMaterial_ if necessary
while (material.Is<MixMaterial>()) {
MixMaterial *mix = material.CastOrNullptr<MixMaterial>();
......@@ -165,14 +167,19 @@ BSDF SurfaceInteraction::GetBSDF(const RayDifferential &ray, SampledWavelengths
if (!material)
return {};
// Evaluate bump map and compute shading normal
// Evaluate normal or bump map, if present
FloatTexture displacement = material.GetDisplacement();
const Image *normalMap = material.GetNormalMap();
if (displacement || normalMap) {
// Get shading $\dpdu$ and $\dpdv$ using normal or bump map
Vector3f dpdu, dpdv;
Bump(UniversalTextureEvaluator(), displacement, normalMap, *this, &dpdu, &dpdv);
SetShadingGeometry(Normal3f(Normalize(Cross(dpdu, dpdv))), dpdu, dpdv,
shading.dndu, shading.dndv, false);
if (normalMap)
NormalMap(normalMap, *this, &dpdu, &dpdv);
else
BumpMap(UniversalTextureEvaluator(), displacement, *this, &dpdu, &dpdv);
Normal3f ns(Normalize(Cross(dpdu, dpdv)));
SetShadingGeometry(ns, dpdu, dpdv, shading.dndu, shading.dndv, false);
}
// Return BSDF for surface interaction
......
......@@ -30,12 +30,13 @@ std::string MaterialEvalContext::ToString() const {
TextureEvalContext::ToString(), wo, ns, dpdus);
}
std::string BumpEvalContext::ToString() const {
return StringPrintf("[ BumpEvalContext p: %s uv: %s shading.n: %s shading.dpdu: %s "
"shading.dpdv: %s shading.dndu: %s shading.dndv: %s dudx: %f "
"dudy: %f dvdx: %f dvdy: %f dpdx: %s dpdy: %s faceIndex: %d ]",
p, uv, shading.n, shading.dpdu, shading.dpdv, shading.dndu,
shading.dndv, dudx, dudy, dvdx, dvdy, dpdx, dpdy, faceIndex);
std::string NormalBumpEvalContext::ToString() const {
return StringPrintf(
"[ NormalBumpEvalContext p: %s uv: %s shading.n: %s shading.dpdu: %s "
"shading.dpdv: %s shading.dndu: %s shading.dndv: %s dudx: %f "
"dudy: %f dvdx: %f dvdy: %f dpdx: %s dpdy: %s faceIndex: %d ]",
p, uv, shading.n, shading.dpdu, shading.dpdv, shading.dndu, shading.dndv, dudx,
dudy, dvdx, dvdy, dpdx, dpdy, faceIndex);
}
// DielectricMaterial Method Definitions
......
......@@ -38,12 +38,12 @@ struct MaterialEvalContext : public TextureEvalContext {
Vector3f dpdus;
};
// BumpEvalContext Definition
struct BumpEvalContext {
// BumpEvalContext Public Methods
BumpEvalContext() = default;
// NormalBumpEvalContext Definition
struct NormalBumpEvalContext {
// NormalBumpEvalContext Public Methods
NormalBumpEvalContext() = default;
PBRT_CPU_GPU
BumpEvalContext(const SurfaceInteraction &si)
NormalBumpEvalContext(const SurfaceInteraction &si)
: p(si.p()),
uv(si.uv),
n(si.n),
......@@ -68,7 +68,7 @@ struct BumpEvalContext {
faceIndex);
}
// BumpEvalContext Public Members
// NormalBumpEvalContext Public Members
Point3f p;
Point2f uv;
Normal3f n;
......@@ -82,56 +82,59 @@ struct BumpEvalContext {
int faceIndex = 0;
};
// Bump-mapping Function Definitions
// Normal Mapping Function Definitions
inline PBRT_CPU_GPU void NormalMap(const Image *normalMap,
const NormalBumpEvalContext &ctx, Vector3f *dpdu,
Vector3f *dpdv) {
// Get normalized normal vector from normal map
WrapMode2D wrap(WrapMode::Repeat);
Point2f uv(ctx.uv[0], 1 - ctx.uv[1]);
Vector3f ns(2 * normalMap->BilerpChannel(uv, 0, wrap) - 1,
2 * normalMap->BilerpChannel(uv, 1, wrap) - 1,
2 * normalMap->BilerpChannel(uv, 2, wrap) - 1);
ns = Normalize(ns);
// Transform tangent-space normal to rendering space
Frame frame = Frame::FromZ(ctx.shading.n);
ns = frame.FromLocal(ns);
// Find $\dpdu$ and $\dpdv$ that give shading normal
Float ulen = Length(ctx.shading.dpdu), vlen = Length(ctx.shading.dpdv);
*dpdu = Normalize(GramSchmidt(ctx.shading.dpdu, ns)) * ulen;
*dpdv = Normalize(Cross(ns, *dpdu)) * vlen;
}
// Bump Mapping Function Definitions
template <typename TextureEvaluator>
PBRT_CPU_GPU void Bump(TextureEvaluator texEval, FloatTexture displacement,
const Image *normalMap, const BumpEvalContext &ctx, Vector3f *dpdu,
Vector3f *dpdv) {
DCHECK(displacement || normalMap);
if (displacement) {
if (displacement)
DCHECK(texEval.CanEvaluate({displacement}, {}));
// Compute offset positions and evaluate displacement texture
TextureEvalContext shiftedCtx = ctx;
// Shift _shiftedCtx_ _du_ in the $u$ direction
Float du = .5f * (std::abs(ctx.dudx) + std::abs(ctx.dudy));
if (du == 0)
du = .0005f;
shiftedCtx.p = ctx.p + du * ctx.shading.dpdu;
shiftedCtx.uv = ctx.uv + Vector2f(du, 0.f);
Float uDisplace = texEval(displacement, shiftedCtx);
// Shift _shiftedCtx_ _dv_ in the $v$ direction
Float dv = .5f * (std::abs(ctx.dvdx) + std::abs(ctx.dvdy));
if (dv == 0)
dv = .0005f;
shiftedCtx.p = ctx.p + dv * ctx.shading.dpdv;
shiftedCtx.uv = ctx.uv + Vector2f(0.f, dv);
Float vDisplace = texEval(displacement, shiftedCtx);
Float displace = texEval(displacement, ctx);
// Compute bump-mapped differential geometry
*dpdu = ctx.shading.dpdu + (uDisplace - displace) / du * Vector3f(ctx.shading.n) +
displace * Vector3f(ctx.shading.dndu);
*dpdv = ctx.shading.dpdv + (vDisplace - displace) / dv * Vector3f(ctx.shading.n) +
displace * Vector3f(ctx.shading.dndv);
} else {
// Sample normal map to compute shading normal
WrapMode2D wrap(WrapMode::Repeat);
Point2f uv(ctx.uv[0], 1 - ctx.uv[1]);
Vector3f ns(2 * normalMap->BilerpChannel(uv, 0, wrap) - 1,
2 * normalMap->BilerpChannel(uv, 1, wrap) - 1,
2 * normalMap->BilerpChannel(uv, 2, wrap) - 1);
ns = Normalize(ns);
Frame frame = Frame::FromZ(ctx.shading.n);
ns = frame.FromLocal(ns);
Float ulen = Length(ctx.shading.dpdu), vlen = Length(ctx.shading.dpdv);
*dpdu = Normalize(GramSchmidt(ctx.shading.dpdu, ns)) * ulen;
*dpdv = Normalize(Cross(ns, *dpdu)) * vlen;
}
PBRT_CPU_GPU void BumpMap(TextureEvaluator texEval, FloatTexture displacement,
const NormalBumpEvalContext &ctx, Vector3f *dpdu,
Vector3f *dpdv) {
DCHECK(texEval.CanEvaluate({displacement}, {}));
// Compute offset positions and evaluate displacement texture
TextureEvalContext shiftedCtx = ctx;
// Shift _shiftedCtx_ _du_ in the $u$ direction
Float du = .5f * (std::abs(ctx.dudx) + std::abs(ctx.dudy));
if (du == 0)
du = .0005f;
shiftedCtx.p = ctx.p + du * ctx.shading.dpdu;
shiftedCtx.uv = ctx.uv + Vector2f(du, 0.f);
Float uDisplace = texEval(displacement, shiftedCtx);
// Shift _shiftedCtx_ _dv_ in the $v$ direction
Float dv = .5f * (std::abs(ctx.dvdx) + std::abs(ctx.dvdy));
if (dv == 0)
dv = .0005f;
shiftedCtx.p = ctx.p + dv * ctx.shading.dpdv;
shiftedCtx.uv = ctx.uv + Vector2f(0.f, dv);
Float vDisplace = texEval(displacement, shiftedCtx);
Float displace = texEval(displacement, ctx);
// Compute bump-mapped differential geometry
*dpdu = ctx.shading.dpdu + (uDisplace - displace) / du * Vector3f(ctx.shading.n) +
displace * Vector3f(ctx.shading.dndu);
*dpdv = ctx.shading.dpdv + (vDisplace - displace) / dv * Vector3f(ctx.shading.n) +
displace * Vector3f(ctx.shading.dndv);
}
// DielectricMaterial Definition
......@@ -182,6 +185,8 @@ class DielectricMaterial {
Float sampledEta = eta(lambda[0]);
if (!eta.template Is<ConstantSpectrum>())
lambda.TerminateSecondary();
// Handle edge case in case lambda[0] is beyond the wavelengths stored by the
// Spectrum.
if (sampledEta == 0)
sampledEta = 1;
......@@ -203,8 +208,8 @@ class DielectricMaterial {
FloatTexture displacement;
Image *normalMap;
FloatTexture uRoughness, vRoughness;
Spectrum eta;
bool remapRoughness;
Spectrum eta;
};
// ThinDielectricMaterial Definition
......@@ -226,6 +231,8 @@ class ThinDielectricMaterial {
Float sampledEta = eta(lambda[0]);
if (!eta.template Is<ConstantSpectrum>())
lambda.TerminateSecondary();
// Handle edge case in case lambda[0] is beyond the wavelengths stored by the
// Spectrum.
if (sampledEta == 0)
sampledEta = 1;
......@@ -276,6 +283,18 @@ class MixMaterial {
materials[1] = m[1];
}
template <typename TextureEvaluator>
PBRT_CPU_GPU Material ChooseMaterial(TextureEvaluator texEval,
MaterialEvalContext ctx) const {
Float amt = texEval(amount, ctx);
if (amt <= 0)
return materials[0];
if (amt >= 1)
return materials[1];
Float u = HashFloat(ctx.p, ctx.wo, materials[0], materials[1]);
return (amt < u) ? materials[0] : materials[1];
}
PBRT_CPU_GPU
Material GetMaterial(int i) const { return materials[i]; }
......@@ -318,19 +337,6 @@ class MixMaterial {
return texEval.CanEvaluate({amount}, {});
}
template <typename TextureEvaluator>
PBRT_CPU_GPU Material ChooseMaterial(TextureEvaluator texEval,
MaterialEvalContext ctx) const {
Float amt = texEval(amount, ctx);
if (amt <= 0)
return materials[0];
if (amt >= 1)
return materials[1];
Float u = HashFloat(ctx.p, ctx.wo, materials[0], materials[1]);
return (amt < u) ? materials[0] : materials[1];
}
template <typename TextureEvaluator>
PBRT_CPU_GPU BSDF GetBSDF(TextureEvaluator texEval, MaterialEvalContext ctx,
SampledWavelengths &lambda, void *bxdf) const {
......
......@@ -99,13 +99,23 @@ void WavefrontPathIntegrator::EvaluateMaterialAndBSDF(MaterialEvalQueue *evalQue
Vector3f dpdus = w.dpdus;
FloatTexture displacement = w.material->GetDisplacement();
const Image *normalMap = w.material->GetNormalMap();
if (displacement || normalMap) {
// Call _Bump()_ to find shading geometry
if (normalMap) {
// Call _NormalMap()_ to find shading geometry
NormalBumpEvalContext bctx =
w.GetNormalBumpEvalContext(dudx, dudy, dvdx, dvdy);
Vector3f dpdvs;
NormalMap(normalMap, bctx, &dpdus, &dpdvs);
ns = Normal3f(Normalize(Cross(dpdus, dpdvs)));
ns = FaceForward(ns, w.n);
} else if (displacement) {
// Call _BumpMap()_ to find shading geometry
if (displacement)
DCHECK(texEval.CanEvaluate({displacement}, {}));
BumpEvalContext bctx = w.GetBumpEvalContext(dudx, dudy, dvdx, dvdy);
NormalBumpEvalContext bctx =
w.GetNormalBumpEvalContext(dudx, dudy, dvdx, dvdy);
Vector3f dpdvs;
Bump(texEval, displacement, normalMap, bctx, &dpdus, &dpdvs);
BumpMap(texEval, displacement, bctx, &dpdus, &dpdvs);
ns = Normal3f(Normalize(Cross(dpdus, dpdvs)));
ns = FaceForward(ns, w.n);
}
......
......@@ -280,9 +280,9 @@ template <typename ConcreteMaterial>
struct MaterialEvalWorkItem {
// MaterialEvalWorkItem Public Methods
PBRT_CPU_GPU
BumpEvalContext GetBumpEvalContext(Float dudx, Float dudy, Float dvdx,
Float dvdy) const {
BumpEvalContext ctx;
NormalBumpEvalContext GetNormalBumpEvalContext(Float dudx, Float dudy, Float dvdx,
Float dvdy) const {
NormalBumpEvalContext ctx;
ctx.p = Point3f(pi);
ctx.uv = uv;
ctx.dudx = dudx;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册