diff --git a/src/pbrt/base/material.h b/src/pbrt/base/material.h index b155a54156ad668b23a1b0e186cde21a2ed14f44..0a749065b6de4192da6a008f2b73fa7034f1d51b 100644 --- a/src/pbrt/base/material.h +++ b/src/pbrt/base/material.h @@ -66,6 +66,8 @@ class MaterialHandle PBRT_CPU_GPU inline FloatTextureHandle GetDisplacement() const; + PBRT_CPU_GPU inline const Image *GetNormalMap() const; + PBRT_CPU_GPU inline bool IsTransparent() const; PBRT_CPU_GPU inline bool HasSubsurfaceScattering() const; }; diff --git a/src/pbrt/cpu/integrators_test.cpp b/src/pbrt/cpu/integrators_test.cpp index 4c225944a58fb83f245292eb655964c392e3d172..671ed905a869664b12d186cb56eada2e22a767e9 100644 --- a/src/pbrt/cpu/integrators_test.cpp +++ b/src/pbrt/cpu/integrators_test.cpp @@ -79,7 +79,7 @@ std::vector GetScenes() { SpectrumTextureHandle Kd = alloc.new_object(&cs); FloatTextureHandle sigma = alloc.new_object(0.); // FIXME: here and below, Materials leak... - MaterialHandle material = new DiffuseMaterial(Kd, sigma, nullptr); + MaterialHandle material = new DiffuseMaterial(Kd, sigma, nullptr, nullptr); MediumInterface mediumInterface; std::vector prims; @@ -106,7 +106,7 @@ std::vector GetScenes() { static ConstantSpectrum cs(0.5); SpectrumTextureHandle Kd = alloc.new_object(&cs); FloatTextureHandle sigma = alloc.new_object(0.); - const MaterialHandle material = new DiffuseMaterial(Kd, sigma, nullptr); + const MaterialHandle material = new DiffuseMaterial(Kd, sigma, nullptr, nullptr); MediumInterface mediumInterface; std::vector prims; @@ -136,7 +136,7 @@ std::vector GetScenes() { static ConstantSpectrum cs(0.5); SpectrumTextureHandle Kd = alloc.new_object(&cs); FloatTextureHandle sigma = alloc.new_object(0.); - const MaterialHandle material = new DiffuseMaterial(Kd, sigma, nullptr); + const MaterialHandle material = new DiffuseMaterial(Kd, sigma, nullptr, nullptr); // We have to do this little dance here to make sure the spectrum is // properly normalized (this is usually all handled inside *Light::Create()) diff --git a/src/pbrt/gpu/surfscatter.cpp b/src/pbrt/gpu/surfscatter.cpp index e8d7b9fc509ad6f258e2264f372a94dda34da9db..79c51adbb9c7c9ea6d8b3b066ae4864b6c2c040b 100644 --- a/src/pbrt/gpu/surfscatter.cpp +++ b/src/pbrt/gpu/surfscatter.cpp @@ -84,11 +84,13 @@ void GPUPathIntegrator::EvaluateMaterialAndBSDF(TextureEvaluator texEval, Normal3f ns = w.ns; Vector3f dpdus = w.dpdus; FloatTextureHandle displacement = w.material->GetDisplacement(); - if (displacement) { - DCHECK(texEval.CanEvaluate({displacement}, {})); + const Image *normalMap = w.material->GetNormalMap(); + if (displacement || normalMap) { + if (displacement) + DCHECK(texEval.CanEvaluate({displacement}, {})); BumpEvalContext bctx = w.GetBumpEvalContext(); Vector3f dpdvs; - Bump(texEval, displacement, bctx, &dpdus, &dpdvs); + Bump(texEval, displacement, normalMap, bctx, &dpdus, &dpdvs); ns = Normal3f(Normalize(Cross(dpdus, dpdvs))); ns = FaceForward(ns, w.n); } diff --git a/src/pbrt/interaction.cpp b/src/pbrt/interaction.cpp index 6673f3a6f792b20e1230c9c3610a9a36ec30425b..b0768834b8ded6141743c37467e9f82d444ae681 100644 --- a/src/pbrt/interaction.cpp +++ b/src/pbrt/interaction.cpp @@ -165,9 +165,10 @@ BSDF SurfaceInteraction::GetBSDF(const RayDifferential &ray, SampledWavelengths // Evaluate bump map and compute shading normal FloatTextureHandle displacement = material.GetDisplacement(); - if (displacement) { + const Image *normalMap = material.GetNormalMap(); + if (displacement || normalMap) { Vector3f dpdu, dpdv; - Bump(UniversalTextureEvaluator(), displacement, *this, &dpdu, &dpdv); + Bump(UniversalTextureEvaluator(), displacement, normalMap, *this, &dpdu, &dpdv); SetShadingGeometry(Normal3f(Normalize(Cross(dpdu, dpdv))), dpdu, dpdv, shading.dndu, shading.dndv, false); } diff --git a/src/pbrt/materials.cpp b/src/pbrt/materials.cpp index 458c357ee0f4a532202a14e98548cc301580b74e..506275f2fb796874d0f2d438845a0d755f3299f5 100644 --- a/src/pbrt/materials.cpp +++ b/src/pbrt/materials.cpp @@ -57,8 +57,23 @@ DielectricMaterial *DielectricMaterial::Create( FloatTextureHandle displacement = parameters.GetFloatTextureOrNull("displacement", alloc); bool remapRoughness = parameters.GetOneBool("remaproughness", true); + // Initialize normal map for material + Image *normalMap = nullptr; + std::string normalMapFilename = parameters.GetOneString("normalmap", ""); + if (!normalMapFilename.empty()) { + ImageAndMetadata immeta = + Image::Read(normalMapFilename, Allocator(), ColorEncodingHandle::Linear); + Image &image = immeta.image; + ImageChannelDesc rgbDesc = image.GetChannelDesc({"R", "G", "B"}); + if (!rgbDesc) + Error(loc, "%s: normal map image must contain R, G, and B channels", + normalMapFilename); + normalMap = alloc.new_object(alloc); + *normalMap = image.SelectChannels(rgbDesc); + } + return alloc.new_object(uRoughness, vRoughness, etaF, etaS, - displacement, remapRoughness); + displacement, normalMap, remapRoughness); } // ThinDielectricMaterial Method Definitions @@ -82,8 +97,22 @@ ThinDielectricMaterial *ThinDielectricMaterial::Create( FloatTextureHandle displacement = parameters.GetFloatTextureOrNull("displacement", alloc); + // Initialize normal map for material + Image *normalMap = nullptr; + std::string normalMapFilename = parameters.GetOneString("normalmap", ""); + if (!normalMapFilename.empty()) { + ImageAndMetadata immeta = + Image::Read(normalMapFilename, Allocator(), ColorEncodingHandle::Linear); + Image &image = immeta.image; + ImageChannelDesc rgbDesc = image.GetChannelDesc({"R", "G", "B"}); + if (!rgbDesc) + Error(loc, "%s: normal map image must contain R, G, and B channels", + normalMapFilename); + normalMap = alloc.new_object(alloc); + *normalMap = image.SelectChannels(rgbDesc); + } - return alloc.new_object(etaF, etaS, displacement); + return alloc.new_object(etaF, etaS, displacement, normalMap); } // MixMaterial Method Definitions @@ -189,7 +218,22 @@ DiffuseMaterial *DiffuseMaterial::Create(const TextureParameterDictionary ¶m FloatTextureHandle sigma = parameters.GetFloatTexture("sigma", 0.f, alloc); FloatTextureHandle displacement = parameters.GetFloatTextureOrNull("displacement", alloc); - return alloc.new_object(reflectance, sigma, displacement); + // Initialize normal map for material + Image *normalMap = nullptr; + std::string normalMapFilename = parameters.GetOneString("normalmap", ""); + if (!normalMapFilename.empty()) { + ImageAndMetadata immeta = + Image::Read(normalMapFilename, Allocator(), ColorEncodingHandle::Linear); + Image &image = immeta.image; + ImageChannelDesc rgbDesc = image.GetChannelDesc({"R", "G", "B"}); + if (!rgbDesc) + Error(loc, "%s: normal map image must contain R, G, and B channels", + normalMapFilename); + normalMap = alloc.new_object(alloc); + *normalMap = image.SelectChannels(rgbDesc); + } + + return alloc.new_object(reflectance, sigma, displacement, normalMap); } // ConductorMaterial Method Definitions @@ -217,8 +261,23 @@ ConductorMaterial *ConductorMaterial::Create(const TextureParameterDictionary &p FloatTextureHandle displacement = parameters.GetFloatTextureOrNull("displacement", alloc); bool remapRoughness = parameters.GetOneBool("remaproughness", true); + // Initialize normal map for material + Image *normalMap = nullptr; + std::string normalMapFilename = parameters.GetOneString("normalmap", ""); + if (!normalMapFilename.empty()) { + ImageAndMetadata immeta = + Image::Read(normalMapFilename, Allocator(), ColorEncodingHandle::Linear); + Image &image = immeta.image; + ImageChannelDesc rgbDesc = image.GetChannelDesc({"R", "G", "B"}); + if (!rgbDesc) + Error(loc, "%s: normal map image must contain R, G, and B channels", + normalMapFilename); + normalMap = alloc.new_object(alloc); + *normalMap = image.SelectChannels(rgbDesc); + } + return alloc.new_object(eta, k, uRoughness, vRoughness, - displacement, remapRoughness); + displacement, normalMap, remapRoughness); } // CoatedDiffuseMaterial Method Definitions @@ -263,9 +322,24 @@ CoatedDiffuseMaterial *CoatedDiffuseMaterial::Create( FloatTextureHandle displacement = parameters.GetFloatTextureOrNull("displacement", alloc); bool remapRoughness = parameters.GetOneBool("remaproughness", true); - return alloc.new_object(reflectance, uRoughness, vRoughness, - thickness, albedo, g, eta, - displacement, remapRoughness, config); + // Initialize normal map for material + Image *normalMap = nullptr; + std::string normalMapFilename = parameters.GetOneString("normalmap", ""); + if (!normalMapFilename.empty()) { + ImageAndMetadata immeta = + Image::Read(normalMapFilename, Allocator(), ColorEncodingHandle::Linear); + Image &image = immeta.image; + ImageChannelDesc rgbDesc = image.GetChannelDesc({"R", "G", "B"}); + if (!rgbDesc) + Error(loc, "%s: normal map image must contain R, G, and B channels", + normalMapFilename); + normalMap = alloc.new_object(alloc); + *normalMap = image.SelectChannels(rgbDesc); + } + + return alloc.new_object( + reflectance, uRoughness, vRoughness, thickness, albedo, g, eta, displacement, + normalMap, remapRoughness, config); } std::string CoatedConductorMaterial::ToString() const { @@ -329,10 +403,25 @@ CoatedConductorMaterial *CoatedConductorMaterial::Create( parameters.GetFloatTextureOrNull("displacement", alloc); bool remapRoughness = parameters.GetOneBool("remaproughness", true); + // Initialize normal map for material + Image *normalMap = nullptr; + std::string normalMapFilename = parameters.GetOneString("normalmap", ""); + if (!normalMapFilename.empty()) { + ImageAndMetadata immeta = + Image::Read(normalMapFilename, Allocator(), ColorEncodingHandle::Linear); + Image &image = immeta.image; + ImageChannelDesc rgbDesc = image.GetChannelDesc({"R", "G", "B"}); + if (!rgbDesc) + Error(loc, "%s: normal map image must contain R, G, and B channels", + normalMapFilename); + normalMap = alloc.new_object(alloc); + *normalMap = image.SelectChannels(rgbDesc); + } + return alloc.new_object( interfaceURoughness, interfaceVRoughness, thickness, interfaceEta, g, albedo, conductorURoughness, conductorVRoughness, conductorEta, k, displacement, - remapRoughness, config); + normalMap, remapRoughness, config); } // SubsurfaceMaterial Method Definitions @@ -410,9 +499,24 @@ SubsurfaceMaterial *SubsurfaceMaterial::Create( FloatTextureHandle displacement = parameters.GetFloatTextureOrNull("displacement", alloc); bool remapRoughness = parameters.GetOneBool("remaproughness", true); - return alloc.new_object(scale, sigma_a, sigma_s, reflectance, mfp, - g, eta, uRoughness, vRoughness, - displacement, remapRoughness, alloc); + // Initialize normal map for material + Image *normalMap = nullptr; + std::string normalMapFilename = parameters.GetOneString("normalmap", ""); + if (!normalMapFilename.empty()) { + ImageAndMetadata immeta = + Image::Read(normalMapFilename, Allocator(), ColorEncodingHandle::Linear); + Image &image = immeta.image; + ImageChannelDesc rgbDesc = image.GetChannelDesc({"R", "G", "B"}); + if (!rgbDesc) + Error(loc, "%s: normal map image must contain R, G, and B channels", + normalMapFilename); + normalMap = alloc.new_object(alloc); + *normalMap = image.SelectChannels(rgbDesc); + } + + return alloc.new_object( + scale, sigma_a, sigma_s, reflectance, mfp, g, eta, uRoughness, vRoughness, + displacement, normalMap, remapRoughness, alloc); } // DiffuseTransmissionMaterial Method Definitions @@ -441,18 +545,35 @@ DiffuseTransmissionMaterial *DiffuseTransmissionMaterial::Create( bool remapRoughness = parameters.GetOneBool("remaproughness", true); FloatTextureHandle sigma = parameters.GetFloatTexture("sigma", 0.f, alloc); Float scale = parameters.GetOneFloat("scale", 1.f); - return alloc.new_object(reflectance, transmittance, - sigma, displacement, scale); + // Initialize normal map for material + Image *normalMap = nullptr; + std::string normalMapFilename = parameters.GetOneString("normalmap", ""); + if (!normalMapFilename.empty()) { + ImageAndMetadata immeta = + Image::Read(normalMapFilename, Allocator(), ColorEncodingHandle::Linear); + Image &image = immeta.image; + ImageChannelDesc rgbDesc = image.GetChannelDesc({"R", "G", "B"}); + if (!rgbDesc) + Error(loc, "%s: normal map image must contain R, G, and B channels", + normalMapFilename); + normalMap = alloc.new_object(alloc); + *normalMap = image.SelectChannels(rgbDesc); + } + + return alloc.new_object( + reflectance, transmittance, sigma, displacement, normalMap, scale); } MeasuredMaterial::MeasuredMaterial(const std::string &filename, - FloatTextureHandle displacement, Allocator alloc) - : displacement(displacement) { + FloatTextureHandle displacement, Image *normalMap, + Allocator alloc) + : displacement(displacement), normalMap(normalMap) { brdf = MeasuredBxDF::BRDFDataFromFile(filename, alloc); } std::string MeasuredMaterial::ToString() const { - return StringPrintf("[ MeasuredMaterial displacement: %s ]", displacement); + return StringPrintf("[ MeasuredMaterial displacement: %s normalMap: %p ]", + displacement, normalMap); } MeasuredMaterial *MeasuredMaterial::Create(const TextureParameterDictionary ¶meters, @@ -464,7 +585,22 @@ MeasuredMaterial *MeasuredMaterial::Create(const TextureParameterDictionary &par } FloatTextureHandle displacement = parameters.GetFloatTextureOrNull("displacement", alloc); - return alloc.new_object(filename, displacement, alloc); + // Initialize normal map for material + Image *normalMap = nullptr; + std::string normalMapFilename = parameters.GetOneString("normalmap", ""); + if (!normalMapFilename.empty()) { + ImageAndMetadata immeta = + Image::Read(normalMapFilename, Allocator(), ColorEncodingHandle::Linear); + Image &image = immeta.image; + ImageChannelDesc rgbDesc = image.GetChannelDesc({"R", "G", "B"}); + if (!rgbDesc) + Error(loc, "%s: normal map image must contain R, G, and B channels", + normalMapFilename); + normalMap = alloc.new_object(alloc); + *normalMap = image.SelectChannels(rgbDesc); + } + + return alloc.new_object(filename, displacement, normalMap, alloc); } std::string MaterialHandle::ToString() const { diff --git a/src/pbrt/materials.h b/src/pbrt/materials.h index b7b50be77facc8b7d737fe1dce4c260b2a286ff3..7117d4f6db5e00cb95e3e381f82a974eb2afcc74 100644 --- a/src/pbrt/materials.h +++ b/src/pbrt/materials.h @@ -83,34 +83,52 @@ struct BumpEvalContext { // Bump-mapping Function Definitions template PBRT_CPU_GPU void Bump(TextureEvaluator texEval, FloatTextureHandle displacement, - const BumpEvalContext &ctx, Vector3f *dpdu, Vector3f *dpdv) { - DCHECK(displacement != nullptr); - 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); + const Image *normalMap, const BumpEvalContext &ctx, Vector3f *dpdu, + Vector3f *dpdv) { + DCHECK(displacement != nullptr || normalMap != nullptr); + 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 + Point2f uv(ctx.uv[0], 1 - ctx.uv[1]); + Vector3f ns(2 * normalMap->BilerpChannel(uv, 0) - 1, + 2 * normalMap->BilerpChannel(uv, 1) - 1, + 2 * normalMap->BilerpChannel(uv, 2) - 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; + } } // DielectricMaterial Definition @@ -123,8 +141,10 @@ class DielectricMaterial { // DielectricMaterial Public Methods DielectricMaterial(FloatTextureHandle uRoughness, FloatTextureHandle vRoughness, FloatTextureHandle etaF, SpectrumTextureHandle etaS, - FloatTextureHandle displacement, bool remapRoughness) + FloatTextureHandle displacement, Image *normalMap, + bool remapRoughness) : displacement(displacement), + normalMap(normalMap), uRoughness(uRoughness), vRoughness(vRoughness), etaF(etaF), @@ -142,6 +162,8 @@ class DielectricMaterial { PBRT_CPU_GPU FloatTextureHandle GetDisplacement() const { return displacement; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { return normalMap; } static DielectricMaterial *Create(const TextureParameterDictionary ¶meters, const FileLoc *loc, Allocator alloc); @@ -184,6 +206,7 @@ class DielectricMaterial { private: // DielectricMaterial Private Members FloatTextureHandle displacement; + Image *normalMap; FloatTextureHandle uRoughness, vRoughness, etaF; SpectrumTextureHandle etaS; bool remapRoughness; @@ -222,8 +245,8 @@ class ThinDielectricMaterial { bool IsTransparent() const { return true; } ThinDielectricMaterial(FloatTextureHandle etaF, SpectrumTextureHandle etaS, - FloatTextureHandle displacement) - : displacement(displacement), etaF(etaF), etaS(etaS) { + FloatTextureHandle displacement, Image *normalMap) + : displacement(displacement), normalMap(normalMap), etaF(etaF), etaS(etaS) { CHECK((bool)etaF ^ (bool)etaS); } @@ -231,6 +254,8 @@ class ThinDielectricMaterial { PBRT_CPU_GPU FloatTextureHandle GetDisplacement() const { return displacement; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { return normalMap; } static ThinDielectricMaterial *Create(const TextureParameterDictionary ¶meters, const FileLoc *loc, Allocator alloc); @@ -246,6 +271,7 @@ class ThinDielectricMaterial { private: // ThinDielectricMaterial Private Data FloatTextureHandle displacement; + Image *normalMap; FloatTextureHandle etaF; SpectrumTextureHandle etaS; }; @@ -276,6 +302,14 @@ class MixMaterial { return nullptr; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { +#ifndef PBRT_IS_GPU_CODE + LOG_FATAL("Shouldn't be called"); +#endif + return nullptr; + } + static MixMaterial *Create(MaterialHandle materials[2], const TextureParameterDictionary ¶meters, const FileLoc *loc, Allocator alloc); @@ -395,6 +429,8 @@ class HairMaterial { PBRT_CPU_GPU FloatTextureHandle GetDisplacement() const { return nullptr; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { return nullptr; } template PBRT_CPU_GPU void GetBSSRDF(TextureEvaluator texEval, MaterialEvalContext ctx, @@ -424,6 +460,8 @@ class DiffuseMaterial { PBRT_CPU_GPU FloatTextureHandle GetDisplacement() const { return displacement; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { return normalMap; } static DiffuseMaterial *Create(const TextureParameterDictionary ¶meters, const FileLoc *loc, Allocator alloc); @@ -438,8 +476,11 @@ class DiffuseMaterial { std::string ToString() const; DiffuseMaterial(SpectrumTextureHandle reflectance, FloatTextureHandle sigma, - FloatTextureHandle displacement) - : displacement(displacement), reflectance(reflectance), sigma(sigma) {} + FloatTextureHandle displacement, Image *normalMap) + : displacement(displacement), + normalMap(normalMap), + reflectance(reflectance), + sigma(sigma) {} template PBRT_CPU_GPU bool CanEvaluateTextures(TextureEvaluator texEval) const { @@ -458,6 +499,7 @@ class DiffuseMaterial { private: // DiffuseMaterial Private Members FloatTextureHandle displacement; + Image *normalMap; SpectrumTextureHandle reflectance; FloatTextureHandle sigma; }; @@ -493,8 +535,10 @@ class ConductorMaterial { ConductorMaterial(SpectrumTextureHandle eta, SpectrumTextureHandle k, FloatTextureHandle uRoughness, FloatTextureHandle vRoughness, - FloatTextureHandle displacement, bool remapRoughness) + FloatTextureHandle displacement, Image *normalMap, + bool remapRoughness) : displacement(displacement), + normalMap(normalMap), eta(eta), k(k), uRoughness(uRoughness), @@ -505,6 +549,8 @@ class ConductorMaterial { PBRT_CPU_GPU FloatTextureHandle GetDisplacement() const { return displacement; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { return normalMap; } static ConductorMaterial *Create(const TextureParameterDictionary ¶meters, const FileLoc *loc, Allocator alloc); @@ -521,6 +567,7 @@ class ConductorMaterial { private: // ConductorMaterial Private Data FloatTextureHandle displacement; + Image *normalMap; SpectrumTextureHandle eta, k; FloatTextureHandle uRoughness, vRoughness; bool remapRoughness; @@ -536,9 +583,10 @@ class CoatedDiffuseMaterial { FloatTextureHandle uRoughness, FloatTextureHandle vRoughness, FloatTextureHandle thickness, SpectrumTextureHandle albedo, FloatTextureHandle g, FloatTextureHandle eta, - FloatTextureHandle displacement, bool remapRoughness, - LayeredBxDFConfig config) + FloatTextureHandle displacement, Image *normalMap, + bool remapRoughness, LayeredBxDFConfig config) : displacement(displacement), + normalMap(normalMap), reflectance(reflectance), uRoughness(uRoughness), vRoughness(vRoughness), @@ -584,6 +632,8 @@ class CoatedDiffuseMaterial { PBRT_CPU_GPU FloatTextureHandle GetDisplacement() const { return displacement; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { return normalMap; } static CoatedDiffuseMaterial *Create(const TextureParameterDictionary ¶meters, const FileLoc *loc, Allocator alloc); @@ -600,6 +650,7 @@ class CoatedDiffuseMaterial { private: // CoatedDiffuseMaterial Private Members FloatTextureHandle displacement; + Image *normalMap; SpectrumTextureHandle reflectance, albedo; FloatTextureHandle uRoughness, vRoughness, thickness, g, eta; bool remapRoughness; @@ -619,9 +670,10 @@ class CoatedConductorMaterial { FloatTextureHandle conductorURoughness, FloatTextureHandle conductorVRoughness, SpectrumTextureHandle conductorEta, SpectrumTextureHandle k, - FloatTextureHandle displacement, bool remapRoughness, - LayeredBxDFConfig config) + FloatTextureHandle displacement, Image *normalMap, + bool remapRoughness, LayeredBxDFConfig config) : displacement(displacement), + normalMap(normalMap), interfaceURoughness(interfaceURoughness), interfaceVRoughness(interfaceVRoughness), thickness(thickness), @@ -681,6 +733,8 @@ class CoatedConductorMaterial { PBRT_CPU_GPU FloatTextureHandle GetDisplacement() const { return displacement; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { return normalMap; } static CoatedConductorMaterial *Create(const TextureParameterDictionary ¶meters, const FileLoc *loc, Allocator alloc); @@ -697,6 +751,7 @@ class CoatedConductorMaterial { private: // CoatedConductorMaterial Private Members FloatTextureHandle displacement; + Image *normalMap; FloatTextureHandle interfaceURoughness, interfaceVRoughness, thickness, interfaceEta; FloatTextureHandle g; SpectrumTextureHandle albedo; @@ -718,9 +773,10 @@ class SubsurfaceMaterial { SpectrumTextureHandle sigma_s, SpectrumTextureHandle reflectance, SpectrumTextureHandle mfp, Float g, Float eta, FloatTextureHandle uRoughness, FloatTextureHandle vRoughness, - FloatTextureHandle displacement, bool remapRoughness, - Allocator alloc) + FloatTextureHandle displacement, Image *normalMap, + bool remapRoughness, Allocator alloc) : displacement(displacement), + normalMap(normalMap), scale(scale), sigma_a(sigma_a), sigma_s(sigma_s), @@ -781,6 +837,9 @@ class SubsurfaceMaterial { PBRT_CPU_GPU FloatTextureHandle GetDisplacement() const { return displacement; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { return normalMap; } + PBRT_CPU_GPU bool IsTransparent() const { return false; } PBRT_CPU_GPU @@ -794,6 +853,7 @@ class SubsurfaceMaterial { private: // SubsurfaceMaterial Private Members FloatTextureHandle displacement; + Image *normalMap; SpectrumTextureHandle sigma_a, sigma_s, reflectance, mfp; Float scale, eta; FloatTextureHandle uRoughness, vRoughness; @@ -810,8 +870,9 @@ class DiffuseTransmissionMaterial { DiffuseTransmissionMaterial(SpectrumTextureHandle reflectance, SpectrumTextureHandle transmittance, FloatTextureHandle sigma, FloatTextureHandle displacement, - Float scale) + Image *normalMap, Float scale) : displacement(displacement), + normalMap(normalMap), reflectance(reflectance), transmittance(transmittance), sigma(sigma), @@ -836,6 +897,8 @@ class DiffuseTransmissionMaterial { PBRT_CPU_GPU FloatTextureHandle GetDisplacement() const { return displacement; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { return normalMap; } static DiffuseTransmissionMaterial *Create( const TextureParameterDictionary ¶meters, const FileLoc *loc, @@ -853,6 +916,7 @@ class DiffuseTransmissionMaterial { private: // DiffuseTransmissionMaterial Private Data FloatTextureHandle displacement; + Image *normalMap; SpectrumTextureHandle reflectance, transmittance; FloatTextureHandle sigma; Float scale; @@ -872,7 +936,7 @@ class MeasuredMaterial { } MeasuredMaterial(const std::string &filename, FloatTextureHandle displacement, - Allocator alloc); + Image *normalMap, Allocator alloc); static const char *Name() { return "MeasuredMaterial"; } @@ -883,6 +947,8 @@ class MeasuredMaterial { PBRT_CPU_GPU FloatTextureHandle GetDisplacement() const { return displacement; } + PBRT_CPU_GPU + const Image *GetNormalMap() const { return normalMap; } static MeasuredMaterial *Create(const TextureParameterDictionary ¶meters, const FileLoc *loc, Allocator alloc); @@ -899,6 +965,7 @@ class MeasuredMaterial { private: // MeasuredMaterial Private Members FloatTextureHandle displacement; + Image *normalMap; const MeasuredBRDF *brdf; }; @@ -959,6 +1026,11 @@ inline FloatTextureHandle MaterialHandle::GetDisplacement() const { return Dispatch(disp); } +inline const Image *MaterialHandle::GetNormalMap() const { + auto nmap = [&](auto ptr) { return ptr->GetNormalMap(); }; + return Dispatch(nmap); +} + } // namespace pbrt #endif // PBRT_MATERIALS_H