texturable specular reflectance for coating + roughcoating
parent
2b9057cf64
commit
30a93f4bbc
|
@ -35,6 +35,9 @@ MTS_NAMESPACE_BEGIN
|
|||
* model absorption --- should be specified 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}}
|
||||
* \parameter{specular\showbreak Transmittance}{\Spectrum\Or\Texture}{Optional
|
||||
* factor that can be used to modulate the specular transmission component. Note
|
||||
* that for physical realism, this parameter should never be touched. \default{1.0}}
|
||||
* \parameter{\Unnamed}{\BSDF}{A nested BSDF model that should be coated.}
|
||||
* }
|
||||
*
|
||||
|
@ -62,13 +65,7 @@ MTS_NAMESPACE_BEGIN
|
|||
* Therefore, users are discouraged to use this plugin to coat smooth
|
||||
* diffuse materials, since there is a separately available plugin
|
||||
* named \pluginref{plastic}, 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 and the absorption, if
|
||||
* any.\newpage
|
||||
* suffer from energy loss.\newpage
|
||||
*
|
||||
* \renderings{
|
||||
* \smallrendering{$\code{thickness}=0$}{bsdf_coating_0}
|
||||
|
@ -99,6 +96,13 @@ MTS_NAMESPACE_BEGIN
|
|||
* \caption{Some interesting materials can be created simply by applying
|
||||
* Mitsuba's material modifiers in different orders.}
|
||||
* }
|
||||
*
|
||||
* \subsubsection*{Technical details}
|
||||
* 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 and the absorption, if
|
||||
* any.
|
||||
*/
|
||||
class SmoothCoating : public BSDF {
|
||||
public:
|
||||
|
@ -122,7 +126,11 @@ public:
|
|||
/* Specifies the absorption within the layer */
|
||||
m_sigmaA = new ConstantSpectrumTexture(
|
||||
props.getSpectrum("sigmaA", Spectrum(0.0f)));
|
||||
|
||||
|
||||
/* Specifies a multiplier for the specular reflectance component */
|
||||
m_specularReflectance = new ConstantSpectrumTexture(
|
||||
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
|
||||
|
||||
if (m_intIOR < 0 || m_extIOR < 0 || m_intIOR == m_extIOR)
|
||||
Log(EError, "The interior and exterior indices of "
|
||||
"refraction must be positive and differ!");
|
||||
|
@ -135,6 +143,7 @@ public:
|
|||
m_thickness = stream->readFloat();
|
||||
m_nested = static_cast<BSDF *>(manager->getInstance(stream));
|
||||
m_sigmaA = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
configure();
|
||||
}
|
||||
|
||||
|
@ -150,10 +159,12 @@ public:
|
|||
for (int i=0; i<m_nested->getComponentCount(); ++i)
|
||||
m_components.push_back(m_nested->getType(i) | extraFlags);
|
||||
|
||||
m_components.push_back(EDeltaReflection | EFrontSide | EBackSide);
|
||||
m_components.push_back(EDeltaReflection | EFrontSide | EBackSide
|
||||
| (m_specularReflectance->isConstant() ? 0 : ESpatiallyVarying));
|
||||
|
||||
m_usesRayDifferentials = m_nested->usesRayDifferentials()
|
||||
|| m_sigmaA->usesRayDifferentials();
|
||||
|| m_sigmaA->usesRayDifferentials()
|
||||
|| m_specularReflectance->usesRayDifferentials();
|
||||
|
||||
/* Compute weights that further steer samples towards
|
||||
the specular or nested components */
|
||||
|
@ -162,6 +173,10 @@ public:
|
|||
|
||||
m_specularSamplingWeight = 1.0f / (avgAbsorption + 1.0f);
|
||||
|
||||
/* Verify the input parameters and fix them if necessary */
|
||||
m_specularReflectance = ensureEnergyConservation(
|
||||
m_specularReflectance, "specularReflectance", 1.0f);
|
||||
|
||||
BSDF::configure();
|
||||
}
|
||||
|
||||
|
@ -173,6 +188,7 @@ public:
|
|||
stream->writeFloat(m_thickness);
|
||||
manager->serialize(stream, m_nested.get());
|
||||
manager->serialize(stream, m_sigmaA.get());
|
||||
manager->serialize(stream, m_specularReflectance.get());
|
||||
}
|
||||
|
||||
void addChild(const std::string &name, ConfigurableObject *child) {
|
||||
|
@ -238,8 +254,8 @@ public:
|
|||
|
||||
if (measure == EDiscrete && sampleSpecular &&
|
||||
std::abs(1-dot(reflect(bRec.wi), bRec.wo)) < Epsilon) {
|
||||
return Spectrum(fresnel(
|
||||
std::abs(Frame::cosTheta(bRec.wi)), m_extIOR, m_intIOR));
|
||||
return m_specularReflectance->getValue(bRec.its) *
|
||||
fresnel(std::abs(Frame::cosTheta(bRec.wi)), m_extIOR, m_intIOR);
|
||||
} else if (sampleNested) {
|
||||
Float R12, R21;
|
||||
BSDFQueryRecord bRecInt(bRec);
|
||||
|
@ -346,7 +362,7 @@ public:
|
|||
bRec.sampledType = EDeltaReflection;
|
||||
bRec.wo = reflect(bRec.wi);
|
||||
pdf = sampleNested ? probSpecular : 1.0f;
|
||||
return Spectrum(R12) / pdf;
|
||||
return m_specularReflectance->getValue(bRec.its) * (R12/pdf);
|
||||
} else {
|
||||
if (R12 == 1.0f) /* Total internal reflection */
|
||||
return Spectrum(0.0f);
|
||||
|
@ -405,6 +421,7 @@ public:
|
|||
<< " extIOR = " << m_extIOR << "," << endl
|
||||
<< " specularSamplingWeight = " << m_specularSamplingWeight << "," << endl
|
||||
<< " sigmaA = " << indent(m_sigmaA->toString()) << "," << endl
|
||||
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << "," << endl
|
||||
<< " thickness = " << m_thickness << "," << endl
|
||||
<< " nested = " << indent(m_nested.toString()) << endl
|
||||
<< "]";
|
||||
|
@ -416,6 +433,7 @@ protected:
|
|||
Float m_specularSamplingWeight;
|
||||
Float m_intIOR, m_extIOR;
|
||||
ref<Texture> m_sigmaA;
|
||||
ref<Texture> m_specularReflectance;
|
||||
ref<BSDF> m_nested;
|
||||
Float m_thickness;
|
||||
};
|
||||
|
|
|
@ -57,6 +57,9 @@ MTS_NAMESPACE_BEGIN
|
|||
* numerically or using a known material name. \default{\texttt{air} / 1.000277}}
|
||||
* \parameter{sigmaA}{\Spectrum\Or\Texture}{The absorption coefficient of the
|
||||
* coating layer. \default{0, i.e. there is no absorption}}
|
||||
* \parameter{specular\showbreak Transmittance}{\Spectrum\Or\Texture}{Optional
|
||||
* factor that can be used to modulate the specular transmission component. Note
|
||||
* that for physical realism, this parameter should never be touched. \default{1.0}}
|
||||
* \parameter{\Unnamed}{\BSDF}{A nested BSDF model that should be coated.}
|
||||
* }\vspace{-4mm}
|
||||
* \renderings{
|
||||
|
@ -75,8 +78,8 @@ MTS_NAMESPACE_BEGIN
|
|||
* \pluginref{coating} plugin produces specular highlights that are too sharp.}
|
||||
* model that simulates a rough dielectric coating. It is essentially the
|
||||
* roughened version of \pluginref{coating}.
|
||||
* Any BSDF in Mitsuba can be coated using this plugin, and multiple coating
|
||||
* layers can even be applied in sequence. This allows designing interesting
|
||||
* Any BSDF in Mitsuba can be coated using this plugin and multiple coating
|
||||
* layers can even be applied in sequence, which allows designing interesting
|
||||
* custom materials. 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.
|
||||
|
@ -109,6 +112,10 @@ public:
|
|||
m_sigmaA = new ConstantSpectrumTexture(
|
||||
props.getSpectrum("sigmaA", Spectrum(0.0f)));
|
||||
|
||||
/* Specifies a multiplier for the specular reflectance component */
|
||||
m_specularReflectance = new ConstantSpectrumTexture(
|
||||
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
|
||||
|
||||
if (m_intIOR < 0 || m_extIOR < 0 || m_intIOR == m_extIOR)
|
||||
Log(EError, "The interior and exterior indices of "
|
||||
"refraction must be positive and differ!");
|
||||
|
@ -134,6 +141,7 @@ public:
|
|||
);
|
||||
m_nested = static_cast<BSDF *>(manager->getInstance(stream));
|
||||
m_sigmaA = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_alpha = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_intIOR = stream->readFloat();
|
||||
m_extIOR = stream->readFloat();
|
||||
|
@ -151,11 +159,13 @@ public:
|
|||
for (int i=0; i<m_nested->getComponentCount(); ++i)
|
||||
m_components.push_back(m_nested->getType(i) | extraFlags);
|
||||
|
||||
m_components.push_back(EGlossyReflection | EFrontSide | EBackSide);
|
||||
m_components.push_back(EGlossyReflection | EFrontSide | EBackSide
|
||||
| (m_specularReflectance->isConstant() ? 0 : ESpatiallyVarying));
|
||||
|
||||
m_usesRayDifferentials = m_nested->usesRayDifferentials()
|
||||
|| m_sigmaA->usesRayDifferentials()
|
||||
|| m_alpha->usesRayDifferentials();
|
||||
|| m_alpha->usesRayDifferentials()
|
||||
|| m_specularReflectance->usesRayDifferentials();
|
||||
|
||||
/* Compute weights that further steer samples towards
|
||||
the specular or nested components */
|
||||
|
@ -164,6 +174,10 @@ public:
|
|||
|
||||
m_specularSamplingWeight = 1.0f / (avgAbsorption + 1.0f);
|
||||
|
||||
/* Verify the input parameters and fix them if necessary */
|
||||
m_specularReflectance = ensureEnergyConservation(
|
||||
m_specularReflectance, "specularReflectance", 1.0f);
|
||||
|
||||
if (!m_roughTransmittance.get()) {
|
||||
/* Load precomputed data used to compute the rough
|
||||
transmittance through the dielectric interface */
|
||||
|
@ -258,7 +272,7 @@ public:
|
|||
Float value = F * D * G /
|
||||
(4.0f * std::abs(Frame::cosTheta(bRec.wi)));
|
||||
|
||||
result += Spectrum(value);
|
||||
result += m_specularReflectance->getValue(bRec.its) * value;
|
||||
}
|
||||
|
||||
if (hasNested) {
|
||||
|
@ -425,6 +439,7 @@ public:
|
|||
stream->writeUInt((uint32_t) m_distribution.getType());
|
||||
manager->serialize(stream, m_nested.get());
|
||||
manager->serialize(stream, m_sigmaA.get());
|
||||
manager->serialize(stream, m_specularReflectance.get());
|
||||
manager->serialize(stream, m_alpha.get());
|
||||
stream->writeFloat(m_intIOR);
|
||||
stream->writeFloat(m_extIOR);
|
||||
|
@ -455,6 +470,7 @@ public:
|
|||
<< " distribution = " << m_distribution.toString() << "," << endl
|
||||
<< " alpha = " << indent(m_alpha->toString()) << "," << endl
|
||||
<< " sigmaA = " << indent(m_sigmaA->toString()) << "," << endl
|
||||
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << "," << endl
|
||||
<< " specularSamplingWeight = " << m_specularSamplingWeight << "," << endl
|
||||
<< " diffuseSamplingWeight = " << (1-m_specularSamplingWeight) << "," << endl
|
||||
<< " intIOR = " << m_intIOR << "," << endl
|
||||
|
@ -472,6 +488,7 @@ private:
|
|||
ref<RoughTransmittance> m_roughTransmittance;
|
||||
ref<Texture> m_sigmaA;
|
||||
ref<Texture> m_alpha;
|
||||
ref<Texture> m_specularReflectance;
|
||||
ref<BSDF> m_nested;
|
||||
Float m_intIOR, m_extIOR;
|
||||
Float m_specularSamplingWeight;
|
||||
|
|
Loading…
Reference in New Issue