diff --git a/data/tests/test_bsdf.xml b/data/tests/test_bsdf.xml
index 94df5b3c..2abd7c4f 100644
--- a/data/tests/test_bsdf.xml
+++ b/data/tests/test_bsdf.xml
@@ -6,6 +6,8 @@
+
+
diff --git a/doc/images/bsdf_coating_roughconductor.jpg b/doc/images/bsdf_coating_roughconductor.jpg
index 4a2b4f98..2fc9b633 100644
Binary files a/doc/images/bsdf_coating_roughconductor.jpg and b/doc/images/bsdf_coating_roughconductor.jpg differ
diff --git a/doc/images/bsdf_roughconductor_copper.jpg b/doc/images/bsdf_roughconductor_copper.jpg
index 2472f5f7..38d45582 100644
Binary files a/doc/images/bsdf_roughconductor_copper.jpg and b/doc/images/bsdf_roughconductor_copper.jpg differ
diff --git a/include/mitsuba/hw/basicshader.h b/include/mitsuba/hw/basicshader.h
index e8cff643..3c2d5e62 100644
--- a/include/mitsuba/hw/basicshader.h
+++ b/include/mitsuba/hw/basicshader.h
@@ -55,6 +55,10 @@ public:
return m_value;
}
+ inline bool isConstant() const {
+ return true;
+ }
+
inline std::string toString() const {
std::ostringstream oss;
oss << "ConstantSpectrumTexture[value=" << m_value.toString() << "]";
@@ -99,6 +103,10 @@ public:
return Spectrum(m_value);
}
+ inline bool isConstant() const {
+ return true;
+ }
+
inline std::string toString() const {
std::ostringstream oss;
oss << "ConstantFloatTexture[value=" << m_value << "]";
diff --git a/include/mitsuba/render/bsdf.h b/include/mitsuba/render/bsdf.h
index 721e444e..11cd5860 100644
--- a/include/mitsuba/render/bsdf.h
+++ b/include/mitsuba/render/bsdf.h
@@ -225,10 +225,12 @@ public:
// =============================================================
/// The lobe is not invariant to rotation around the normal
EAnisotropic = 0x01000,
+ /// The BSDF depends on the UV coordinates
+ ESpatiallyVarying = 0x02000,
/// Supports interactions on the front-facing side
- EFrontSide = 0x02000,
+ EFrontSide = 0x04000,
/// Supports interactions on the back-facing side
- EBackSide = 0x04000,
+ EBackSide = 0x08000,
/// Can use an extra sampler instance to improve the sampling method
ECanUseSampler = 0x10000
//! @}
@@ -276,7 +278,7 @@ public:
inline unsigned int getType(int component) const {
return m_components[component];
}
-
+
/**
* \brief Return the measure corresponding to a particular
* component type
diff --git a/include/mitsuba/render/texture.h b/include/mitsuba/render/texture.h
index f10f052a..a2a7e519 100644
--- a/include/mitsuba/render/texture.h
+++ b/include/mitsuba/render/texture.h
@@ -43,6 +43,9 @@ public:
/// Return the resolution in pixels, if applicable
virtual Vector3i getResolution() const;
+ /// Return whether the texture takes on a single constant value
+ virtual bool isConstant() const = 0;
+
/**
* \brief Does this texture do pre-filtering when ray
* differentials are available?
diff --git a/src/bsdfs/coating.cpp b/src/bsdfs/coating.cpp
index d9b9414b..94494da5 100644
--- a/src/bsdfs/coating.cpp
+++ b/src/bsdfs/coating.cpp
@@ -30,37 +30,44 @@ MTS_NAMESPACE_BEGIN
* numerically or using a known material name. \default{\texttt{bk7} / 1.5046}}
* \parameter{extIOR}{\Float\Or\String}{Exterior index of refraction specified
* numerically or using a known material name. \default{\texttt{air} / 1.000277}}
- * \parameter{sigmaA}{\Spectrum\Or\Texture}{Absorption coefficient within the layer. \default{0}}
- * \parameter{thickness}{\Float}{Thickness of the absorbing layer (given in inverse units of \code{sigmaA})\default{1}}
+ * \parameter{thickness}{\Float}{Denotes the thickness of the absorbing layer (given in inverse units of \code{sigmaA})\default{1}}
+ * \parameter{sigmaA}{\Spectrum\Or\Texture}{The absorption coefficient of the coating layer. \default{0, i.e. there is no absorption}}
* }
*
* \renderings{
- * \rendering{Coated rough copper (lower exposure, \lstref{coating-roughcopper})}
+ * \rendering{Rough copper}
+ * {bsdf_roughconductor_copper}
+ * \rendering{The same material coated with a single layer of clear varnish (see \lstref{coating-roughcopper})}
* {bsdf_coating_roughconductor}
- * \rendering{Coated rough plastic}
- * {bsdf_coating_roughplastic}
* }
*
- * This plugin implements a smooth dielectric coating in the style of the
- * paper ``Arbitrarily Layered Micro-Facet Surfaces'' by Weidlich and
- * Wilkie \cite{Weidlich2007Arbitrarily}. Any non-transmissive model can
- * be coated, and multiple layers can be applied in sequence. This allows
- * designing custom materials like car paint.
+ * This plugin implements a smooth dielectric coating (e.g. a layer of varnish)
+ * in the style of the paper ``Arbitrarily Layered Micro-Facet Surfaces'' by
+ * Weidlich and Wilkie \cite{Weidlich2007Arbitrarily}. Any non-transmissive
+ * BSDF in Mitsuba can be coated using this plugin, and multiple coating layers
+ * can be applied in sequence. This allows designing interesting custom materials
+ * like car paint or glazed metal foil. The coating layer can optionally be
+ * tinted (i.e. filled with an absorbing medium), in which case this model also
+ * accounts for the directionally dependent absorption within the layer.
*
- * The coating layer can optionally be filled with an absorbing medium,
- * in which case this model also accounts for the directionally dependent
- * extinction within the layer.
+ * Note that the plugin discards illumination that undergoes internal
+ * reflection within the coating. This can lead to a noticeable energy
+ * loss for materials that reflect much of their energy near or below the critical
+ * angle (i.e. diffuse or very rough materials).
+ * Therefore, users are discouraged to use this plugin to coat smooth
+ * diffuse materials, since there is a separately available plugin
+ * named \pluginref{smoothplastic}, which covers the same case and does not
+ * suffer from energy loss.
*
* Evaluating the internal component of this model entails refracting the
* incident and exitant rays through the dielectric interface, followed by
* querying the nested material with this modified direction pair. The result
- * is attenuated by the two Fresnel transmittances. Note that this model does
- * not attempt to handle illumination that is reflected by the interior of the
- * coating---this energy is essentially lost.
+ * is attenuated by the two Fresnel transmittances and the absorption, if any.
*
* \vspace{4mm}
*
- * \begin{xml}[caption=Rough copper coated with a transparent layer of lacquer, label=lst:coating-roughcopper]
+ * \begin{xml}[caption=Rough copper coated with a transparent layer of
+ * varnish, label=lst:coating-roughcopper]
*
*
*
@@ -79,13 +86,13 @@ public:
/* Specifies the external index of refraction at the interface */
m_extIOR = lookupIOR(props, "extIOR", "air");
-
- /* Specifies the absorption within the layer */
- m_sigmaA = new ConstantSpectrumTexture(
- props.getSpectrum("sigmaA", Spectrum(0.0f)));
/* Specifies the layer's thickness using the inverse units of sigmaA */
m_thickness = props.getFloat("thickness", 1);
+
+ /* Specifies the absorption within the layer */
+ m_sigmaA = new ConstantSpectrumTexture(
+ props.getSpectrum("sigmaA", Spectrum(0.0f)));
}
SmoothCoating(Stream *stream, InstanceManager *manager)
@@ -105,11 +112,26 @@ public:
Log(EError, "Tried to put a smooth coating layer on top of a BSDF "
"with a transmission component -- this is currently not allowed!");
+#if COMPENSATE
+ if (m_nested->getClass()->getName() == "SmoothDiffuse") {
+ /* For an ideally diffuse material, it is known how much
+ energy will be lost to total internal reflection */
+ m_compensation = (m_intIOR*m_intIOR) / (m_extIOR * m_extIOR);
+ } else {
+ /* Otherwise, give up (for now) */
+ m_compensation = 1.0f;
+ }
+#endif
+ unsigned int extraFlags = 0;
+ if (!m_sigmaA->isConstant())
+ extraFlags |= ESpatiallyVarying;
+
m_components.clear();
for (int i=0; igetComponentCount(); ++i)
- m_components.push_back(m_nested->getType(i));
+ m_components.push_back(m_nested->getType(i) | extraFlags);
+
m_components.push_back(EDeltaReflection | EFrontSide);
-
+
m_usesRayDifferentials = m_nested->usesRayDifferentials()
|| m_sigmaA->usesRayDifferentials();
@@ -206,9 +228,10 @@ public:
if (R12 == 1 || R21 == 1) /* Total internal reflection */
return Spectrum(0.0f);
+ Float eta = m_extIOR / m_intIOR;
Spectrum result = m_nested->eval(bRec2, measure)
- * ((1-R12) * (1-R21));
-
+ * ((1-R12) * (1-R21) * eta * eta);
+
Spectrum sigmaA = m_sigmaA->getValue(bRec.its) * m_thickness;
if (!sigmaA.isZero())
result *= (-sigmaA *
@@ -216,10 +239,12 @@ public:
1/std::abs(Frame::cosTheta(bRec2.wo)))).exp();
if (measure == ESolidAngle)
- result *= Frame::cosTheta(bRec2.wo);
+ result *= Frame::cosTheta(bRec.wo)
+ / Frame::cosTheta(bRec2.wo);
- Float eta = m_extIOR / m_intIOR;
- result *= eta * eta;
+#ifdef COMPENSATE
+ result *= m_compensation;
+#endif
return result;
}
@@ -250,9 +275,11 @@ public:
if (R12 == 1 || R21 == 1) /* Total internal reflection */
return 0.0f;
- Float pdf = m_nested->pdf(bRec2, measure)
- * Frame::cosTheta(bRec.wo)
- / Frame::cosTheta(bRec2.wo);
+ Float pdf = m_nested->pdf(bRec2, measure);
+
+ if (measure == ESolidAngle)
+ pdf *= Frame::cosTheta(bRec.wo)
+ / Frame::cosTheta(bRec2.wo);
Float eta = m_extIOR / m_intIOR;
pdf *= eta * eta;
@@ -324,11 +351,16 @@ public:
if (R21 == 1.0f) /* Total internal reflection */
return Spectrum(0.0f);
+ bool sampledSA = (BSDF::getMeasure(bRec.sampledType) == ESolidAngle);
+ Float cosRatio = Frame::cosTheta(bRec.wo) / cosThetaWoPrime,
+ commonTerms = (sampledSA ? cosRatio : 1.0f)* eta * eta;
- pdf *= (sampleSpecular ? (1 - R12) : 1.0f) * eta * eta *
- Frame::cosTheta(bRec.wo) / cosThetaWoPrime;
+ pdf *= (sampleSpecular ? (1 - R12) : 1.0f) * commonTerms;
+ result *= (1 - R12) * (1 - R21) * commonTerms;
- result *= (1 - R12) * (1 - R21) * cosThetaWoPrime * eta * eta;
+#ifdef COMPENSATE
+ result *= m_compensation;
+#endif
return result;
}
@@ -358,11 +390,14 @@ public:
}
MTS_DECLARE_CLASS()
-private:
+protected:
Float m_intIOR, m_extIOR;
ref m_sigmaA;
ref m_nested;
Float m_thickness;
+#ifdef COMPENSATE
+ Float m_compensation;
+#endif
};
MTS_IMPLEMENT_CLASS_S(SmoothCoating, false, BSDF)
diff --git a/src/bsdfs/conductor.cpp b/src/bsdfs/conductor.cpp
index 75247472..7c4e30e6 100644
--- a/src/bsdfs/conductor.cpp
+++ b/src/bsdfs/conductor.cpp
@@ -181,8 +181,9 @@ public:
m_specularReflectance->usesRayDifferentials();
m_components.clear();
- m_components.push_back(EDeltaReflection | EFrontSide);
-
+ m_components.push_back(EDeltaReflection | EFrontSide
+ | (m_specularReflectance->isConstant() ? 0 : ESpatiallyVarying));
+
BSDF::configure();
}
diff --git a/src/bsdfs/dielectric.cpp b/src/bsdfs/dielectric.cpp
index 6f185b31..3fbd4cda 100644
--- a/src/bsdfs/dielectric.cpp
+++ b/src/bsdfs/dielectric.cpp
@@ -176,8 +176,10 @@ public:
m_specularTransmittance, "specularTransmittance", 1.0f);
m_components.clear();
- m_components.push_back(EDeltaReflection | EFrontSide | EBackSide);
- m_components.push_back(EDeltaTransmission | EFrontSide | EBackSide);
+ m_components.push_back(EDeltaReflection | EFrontSide | EBackSide
+ | (m_specularReflectance->isConstant() ? 0 : ESpatiallyVarying));
+ m_components.push_back(EDeltaTransmission | EFrontSide | EBackSide
+ | (m_specularTransmittance->isConstant() ? 0 : ESpatiallyVarying));
m_usesRayDifferentials =
m_specularReflectance->usesRayDifferentials() ||
diff --git a/src/bsdfs/difftrans.cpp b/src/bsdfs/difftrans.cpp
index 96bc4722..60fd8707 100644
--- a/src/bsdfs/difftrans.cpp
+++ b/src/bsdfs/difftrans.cpp
@@ -64,7 +64,8 @@ public:
m_transmittance = ensureEnergyConservation(m_transmittance, "transmittance", 1.0f);
m_components.clear();
- m_components.push_back(EDiffuseTransmission | EFrontSide | EBackSide);
+ m_components.push_back(EDiffuseTransmission | EFrontSide | EBackSide
+ | (m_transmittance->isConstant() ? 0 : ESpatiallyVarying));
BSDF::configure();
}
diff --git a/src/bsdfs/diffuse.cpp b/src/bsdfs/diffuse.cpp
index 39c3ddf4..deb9f790 100644
--- a/src/bsdfs/diffuse.cpp
+++ b/src/bsdfs/diffuse.cpp
@@ -93,7 +93,8 @@ public:
m_reflectance = ensureEnergyConservation(m_reflectance, "reflectance", 1.0f);
m_components.clear();
- m_components.push_back(EDiffuseReflection | EFrontSide);
+ m_components.push_back(EDiffuseReflection | EFrontSide
+ | (m_reflectance->isConstant() ? 0 : ESpatiallyVarying));
m_usesRayDifferentials = m_reflectance->usesRayDifferentials();
BSDF::configure();
diff --git a/src/bsdfs/irawan.cpp b/src/bsdfs/irawan.cpp
index 5e048f4c..6f42fb89 100644
--- a/src/bsdfs/irawan.cpp
+++ b/src/bsdfs/irawan.cpp
@@ -122,8 +122,10 @@ public:
void configure() {
m_components.clear();
- m_components.push_back(EGlossyReflection | EAnisotropic | EFrontSide);
- m_components.push_back(EDiffuseReflection | EFrontSide);
+ m_components.push_back(EGlossyReflection | EFrontSide
+ | EAnisotropic | ESpatiallyVarying);
+ m_components.push_back(EDiffuseReflection | EFrontSide
+ | ESpatiallyVarying);
BSDF::configure();
}
diff --git a/src/bsdfs/mask.cpp b/src/bsdfs/mask.cpp
index af0cff2a..8a7c3392 100644
--- a/src/bsdfs/mask.cpp
+++ b/src/bsdfs/mask.cpp
@@ -83,10 +83,17 @@ public:
void configure() {
if (!m_nestedBSDF)
Log(EError, "A child BSDF is required");
+
+ unsigned int extraFlags = 0;
+ if (!m_opacity->isConstant())
+ extraFlags |= ESpatiallyVarying;
+
m_components.clear();
for (int i=0; igetComponentCount(); ++i)
- m_components.push_back(m_nestedBSDF->getType(i));
- m_components.push_back(EDeltaTransmission | EFrontSide | EBackSide);
+ m_components.push_back(m_nestedBSDF->getType(i) | extraFlags);
+ m_components.push_back(EDeltaTransmission | EFrontSide
+ | EBackSide | extraFlags);
+
m_usesRayDifferentials = m_nestedBSDF->usesRayDifferentials();
m_opacity = ensureEnergyConservation(m_opacity, "opacity", 1.0f);
BSDF::configure();
diff --git a/src/bsdfs/mixture.cpp b/src/bsdfs/mixture.cpp
index 4a090b5f..ce88404c 100644
--- a/src/bsdfs/mixture.cpp
+++ b/src/bsdfs/mixture.cpp
@@ -28,8 +28,8 @@ MTS_NAMESPACE_BEGIN
* \parameter{weights}{\String}{A comma-separated list of BSDF weights}
* }
* \renderings{
- * \rendering{An exemplary combination of BSDFs
- * (\lstref{mixture-example})}{bsdf_mixture_test}
+ * \rendering{An admittedly not particularly realistic linear combination of
+ * diffuse and specular BSDFs (\lstref{mixture-example})}{bsdf_mixture_test}
* }
*
* This plugin implements a ``mixture'' material, which represents
diff --git a/src/bsdfs/phong.cpp b/src/bsdfs/phong.cpp
index 97729071..8ef18259 100644
--- a/src/bsdfs/phong.cpp
+++ b/src/bsdfs/phong.cpp
@@ -77,8 +77,11 @@ public:
void configure() {
m_components.clear();
- m_components.push_back(EGlossyReflection | EFrontSide);
- m_components.push_back(EDiffuseReflection | EFrontSide);
+ m_components.push_back(EGlossyReflection | EFrontSide |
+ ((!m_specularReflectance->isConstant()
+ || !m_exponent->isConstant()) ? ESpatiallyVarying : 0));
+ m_components.push_back(EDiffuseReflection | EFrontSide
+ | (m_diffuseReflectance->isConstant() ? 0 : ESpatiallyVarying));
/* Verify the input parameters and fix them if necessary */
std::pair result = ensureEnergyConservation(
@@ -230,7 +233,7 @@ public:
}
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
- Float pdf;
+ Float pdf = 0;
Spectrum result = Phong::sample(bRec, pdf, sample);
if (result.isZero())
diff --git a/src/bsdfs/plastic.cpp b/src/bsdfs/plastic.cpp
index ee1c2133..c2fc9522 100644
--- a/src/bsdfs/plastic.cpp
+++ b/src/bsdfs/plastic.cpp
@@ -103,8 +103,10 @@ public:
m_diffuseReflectance->usesRayDifferentials();
m_components.clear();
- m_components.push_back(EDeltaReflection | EFrontSide);
- m_components.push_back(EDiffuseReflection | EFrontSide);
+ m_components.push_back(EDeltaReflection | EFrontSide
+ | (m_specularReflectance->isConstant() ? 0 : ESpatiallyVarying));
+ m_components.push_back(EDiffuseReflection | EFrontSide
+ | (m_diffuseReflectance->isConstant() ? 0 : ESpatiallyVarying));
BSDF::configure();
}
diff --git a/src/bsdfs/roughconductor.cpp b/src/bsdfs/roughconductor.cpp
index 74eb5f61..cf75d9fe 100644
--- a/src/bsdfs/roughconductor.cpp
+++ b/src/bsdfs/roughconductor.cpp
@@ -205,10 +205,12 @@ public:
"anisotropic Ashikhmin-Shirley microfacet distribution "
"(named \"as\")");
}
+ if (!m_alphaU->isConstant() || !m_alphaV->isConstant() ||
+ !m_specularReflectance->isConstant())
+ extraFlags |= ESpatiallyVarying;
m_components.clear();
- m_components.push_back(
- EGlossyReflection | EFrontSide | extraFlags);
+ m_components.push_back(EGlossyReflection | EFrontSide | extraFlags);
/* Verify the input parameters and fix them if necessary */
m_specularReflectance = ensureEnergyConservation(
diff --git a/src/bsdfs/roughdielectric.cpp b/src/bsdfs/roughdielectric.cpp
index 156fac94..981ce8bc 100644
--- a/src/bsdfs/roughdielectric.cpp
+++ b/src/bsdfs/roughdielectric.cpp
@@ -227,11 +227,16 @@ public:
"(named \"as\")");
}
+ if (!m_alphaU->isConstant() || !m_alphaV->isConstant())
+ extraFlags |= ESpatiallyVarying;
+
m_components.clear();
- m_components.push_back(
- EGlossyReflection | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
- m_components.push_back(
- EGlossyTransmission | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
+ m_components.push_back(EGlossyReflection | EFrontSide
+ | EBackSide | ECanUseSampler | extraFlags
+ | (m_specularReflectance->isConstant() ? 0 : ESpatiallyVarying));
+ m_components.push_back(EGlossyTransmission | EFrontSide
+ | EBackSide | ECanUseSampler | extraFlags
+ | (m_specularTransmittance->isConstant() ? 0 : ESpatiallyVarying));
/* Verify the input parameters and fix them if necessary */
m_specularReflectance = ensureEnergyConservation(
diff --git a/src/bsdfs/roughdiffuse.cpp b/src/bsdfs/roughdiffuse.cpp
index c3e311ae..f10de621 100644
--- a/src/bsdfs/roughdiffuse.cpp
+++ b/src/bsdfs/roughdiffuse.cpp
@@ -107,9 +107,12 @@ public:
void configure() {
/* Verify the input parameter and fix them if necessary */
m_reflectance = ensureEnergyConservation(m_reflectance, "reflectance", 1.0f);
-
+
m_components.clear();
- m_components.push_back(EGlossyReflection | EFrontSide);
+ m_components.push_back(EGlossyReflection | EFrontSide
+ | ((!m_reflectance->isConstant() || !m_alpha->isConstant())
+ ? ESpatiallyVarying : 0));
+
m_usesRayDifferentials = m_reflectance->usesRayDifferentials() ||
m_alpha->usesRayDifferentials();
diff --git a/src/bsdfs/roughplastic.cpp b/src/bsdfs/roughplastic.cpp
index c107f6e5..23da5be8 100644
--- a/src/bsdfs/roughplastic.cpp
+++ b/src/bsdfs/roughplastic.cpp
@@ -176,8 +176,11 @@ public:
void configure() {
m_components.clear();
- m_components.push_back(EGlossyReflection | EFrontSide);
- m_components.push_back(EDiffuseReflection | EFrontSide);
+
+ m_components.push_back(EGlossyReflection | EFrontSide
+ | (m_specularReflectance->isConstant() ? 0 : ESpatiallyVarying));
+ m_components.push_back(EDiffuseReflection | EFrontSide
+ | (m_diffuseReflectance->isConstant() ? 0 : ESpatiallyVarying));
/* Verify the input parameters and fix them if necessary */
m_specularReflectance = ensureEnergyConservation(
@@ -357,7 +360,7 @@ public:
}
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
- Float pdf;
+ Float pdf = 0;
Spectrum result = RoughPlastic::sample(bRec, pdf, sample);
if (result.isZero())
diff --git a/src/bsdfs/ward.cpp b/src/bsdfs/ward.cpp
index 471041c9..66ed9abc 100644
--- a/src/bsdfs/ward.cpp
+++ b/src/bsdfs/ward.cpp
@@ -140,8 +140,11 @@ public:
extraFlags |= EAnisotropic;
m_components.clear();
- m_components.push_back(EGlossyReflection | EFrontSide | extraFlags);
- m_components.push_back(EDiffuseReflection | EFrontSide | extraFlags);
+ m_components.push_back(EGlossyReflection | EFrontSide | extraFlags
+ | ((!m_specularReflectance->isConstant() || !m_alphaU->isConstant()
+ || !m_alphaV->isConstant()) ? ESpatiallyVarying : 0));
+ m_components.push_back(EDiffuseReflection | EFrontSide | extraFlags
+ | (m_diffuseReflectance->isConstant() ? 0 : ESpatiallyVarying));
/* Verify the input parameters and fix them if necessary */
std::pair result = ensureEnergyConservation(
diff --git a/src/librender/texture.cpp b/src/librender/texture.cpp
index 01efc62b..de504110 100644
--- a/src/librender/texture.cpp
+++ b/src/librender/texture.cpp
@@ -31,7 +31,7 @@ Texture::Texture(Stream *stream, InstanceManager *manager)
Vector3i Texture::getResolution() const {
return Vector3i(0);
}
-
+
Texture::~Texture() {
}
diff --git a/src/textures/bitmap.cpp b/src/textures/bitmap.cpp
index 88843042..cddeb6f4 100644
--- a/src/textures/bitmap.cpp
+++ b/src/textures/bitmap.cpp
@@ -256,6 +256,10 @@ public:
return m_maximum;
}
+ bool isConstant() const {
+ return false;
+ }
+
bool usesRayDifferentials() const {
return true;
}
@@ -353,7 +357,7 @@ public:
void unbind() const {
m_gpuTexture->unbind();
}
-
+
MTS_DECLARE_CLASS()
private:
ref m_gpuTexture;
diff --git a/src/textures/checkerboard.cpp b/src/textures/checkerboard.cpp
index 98f13435..46925746 100644
--- a/src/textures/checkerboard.cpp
+++ b/src/textures/checkerboard.cpp
@@ -71,6 +71,10 @@ public:
return m_brightColor;
}
+ bool isConstant() const {
+ return false;
+ }
+
std::string toString() const {
return "Checkerboard[]";
}
@@ -128,7 +132,7 @@ public:
program->setParameter(parameterIDs[2], m_uvOffset);
program->setParameter(parameterIDs[3], m_uvScale);
}
-
+
MTS_DECLARE_CLASS()
private:
Spectrum m_brightColor;
diff --git a/src/textures/gridtexture.cpp b/src/textures/gridtexture.cpp
index d45f7898..cdd417ff 100644
--- a/src/textures/gridtexture.cpp
+++ b/src/textures/gridtexture.cpp
@@ -79,6 +79,10 @@ public:
Spectrum getAverage() const {
return m_brightColor; // that's not quite right
}
+
+ bool isConstant() const {
+ return false;
+ }
std::string toString() const {
return "GridTexture[]";
diff --git a/src/textures/scale.cpp b/src/textures/scale.cpp
index 69522b69..bcb9ecf0 100644
--- a/src/textures/scale.cpp
+++ b/src/textures/scale.cpp
@@ -68,6 +68,10 @@ public:
return m_nested->getMaximum() * m_scale;
}
+ bool isConstant() const {
+ return m_nested->isConstant();
+ }
+
std::string toString() const {
std::ostringstream oss;
oss << "ScalingTexture[" << endl
diff --git a/src/textures/vertexcolors.cpp b/src/textures/vertexcolors.cpp
index 3a5b0e00..79fa0c68 100644
--- a/src/textures/vertexcolors.cpp
+++ b/src/textures/vertexcolors.cpp
@@ -54,6 +54,10 @@ public:
return Spectrum(1.0f);
}
+ bool isConstant() const {
+ return false;
+ }
+
std::string toString() const {
return "VertexColors[]";
}