diff --git a/data/tests/test_bsdf.xml b/data/tests/test_bsdf.xml
index 6f7b0448..57aac646 100644
--- a/data/tests/test_bsdf.xml
+++ b/data/tests/test_bsdf.xml
@@ -118,8 +118,15 @@
-
-
+
+
+
+
+
+
+
+
+
diff --git a/doc/images/bsdf_plastic_diffuse.jpg b/doc/images/bsdf_plastic_diffuse.jpg
new file mode 100644
index 00000000..b09b14a0
Binary files /dev/null and b/doc/images/bsdf_plastic_diffuse.jpg differ
diff --git a/doc/images/bsdf_plastic_nopreserve.jpg b/doc/images/bsdf_plastic_nopreserve.jpg
new file mode 100644
index 00000000..23434692
Binary files /dev/null and b/doc/images/bsdf_plastic_nopreserve.jpg differ
diff --git a/doc/images/bsdf_plastic_preserve.jpg b/doc/images/bsdf_plastic_preserve.jpg
new file mode 100644
index 00000000..bdc74d9b
Binary files /dev/null and b/doc/images/bsdf_plastic_preserve.jpg differ
diff --git a/doc/images/bsdf_plastic_shiny.jpg b/doc/images/bsdf_plastic_shiny.jpg
index e63c515f..6916cdc4 100644
Binary files a/doc/images/bsdf_plastic_shiny.jpg and b/doc/images/bsdf_plastic_shiny.jpg differ
diff --git a/doc/macros.sty b/doc/macros.sty
index 8fe8fcf3..7792cf72 100644
--- a/doc/macros.sty
+++ b/doc/macros.sty
@@ -71,8 +71,8 @@
}
\newcommand{\rendering}[2]{\subfloat[#1]{\fbox{\includegraphics[width=0.47\textwidth]{images/#2}}}\hfill}
\newcommand{\unframedrendering}[2]{\subfloat[#1]{\includegraphics[width=0.47\textwidth]{images/#2}}\hfill}
-\newcommand{\medrendering}[2]{ \subfloat[#1]{\fbox{\includegraphics[width=0.3\textwidth]{images/#2}}}\hfill}
-\newcommand{\unframedmedrendering}[2]{\subfloat[#1]{\includegraphics[width=0.3\textwidth]{images/#2}}\hfill}
+\newcommand{\medrendering}[2]{ \subfloat[#1]{\fbox{\includegraphics[width=0.31\textwidth]{images/#2}}}\hfill}
+\newcommand{\unframedmedrendering}[2]{\subfloat[#1]{\includegraphics[width=0.31\textwidth]{images/#2}}\hfill}
\newcommand{\smallrendering}[2]{ \subfloat[#1]{\fbox{\includegraphics[width=0.2\textwidth]{images/#2}}}\hfill}
\newcommand{\tinyrendering}[2]{ \subfloat[#1]{\includegraphics[width=0.125\textwidth]{images/#2}}}
diff --git a/src/bsdfs/plastic.cpp b/src/bsdfs/plastic.cpp
index e86d9692..450b71f9 100644
--- a/src/bsdfs/plastic.cpp
+++ b/src/bsdfs/plastic.cpp
@@ -56,7 +56,7 @@ MTS_NAMESPACE_BEGIN
* of the illumination is specularly reflected at the material
* boundary, which results in a sharp reflection in the mirror direction.
* The remaining illumination refracts into the material, where it
- * scatters from the diffuse base layer. While some of the diffuse
+ * scatters from the diffuse base layer. While some of the diffusely
* scattered illumination is able to directly refract outwards again,
* the remainder is reflected from the interior side of the dielectric boundary
* and will in fact remain trapped inside the material for some number of
@@ -66,22 +66,38 @@ MTS_NAMESPACE_BEGIN
* out the correct form of the model without ever having to spend
* computational resources on the potentially large number of
* internal scattering events.
+
+ * Since it is simple, realistic, and fast, this model is often a better choice
+ * than the \pluginref{phong}, \pluginref{ward}, and \pluginref{roughplastic}
+ * plugins when rendering smooth plastic-like materials.
+ *
+ *
+ * \renderings{
+ * \medrendering{Diffuse textured rendering}{bsdf_plastic_diffuse}
+ * \medrendering{Plastic, \code{preserveColors=true}}{bsdf_plastic_preserve}
+ * \medrendering{Plastic, \code{preserveColors=false}}{bsdf_plastic_nopreserve}
+ * \caption{
+ * \label{fig:plastic-preservecolors}
+ * When asked to do so, this model can account for subtle color shifts due
+ * to internal scattering processes. The above images show a textured
+ * object first rendered using \pluginref{diffuse}, then
+ * \pluginref{plastic} with the default parameters, and finally using
+ * \pluginref{plastic} and support for color shifts.
+ * }
+ * }
*
* Note that due to the internal scattering, the diffuse color of the
* material is in practice slightly different from the color of the
* base layer on its own---in particular, the material color will tend to shift towards
- * higher saturation. Since this can be counter-intuitive when using bitmap
- * textures for the base layer, these color shifts are disabled by default. Specify
- * \code{preserveColors=false} to enable them.
+ * darker colors with higher saturation. Since this can be counter-intuitive when
+ * using bitmap textures, these color shifts are disabled by default. Specify
+ * the parameter \code{preserveColors=false} to enable them.
+ * \figref{plastic-preservecolors} illustrates this effect.
*
* Similar to the \pluginref{dielectric} plugin, this model allows to specify
* IOR values either numerically, or based on a list of known materials (see
* \tblref{dielectric-iors} for an overview).
*
- * Since it is simple, realistic, and fast, this model is often a better choice
- * than the \pluginref{phong}, \pluginref{ward}, and \pluginref{roughplastic}
- * plugins when rendering smooth plastic-like materials.
- *
* Note that this plugin is quite similar to what one would get by applying the
* \pluginref{coating} plugin to the \pluginref{diffuse} material. The main
* difference is that this plugin is significantly faster, while at the same
@@ -113,7 +129,7 @@ public:
m_diffuseReflectance = new ConstantSpectrumTexture(
props.getSpectrum("diffuseReflectance", Spectrum(0.5f)));
- m_preserveColors = props.getBoolean("preserveColors", false);
+ m_preserveColors = props.getBoolean("preserveColors", true);
m_specularSamplingWeight = 0.0f;
}
@@ -144,6 +160,9 @@ public:
sAvg = m_specularReflectance->getAverage().getLuminance();
m_specularSamplingWeight = sAvg / (dAvg + sAvg);
+
+ Float eta = m_extIOR / m_intIOR;
+ m_eta2 = eta*eta;
m_usesRayDifferentials =
m_specularReflectance->usesRayDifferentials() ||
@@ -217,7 +236,7 @@ public:
diff /= 1 - m_fdr;
else
diff /= Spectrum(1) - m_fdr*diff;
- return diff * (INV_PI * Frame::cosTheta(bRec.wo) * (1-Fr) * (1-Fr2));
+ return diff * (INV_PI * Frame::cosTheta(bRec.wo) * m_eta2 * (1-Fr) * (1-Fr2));
}
}
@@ -292,7 +311,7 @@ public:
else
diff /= Spectrum(1) - m_fdr*diff;
- return diff * ((1-Fr) * (1-Fr2) / (1-probSpecular));
+ return diff * (m_eta2 * (1-Fr) * (1-Fr2) / (1-probSpecular));
}
} else if (hasSpecular) {
bRec.sampledComponent = 0;
@@ -311,8 +330,7 @@ public:
else
diff /= Spectrum(1) - m_fdr*diff;
-
- return diff * (1-Fr) * (1-Fr2);
+ return diff * (m_eta2 * (1-Fr) * (1-Fr2));
}
}
@@ -357,7 +375,7 @@ public:
pdf = (1-probSpecular) * Frame::cosTheta(bRec.wo) * INV_PI;
- return diff * ((1-Fr) * (1-Fr2) / (1-probSpecular));
+ return diff * (m_eta2 * (1-Fr) * (1-Fr2) / (1-probSpecular));
}
} else if (hasSpecular) {
bRec.sampledComponent = 0;
@@ -368,12 +386,8 @@ public:
} else {
bRec.sampledComponent = 1;
bRec.sampledType = EDiffuseReflection;
- Float Fr2 = fresnel(Frame::cosTheta(bRec.wo), m_extIOR, m_intIOR);
-
- if (Fr == 1.0f) /* Total internal reflection */
- return Spectrum(0.0f);
-
bRec.wo = squareToHemispherePSA(sample);
+ Float Fr2 = fresnel(Frame::cosTheta(bRec.wo), m_extIOR, m_intIOR);
pdf = Frame::cosTheta(bRec.wo) * INV_PI;
@@ -383,7 +397,7 @@ public:
else
diff /= Spectrum(1) - m_fdr*diff;
- return diff * (1-Fr) * (1-Fr2);
+ return diff * (m_eta2 * (1-Fr) * (1-Fr2));
}
}
@@ -407,7 +421,7 @@ public:
MTS_DECLARE_CLASS()
private:
- Float m_intIOR, m_extIOR, m_fdr;
+ Float m_intIOR, m_extIOR, m_fdr, m_eta2;
ref m_diffuseReflectance;
ref m_specularReflectance;
Float m_specularSamplingWeight;