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