got the rough plastic material to work properly again
parent
4cd971e274
commit
03264f9913
|
@ -369,7 +369,7 @@ public:
|
|||
<< "}" << endl
|
||||
<< endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
<< " return " << evalName << "_R0 * 0.31831 * cosTheta(wo);"<< endl
|
||||
<< " return " << evalName << "_R0 * inv_pi * cosTheta(wo);"<< endl
|
||||
<< "}" << endl;
|
||||
}
|
||||
MTS_DECLARE_CLASS()
|
||||
|
|
|
@ -171,7 +171,7 @@ public:
|
|||
oss << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
<< " if (cosTheta(wi) * cosTheta(wo) >= 0.0)" << endl
|
||||
<< " return vec3(0.0);" << endl
|
||||
<< " return " << depNames[0] << "(uv) * 0.31831 * abs(cosTheta(wo));" << endl
|
||||
<< " return " << depNames[0] << "(uv) * inv_pi * abs(cosTheta(wo));" << endl
|
||||
<< "}" << endl
|
||||
<< endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
|
|
|
@ -203,7 +203,7 @@ public:
|
|||
oss << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
<< " if (cosTheta(wi) < 0.0 || cosTheta(wo) < 0.0)" << endl
|
||||
<< " return vec3(0.0);" << endl
|
||||
<< " return " << depNames[0] << "(uv) * 0.31831 * cosTheta(wo);" << endl
|
||||
<< " return " << depNames[0] << "(uv) * inv_pi * cosTheta(wo);" << endl
|
||||
<< "}" << endl
|
||||
<< endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
|
|
|
@ -291,7 +291,7 @@ public:
|
|||
<< " reducedAlbedo[i] = reducedSigmaT[i] > 0.0 ? reducedSigmaS[i]/reducedSigmaT[i] : 0.0;" << endl
|
||||
<< " vec3 rootExp = sqrt((1.0 - reducedAlbedo) * 3.0);" << endl
|
||||
<< " return (reducedAlbedo * 0.5) * (1+exp(-rootExp*(4.0/3.0 * " << endl
|
||||
<< " " << evalName << "_A" << "))) * exp(-rootExp) * 0.31831 * cosThetaO;" << endl
|
||||
<< " " << evalName << "_A" << "))) * exp(-rootExp) * inv_pi * cosThetaO;" << endl
|
||||
<< "}" << endl
|
||||
<< endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
|
|
|
@ -333,13 +333,13 @@ public:
|
|||
<< " if (alpha > 0.0)" << endl
|
||||
<< " specRef = pow(alpha, exponent) * " << endl
|
||||
<< " (exponent + 2) * 0.15915;" << endl
|
||||
<< " return (" << depNames[1] << "(uv) * 0.31831" << endl
|
||||
<< " return (" << depNames[1] << "(uv) * inv_pi" << endl
|
||||
<< " + " << depNames[2] << "(uv) * specRef) * cosTheta(wo);" << endl
|
||||
<< "}" << endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
<< " if (wi.z <= 0.0 || wo.z <= 0.0)" << endl
|
||||
<< " return vec3(0.0);" << endl
|
||||
<< " return " << depNames[1] << "(uv) * (0.31831 * cosTheta(wo));" << endl
|
||||
<< " return " << depNames[1] << "(uv) * (inv_pi * cosTheta(wo));" << endl
|
||||
<< "}" << endl;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,10 +35,10 @@ MTS_NAMESPACE_BEGIN
|
|||
* for physical realism, this parameter should never be touched. \default{1.0}}
|
||||
* \parameter{diffuse\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
|
||||
* factor used to modulate the diffuse reflection component\default{0.5}}
|
||||
* \parameter{preserveColors}{\Boolean}{
|
||||
* Account for color shifts due to internal scattering? See the main text
|
||||
* for a detailed description.\default{Don't account for them and
|
||||
* preserve the colors, i.e. \code{true}}
|
||||
* \parameter{nonlinear}{\Boolean}{
|
||||
* Account for nonlinear color shifts due to internal scattering? See the
|
||||
* main text for details.\default{Don't account for them and
|
||||
* preserve the texture colors, i.e. \code{false}}
|
||||
* }
|
||||
* }
|
||||
*
|
||||
|
@ -75,11 +75,11 @@ MTS_NAMESPACE_BEGIN
|
|||
*
|
||||
* \renderings{
|
||||
* \medrendering{Diffuse textured rendering}{bsdf_plastic_diffuse}
|
||||
* \medrendering{Plastic, \code{preserveColors=true}}{bsdf_plastic_preserve}
|
||||
* \medrendering{Plastic, \code{preserveColors=false}}{bsdf_plastic_nopreserve}
|
||||
* \medrendering{Plastic, \code{nonlinear=false}}{bsdf_plastic_preserve}
|
||||
* \medrendering{Plastic, \code{nonlinear=true}}{bsdf_plastic_nopreserve}
|
||||
* \caption{
|
||||
* \label{fig:plastic-preservecolors}
|
||||
* When asked to do so, this model can account for subtle color shifts due
|
||||
* \label{fig:plastic-nonlinear}
|
||||
* When asked to do so, this model can account for subtle nonlinear 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
|
||||
|
@ -92,8 +92,8 @@ MTS_NAMESPACE_BEGIN
|
|||
* base layer on its own---in particular, the material color will tend to shift towards
|
||||
* 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.
|
||||
* the parameter \code{nonlinear=true} to enable them.
|
||||
* \figref{plastic-nonlinear} 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
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
m_diffuseReflectance = new ConstantSpectrumTexture(
|
||||
props.getSpectrum("diffuseReflectance", Spectrum(0.5f)));
|
||||
|
||||
m_preserveColors = props.getBoolean("preserveColors", true);
|
||||
m_nonlinear = props.getBoolean("nonlinear", false);
|
||||
|
||||
m_specularSamplingWeight = 0.0f;
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ public:
|
|||
: BSDF(stream, manager) {
|
||||
m_intIOR = stream->readFloat();
|
||||
m_extIOR = stream->readFloat();
|
||||
m_preserveColors = stream->readBool();
|
||||
m_nonlinear = stream->readBool();
|
||||
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_diffuseReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
configure();
|
||||
|
@ -153,7 +153,8 @@ public:
|
|||
m_diffuseReflectance, "diffuseReflectance", 1.0f);
|
||||
|
||||
/* Numerically approximate the diffuse Fresnel reflectance */
|
||||
m_fdr = fresnelDiffuseReflectance(m_extIOR / m_intIOR, false);
|
||||
m_fdrInt = fresnelDiffuseReflectance(m_extIOR / m_intIOR, false);
|
||||
m_fdrExt = fresnelDiffuseReflectance(m_intIOR / m_extIOR, false);
|
||||
|
||||
/* Compute weights that further steer samples towards
|
||||
the specular or diffuse components */
|
||||
|
@ -162,8 +163,8 @@ public:
|
|||
|
||||
m_specularSamplingWeight = sAvg / (dAvg + sAvg);
|
||||
|
||||
Float eta = m_extIOR / m_intIOR;
|
||||
m_eta2 = eta*eta;
|
||||
Float invEta = m_extIOR / m_intIOR;
|
||||
m_invEta2 = invEta*invEta;
|
||||
|
||||
m_usesRayDifferentials =
|
||||
m_specularReflectance->usesRayDifferentials() ||
|
||||
|
@ -178,9 +179,8 @@ public:
|
|||
BSDF::configure();
|
||||
}
|
||||
|
||||
|
||||
Spectrum getDiffuseReflectance(const Intersection &its) const {
|
||||
return m_diffuseReflectance->getValue(its);
|
||||
return m_diffuseReflectance->getValue(its) * (1-m_fdrExt);
|
||||
}
|
||||
|
||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||
|
@ -188,7 +188,7 @@ public:
|
|||
|
||||
stream->writeFloat(m_intIOR);
|
||||
stream->writeFloat(m_extIOR);
|
||||
stream->writeBool(m_preserveColors);
|
||||
stream->writeBool(m_nonlinear);
|
||||
manager->serialize(stream, m_specularReflectance.get());
|
||||
manager->serialize(stream, m_diffuseReflectance.get());
|
||||
}
|
||||
|
@ -232,11 +232,11 @@ public:
|
|||
Float Fr2 = fresnel(Frame::cosTheta(bRec.wo), m_extIOR, m_intIOR);
|
||||
|
||||
Spectrum diff = m_diffuseReflectance->getValue(bRec.its);
|
||||
if (m_preserveColors)
|
||||
diff /= 1 - m_fdr;
|
||||
if (m_nonlinear)
|
||||
diff /= Spectrum(1) - diff * m_fdrInt;
|
||||
else
|
||||
diff /= Spectrum(1) - diff * m_fdr;
|
||||
return diff * (INV_PI * Frame::cosTheta(bRec.wo) * m_eta2 * (1-Fr) * (1-Fr2));
|
||||
diff /= 1 - m_fdrInt;
|
||||
return diff * (INV_PI * Frame::cosTheta(bRec.wo) * m_invEta2 * (1-Fr) * (1-Fr2));
|
||||
}
|
||||
|
||||
return Spectrum(0.0f);
|
||||
|
@ -305,12 +305,12 @@ public:
|
|||
Float Fr2 = fresnel(Frame::cosTheta(bRec.wo), m_extIOR, m_intIOR);
|
||||
|
||||
Spectrum diff = m_diffuseReflectance->getValue(bRec.its);
|
||||
if (m_preserveColors)
|
||||
diff /= 1 - m_fdr;
|
||||
if (m_nonlinear)
|
||||
diff /= Spectrum(1) - m_fdrInt*diff;
|
||||
else
|
||||
diff /= Spectrum(1) - m_fdr*diff;
|
||||
diff /= 1 - m_fdrInt;
|
||||
|
||||
return diff * (m_eta2 * (1-Fr) * (1-Fr2) / (1-probSpecular));
|
||||
return diff * (m_invEta2 * (1-Fr) * (1-Fr2) / (1-probSpecular));
|
||||
}
|
||||
} else if (hasSpecular) {
|
||||
bRec.sampledComponent = 0;
|
||||
|
@ -324,12 +324,12 @@ public:
|
|||
bRec.sampledType = EDiffuseReflection;
|
||||
|
||||
Spectrum diff = m_diffuseReflectance->getValue(bRec.its);
|
||||
if (m_preserveColors)
|
||||
diff /= 1 - m_fdr;
|
||||
if (m_nonlinear)
|
||||
diff /= Spectrum(1) - diff*m_fdrInt;
|
||||
else
|
||||
diff /= Spectrum(1) - m_fdr*diff;
|
||||
diff /= 1 - m_fdrInt;
|
||||
|
||||
return diff * (m_eta2 * (1-Fr) * (1-Fr2));
|
||||
return diff * (m_invEta2 * (1-Fr) * (1-Fr2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,14 +367,14 @@ public:
|
|||
Float Fr2 = fresnel(Frame::cosTheta(bRec.wo), m_extIOR, m_intIOR);
|
||||
|
||||
Spectrum diff = m_diffuseReflectance->getValue(bRec.its);
|
||||
if (m_preserveColors)
|
||||
diff /= 1 - m_fdr;
|
||||
if (m_nonlinear)
|
||||
diff /= Spectrum(1) - diff*m_fdrInt;
|
||||
else
|
||||
diff /= Spectrum(1) - m_fdr*diff;
|
||||
diff /= 1 - m_fdrInt;
|
||||
|
||||
pdf = (1-probSpecular) * Frame::cosTheta(bRec.wo) * INV_PI;
|
||||
|
||||
return diff * (m_eta2 * (1-Fr) * (1-Fr2) / (1-probSpecular));
|
||||
return diff * (m_invEta2 * (1-Fr) * (1-Fr2) / (1-probSpecular));
|
||||
}
|
||||
} else if (hasSpecular) {
|
||||
bRec.sampledComponent = 0;
|
||||
|
@ -391,12 +391,12 @@ public:
|
|||
pdf = Frame::cosTheta(bRec.wo) * INV_PI;
|
||||
|
||||
Spectrum diff = m_diffuseReflectance->getValue(bRec.its);
|
||||
if (m_preserveColors)
|
||||
diff /= 1 - m_fdr;
|
||||
if (m_nonlinear)
|
||||
diff /= Spectrum(1) - diff*m_fdrInt;
|
||||
else
|
||||
diff /= Spectrum(1) - m_fdr*diff;
|
||||
diff /= 1 - m_fdrInt;
|
||||
|
||||
return diff * (m_eta2 * (1-Fr) * (1-Fr2));
|
||||
return diff * (m_invEta2 * (1-Fr) * (1-Fr2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,21 +410,23 @@ public:
|
|||
<< " diffuseReflectance = " << indent(m_diffuseReflectance->toString()) << "," << endl
|
||||
<< " specularSamplingWeight = " << m_specularSamplingWeight << "," << endl
|
||||
<< " diffuseSamplingWeight = " << (1-m_specularSamplingWeight) << "," << endl
|
||||
<< " preserveColors = " << m_preserveColors << "," << endl
|
||||
<< " nonlinear = " << m_nonlinear << "," << endl
|
||||
<< " intIOR = " << m_intIOR << "," << endl
|
||||
<< " extIOR = " << m_extIOR << "," << endl
|
||||
<< " fdr = " << m_fdr << endl
|
||||
<< " fdrInt = " << m_fdrInt << "," << endl
|
||||
<< " fdrExt = " << m_fdrExt << endl
|
||||
<< "]";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
private:
|
||||
Float m_intIOR, m_extIOR, m_fdr, m_eta2;
|
||||
Float m_intIOR, m_extIOR;
|
||||
Float m_fdrInt, m_fdrExt, m_invEta2;
|
||||
ref<Texture> m_diffuseReflectance;
|
||||
ref<Texture> m_specularReflectance;
|
||||
Float m_specularSamplingWeight;
|
||||
bool m_preserveColors;
|
||||
bool m_nonlinear;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -512,12 +514,12 @@ public:
|
|||
<< " float G = " << evalName << "_G(H, wi, wo);" << endl
|
||||
<< " float F = " << evalName << "_schlick(1-dot(wi, H));" << endl
|
||||
<< " return specRef * (F * D * G / (4*cosTheta(wi))) + " << endl
|
||||
<< " diffuseRef * ((1-F) * cosTheta(wo) * 0.31831);" << endl
|
||||
<< " diffuseRef * ((1-F) * cosTheta(wo) * inv_pi);" << endl
|
||||
<< "}" << endl
|
||||
<< endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
<< " vec3 diffuseRef = " << depNames[1] << "(uv);" << endl
|
||||
<< " return diffuseRef * 0.31831 * cosTheta(wo);"<< endl
|
||||
<< " return diffuseRef * inv_pi * cosTheta(wo);"<< endl
|
||||
<< "}" << endl;
|
||||
}
|
||||
MTS_DECLARE_CLASS()
|
||||
|
|
|
@ -517,7 +517,7 @@ public:
|
|||
<< "}" << endl
|
||||
<< endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
<< " return " << evalName << "_R0 * 0.31831 * cosTheta(wo);"<< endl
|
||||
<< " return " << evalName << "_R0 * inv_pi * cosTheta(wo);"<< endl
|
||||
<< "}" << endl;
|
||||
}
|
||||
MTS_DECLARE_CLASS()
|
||||
|
|
|
@ -333,13 +333,13 @@ public:
|
|||
<< " tanBeta = sinTheta(wo) / cosTheta(wo);" << endl
|
||||
<< " }" << endl
|
||||
<< " float value = A + B * maxCos * sinAlpha * tanBeta;" << endl
|
||||
<< " return " << depNames[0] << "(uv) * 0.31831 * cosTheta(wo) * value;" << endl
|
||||
<< " return " << depNames[0] << "(uv) * inv_pi * cosTheta(wo) * value;" << endl
|
||||
<< "}" << endl
|
||||
<< endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
<< " if (cosTheta(wi) <= 0.0 || cosTheta(wo) <= 0.0)" << endl
|
||||
<< " return vec3(0.0);" << endl
|
||||
<< " return " << depNames[0] << "(uv) * 0.31831 * cosTheta(wo);" << endl
|
||||
<< " return " << depNames[0] << "(uv) * inv_pi * cosTheta(wo);" << endl
|
||||
<< "}" << endl;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ MTS_NAMESPACE_BEGIN
|
|||
* Due to the underlying microfacet theory,
|
||||
* the use of this distribution here leads to more realistic
|
||||
* behavior than the separately available \pluginref{phong} plugin.
|
||||
* \vspace{-4mm}
|
||||
* \vspace{-3mm}
|
||||
* \end{enumerate}
|
||||
* }
|
||||
* \parameter{alpha}{\Float}{
|
||||
|
@ -60,26 +60,22 @@ MTS_NAMESPACE_BEGIN
|
|||
* that for physical realism, this parameter should never be touched. \default{1.0}}
|
||||
* \parameter{diffuse\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
|
||||
* factor used to modulate the diffuse reflection component\default{0.5}}
|
||||
* \parameter{preserveColors}{\Boolean}{
|
||||
* Account for color shifts due to internal scattering? See the main text
|
||||
* for a detailed description.\default{Don't account for them and
|
||||
* preserve the colors, i.e. \code{true}}
|
||||
* }\vspace{-1mm}
|
||||
* \parameter{nonlinear}{\Boolean}{
|
||||
* Account for nonlinear color shifts due to internal scattering? See the
|
||||
* main text for details.\default{Don't account for them and
|
||||
* preserve the texture colors, i.e. \code{false}}
|
||||
* }
|
||||
* }
|
||||
* \renderings{
|
||||
* \rendering{Beckmann, $\alpha=0.1$}{bsdf_roughplastic_beckmann}
|
||||
* \rendering{GGX, $\alpha=0.3$}{bsdf_roughplastic_ggx}
|
||||
* }\vspace{-1mm}
|
||||
* }
|
||||
*
|
||||
* This plugin implements a realistic microfacet scattering model for rendering
|
||||
* rough dielectric materials with internal scattering, such as plastic. It can
|
||||
* be interpreted as a fancy version of the Cook-Torrance model and should be
|
||||
* preferred over empirical models like \pluginref{phong} and \pluginref{ward}
|
||||
* when possible.
|
||||
* \renderings{
|
||||
* \setcounter{subfigure}{2}
|
||||
* \rendering{Beckmann, $\alpha=0.05$, diffuseReflectance=0}
|
||||
* {bsdf_roughplastic_beckmann_lacquer}
|
||||
* }
|
||||
*
|
||||
* Microfacet theory describes rough surfaces as an arrangement of unresolved and
|
||||
* ideally specular facets, whose normal directions are given by a specially
|
||||
|
@ -112,6 +108,12 @@ MTS_NAMESPACE_BEGIN
|
|||
* which describe a white polypropylene plastic material with a light amount
|
||||
* of roughness modeled using the Beckmann distribution.
|
||||
*
|
||||
* \renderings{
|
||||
* \setcounter{subfigure}{2}
|
||||
* \rendering{Beckmann, $\alpha=0.05$, diffuseReflectance=0}
|
||||
* {bsdf_roughplastic_beckmann_lacquer}
|
||||
* }
|
||||
*
|
||||
* To get an intuition about the effect of the surface roughness
|
||||
* parameter $\alpha$, consider the following approximate differentiation:
|
||||
* a value of $\alpha=0.001-0.01$ corresponds to a material
|
||||
|
@ -119,14 +121,15 @@ MTS_NAMESPACE_BEGIN
|
|||
* otherwise smooth surface finish, $\alpha=0.1$ is relatively rough,
|
||||
* and $\alpha=0.3-0.7$ is \emph{extremely} rough (e.g. an etched or ground
|
||||
* finish). Values significantly above that are probably not too realistic.
|
||||
*
|
||||
*
|
||||
* When rendering with the Phong microfacet
|
||||
* distributions, a conversion is used to turn the specified
|
||||
* $\alpha$ roughness value into the Phong exponent.
|
||||
* This is done in a way, such that the different
|
||||
* distributions all produce a similar appearance for
|
||||
* the same value of $\alpha$.
|
||||
* \begin{xml}[caption={A material definition for rough, black laquer.}, label=lst:roughplastic-lacquer]
|
||||
* \begin{xml}[caption={A material definition for rough, black laquer.},
|
||||
* label=lst:roughplastic-lacquer]
|
||||
* <bsdf type="roughplastic">
|
||||
* <string name="distribution" value="beckmann"/>
|
||||
* <float name="alpha" value="0.05"/>
|
||||
|
@ -162,7 +165,7 @@ public:
|
|||
Log(EError, "The 'roughplastic' plugin currently does not support "
|
||||
"anisotropic microfacet distributions!");
|
||||
|
||||
m_preserveColors = props.getBoolean("preserveColors", true);
|
||||
m_nonlinear = props.getBoolean("nonlinear", true);
|
||||
|
||||
m_alpha = new ConstantFloatTexture(
|
||||
props.getFloat("alpha", 0.1f));
|
||||
|
@ -180,7 +183,7 @@ public:
|
|||
m_alpha = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_intIOR = stream->readFloat();
|
||||
m_extIOR = stream->readFloat();
|
||||
m_preserveColors = stream->readBool();
|
||||
m_nonlinear = stream->readBool();
|
||||
|
||||
configure();
|
||||
}
|
||||
|
@ -210,23 +213,26 @@ public:
|
|||
m_specularSamplingWeight = sAvg / (dAvg + sAvg);
|
||||
|
||||
Float eta = m_intIOR / m_extIOR;
|
||||
m_invEta2 = 1.0f / (eta*eta);
|
||||
|
||||
if (!m_roughTransmittance.get()) {
|
||||
if (!m_externalRoughTransmittance.get()) {
|
||||
/* Load precomputed data used to compute the rough
|
||||
transmittance through the dielectric interface */
|
||||
m_roughTransmittance = new RoughTransmittance(
|
||||
m_externalRoughTransmittance = new RoughTransmittance(
|
||||
m_distribution.getType());
|
||||
|
||||
m_roughTransmittance->checkEta(eta);
|
||||
m_roughTransmittance->checkAlpha(m_alpha->getMinimum().average());
|
||||
m_roughTransmittance->checkAlpha(m_alpha->getMaximum().average());
|
||||
|
||||
m_externalRoughTransmittance->checkEta(eta);
|
||||
m_externalRoughTransmittance->checkAlpha(m_alpha->getMinimum().average());
|
||||
m_externalRoughTransmittance->checkAlpha(m_alpha->getMaximum().average());
|
||||
|
||||
/* Reduce the rough transmittance data to a 2D slice */
|
||||
m_roughTransmittance->setEta(eta);
|
||||
m_internalRoughTransmittance = m_externalRoughTransmittance->clone();
|
||||
m_externalRoughTransmittance->setEta(eta);
|
||||
m_internalRoughTransmittance->setEta(1/eta);
|
||||
|
||||
/* If possible, even reduce it to a 1D slice */
|
||||
if (constAlpha)
|
||||
m_roughTransmittance->setAlpha(
|
||||
m_externalRoughTransmittance->setAlpha(
|
||||
m_alpha->getValue(Intersection()).average());
|
||||
}
|
||||
|
||||
|
@ -238,7 +244,11 @@ public:
|
|||
}
|
||||
|
||||
Spectrum getDiffuseReflectance(const Intersection &its) const {
|
||||
return m_diffuseReflectance->getValue(its);
|
||||
/* Evaluate the roughness texture */
|
||||
Float alpha = m_alpha->getValue(its).average();
|
||||
Float Ftr = m_externalRoughTransmittance->evalDiffuse(alpha);
|
||||
|
||||
return m_diffuseReflectance->getValue(its) * Ftr;
|
||||
}
|
||||
|
||||
/// Helper function: reflect \c wi with respect to a given surface normal
|
||||
|
@ -285,16 +295,16 @@ public:
|
|||
|
||||
if (hasDiffuse) {
|
||||
Spectrum diff = m_diffuseReflectance->getValue(bRec.its);
|
||||
Float T12 = m_roughTransmittance->eval(Frame::cosTheta(bRec.wi), alpha);
|
||||
Float T21 = m_roughTransmittance->eval(Frame::cosTheta(bRec.wo), alpha);
|
||||
Float Fdr = 1-m_roughTransmittance->evalDiffuse(alpha);
|
||||
Float T12 = m_externalRoughTransmittance->eval(Frame::cosTheta(bRec.wi), alpha);
|
||||
Float T21 = m_externalRoughTransmittance->eval(Frame::cosTheta(bRec.wo), alpha);
|
||||
Float Fdr = 1-m_internalRoughTransmittance->evalDiffuse(alpha);
|
||||
|
||||
if (m_preserveColors)
|
||||
diff /= 1-Fdr;
|
||||
else
|
||||
if (m_nonlinear)
|
||||
diff /= Spectrum(1.0f) - diff * Fdr;
|
||||
else
|
||||
diff /= 1-Fdr;
|
||||
|
||||
result += diff * (INV_PI * Frame::cosTheta(bRec.wo) * T12 * T21);
|
||||
result += diff * (INV_PI * Frame::cosTheta(bRec.wo) * T12 * T21 * m_invEta2);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -322,7 +332,7 @@ public:
|
|||
Float probDiffuse, probSpecular;
|
||||
if (hasSpecular && hasDiffuse) {
|
||||
/* Find the probability of sampling the specular component */
|
||||
probSpecular = 1-m_roughTransmittance->eval(Frame::cosTheta(bRec.wi), alpha);
|
||||
probSpecular = 1-m_externalRoughTransmittance->eval(Frame::cosTheta(bRec.wi), alpha);
|
||||
|
||||
/* Reallocate samples */
|
||||
probSpecular = (probSpecular*m_specularSamplingWeight) /
|
||||
|
@ -370,7 +380,7 @@ public:
|
|||
Float probSpecular;
|
||||
if (hasSpecular && hasDiffuse) {
|
||||
/* Find the probability of sampling the specular component */
|
||||
probSpecular = 1 - m_roughTransmittance->eval(Frame::cosTheta(bRec.wi), alpha);
|
||||
probSpecular = 1 - m_externalRoughTransmittance->eval(Frame::cosTheta(bRec.wi), alpha);
|
||||
|
||||
/* Reallocate samples */
|
||||
probSpecular = (probSpecular*m_specularSamplingWeight) /
|
||||
|
@ -424,7 +434,7 @@ public:
|
|||
manager->serialize(stream, m_alpha.get());
|
||||
stream->writeFloat(m_intIOR);
|
||||
stream->writeFloat(m_extIOR);
|
||||
stream->writeBool(m_preserveColors);
|
||||
stream->writeBool(m_nonlinear);
|
||||
}
|
||||
|
||||
void addChild(const std::string &name, ConfigurableObject *child) {
|
||||
|
@ -452,7 +462,7 @@ public:
|
|||
<< " diffuseReflectance = " << indent(m_diffuseReflectance->toString()) << "," << endl
|
||||
<< " specularSamplingWeight = " << m_specularSamplingWeight << "," << endl
|
||||
<< " diffuseSamplingWeight = " << (1-m_specularSamplingWeight) << "," << endl
|
||||
<< " preserveColors = " << m_preserveColors << "," << endl
|
||||
<< " nonlinear = " << m_nonlinear << "," << endl
|
||||
<< " intIOR = " << m_intIOR << "," << endl
|
||||
<< " extIOR = " << m_extIOR << endl
|
||||
<< "]";
|
||||
|
@ -464,13 +474,14 @@ public:
|
|||
MTS_DECLARE_CLASS()
|
||||
private:
|
||||
MicrofacetDistribution m_distribution;
|
||||
ref<RoughTransmittance> m_roughTransmittance;
|
||||
ref<RoughTransmittance> m_externalRoughTransmittance;
|
||||
ref<RoughTransmittance> m_internalRoughTransmittance;
|
||||
ref<Texture> m_diffuseReflectance;
|
||||
ref<Texture> m_specularReflectance;
|
||||
ref<Texture> m_alpha;
|
||||
Float m_intIOR, m_extIOR;
|
||||
Float m_intIOR, m_extIOR, m_invEta2;
|
||||
Float m_specularSamplingWeight;
|
||||
bool m_preserveColors;
|
||||
bool m_nonlinear;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -520,7 +531,7 @@ public:
|
|||
}
|
||||
|
||||
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs, int &textureUnitOffset) const {
|
||||
program->setParameter(parameterIDs[1], m_R0);
|
||||
program->setParameter(parameterIDs[0], m_R0);
|
||||
}
|
||||
|
||||
void generateCode(std::ostringstream &oss,
|
||||
|
@ -559,17 +570,18 @@ public:
|
|||
<< " vec3 H = normalize(wi + wo);" << endl
|
||||
<< " vec3 specRef = " << depNames[0] << "(uv);" << endl
|
||||
<< " vec3 diffuseRef = " << depNames[1] << "(uv);" << endl
|
||||
<< " float alpha = " << depNames[2] << "(uv)[0];" << endl
|
||||
// << " float alpha = max(0.2, " << depNames[2] << "(uv)[0]);" << endl
|
||||
<< " float alpha = 0.4;" << endl
|
||||
<< " float D = " << evalName << "_D(H, alpha)" << ";" << endl
|
||||
<< " float G = " << evalName << "_G(H, wi, wo);" << endl
|
||||
<< " float F = " << evalName << "_schlick(1-dot(wi, H));" << endl
|
||||
<< " return specRef * (F * D * G / (4*cosTheta(wi))) + " << endl
|
||||
<< " diffuseRef * ((1-F) * cosTheta(wo) * 0.31831);" << endl
|
||||
<< " diffuseRef * ((1-F) * cosTheta(wo) * inv_pi);" << endl
|
||||
<< "}" << endl
|
||||
<< endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
<< " vec3 diffuseRef = " << depNames[1] << "(uv);" << endl
|
||||
<< " return diffuseRef * 0.31831 * cosTheta(wo);"<< endl
|
||||
<< " return diffuseRef * inv_pi * cosTheta(wo);"<< endl
|
||||
<< "}" << endl;
|
||||
}
|
||||
MTS_DECLARE_CLASS()
|
||||
|
|
|
@ -102,17 +102,17 @@ public:
|
|||
m_alphaSamples = fstream->readSize();
|
||||
m_thetaSamples = fstream->readSize();
|
||||
|
||||
size_t transSize = 2 * m_etaSamples * m_alphaSamples * m_thetaSamples;
|
||||
size_t diffTransSize = 2 * m_etaSamples * m_alphaSamples;
|
||||
m_transSize = 2 * m_etaSamples * m_alphaSamples * m_thetaSamples;
|
||||
m_diffTransSize = 2 * m_etaSamples * m_alphaSamples;
|
||||
|
||||
SLog(EDebug, "Loading " SIZE_T_FMT "x" SIZE_T_FMT "x" SIZE_T_FMT
|
||||
" (%s) rough transmittance samples from \"%s\"", 2*m_etaSamples,
|
||||
m_alphaSamples, m_thetaSamples,
|
||||
memString((transSize + diffTransSize) * sizeof(float)).c_str(),
|
||||
memString((m_transSize + m_diffTransSize) * sizeof(float)).c_str(),
|
||||
sourceFile.file_string().c_str());
|
||||
|
||||
m_trans = new Float[transSize];
|
||||
m_diffTrans = new Float[diffTransSize];
|
||||
m_trans = new Float[m_transSize];
|
||||
m_diffTrans = new Float[m_diffTransSize];
|
||||
m_etaFixed = false;
|
||||
m_alphaFixed = false;
|
||||
|
||||
|
@ -125,8 +125,8 @@ public:
|
|||
"[%.4f, %.1f] and roughness range [%.4f, %.1f]", m_etaMin,
|
||||
m_etaMax, m_alphaMin, m_alphaMax);
|
||||
|
||||
float *temp = new float[transSize + diffTransSize];
|
||||
fstream->readSingleArray(temp, transSize + diffTransSize);
|
||||
float *temp = new float[m_transSize + m_diffTransSize];
|
||||
fstream->readSingleArray(temp, m_transSize + m_diffTransSize);
|
||||
|
||||
float *ptr = temp;
|
||||
size_t fdrEntry = 0, dataEntry = 0;
|
||||
|
@ -282,11 +282,11 @@ public:
|
|||
if (m_etaFixed)
|
||||
return;
|
||||
|
||||
size_t transSize = m_alphaSamples * m_thetaSamples;
|
||||
size_t diffTransSize = m_alphaSamples;
|
||||
m_transSize = m_alphaSamples * m_thetaSamples;
|
||||
m_diffTransSize = m_alphaSamples;
|
||||
|
||||
SLog(EDebug, "Reducing dimension from 3D to 2D (%s), eta = %f",
|
||||
memString((transSize + diffTransSize) * sizeof(Float)).c_str(), eta);
|
||||
memString((m_transSize + m_diffTransSize) * sizeof(Float)).c_str(), eta);
|
||||
|
||||
Float *trans = m_trans,
|
||||
*diffTrans = m_diffTrans;
|
||||
|
@ -305,8 +305,8 @@ public:
|
|||
Float warpedEta = std::pow((eta - m_etaMin)
|
||||
/ (m_etaMax-m_etaMin), 0.25f);
|
||||
|
||||
Float *newTrans = new Float[transSize];
|
||||
Float *newDiffTrans = new Float[diffTransSize];
|
||||
Float *newTrans = new Float[m_transSize];
|
||||
Float *newDiffTrans = new Float[m_diffTransSize];
|
||||
|
||||
Float dAlpha = 1.0f / (m_alphaSamples - 1),
|
||||
dTheta = 1.0f / (m_thetaSamples - 1);
|
||||
|
@ -344,17 +344,17 @@ public:
|
|||
if (m_alphaFixed)
|
||||
return;
|
||||
|
||||
size_t transSize = m_thetaSamples;
|
||||
size_t diffTransSize = 1;
|
||||
m_transSize = m_thetaSamples;
|
||||
m_diffTransSize = 1;
|
||||
|
||||
SLog(EDebug, "Reducing dimension from 2D to 1D (%s), alpha = %f",
|
||||
memString((transSize + diffTransSize) * sizeof(Float)).c_str(), alpha);
|
||||
memString((m_transSize + m_diffTransSize) * sizeof(Float)).c_str(), alpha);
|
||||
|
||||
Float warpedAlpha = std::pow((alpha - m_alphaMin)
|
||||
/ (m_alphaMax-m_alphaMin), 0.25f);
|
||||
|
||||
Float *newTrans = new Float[transSize];
|
||||
Float *newDiffTrans = new Float[diffTransSize];
|
||||
Float *newTrans = new Float[m_transSize];
|
||||
Float *newDiffTrans = new Float[m_diffTransSize];
|
||||
|
||||
Float dTheta = 1.0f / (m_thetaSamples - 1);
|
||||
|
||||
|
@ -388,12 +388,35 @@ public:
|
|||
if (eta < 1)
|
||||
eta = 1/eta;
|
||||
if (eta < m_etaMin || eta > m_etaMax)
|
||||
SLog(EError, "Error: the requested index of refraction eta=%f is"
|
||||
" outside of the supported range [%f, %f]! Please update your "
|
||||
" scene so that it uses realistic IOR values.", eta,
|
||||
m_etaMin, m_etaMax);
|
||||
SLog(EError, "Error: the requested relative index of refraction "
|
||||
"eta=%f is outside of the supported range [%f, %f]! Please "
|
||||
"update your scene so that it uses realistic IOR values.",
|
||||
eta, m_etaMin, m_etaMax);
|
||||
}
|
||||
|
||||
/// Create a deep copy of the current instance
|
||||
ref<RoughTransmittance> clone() const {
|
||||
RoughTransmittance *result = new RoughTransmittance();
|
||||
result->m_name = m_name;
|
||||
result->m_etaSamples = m_etaSamples;
|
||||
result->m_alphaSamples = m_alphaSamples;
|
||||
result->m_thetaSamples = m_thetaSamples;
|
||||
result->m_etaFixed = m_etaFixed;
|
||||
result->m_alphaFixed = m_alphaFixed;
|
||||
result->m_etaMin = m_etaMin;
|
||||
result->m_etaMax = m_etaMax;
|
||||
result->m_alphaMin = m_alphaMin;
|
||||
result->m_alphaMax = m_alphaMax;
|
||||
result->m_transSize = m_transSize;
|
||||
result->m_diffTransSize = m_diffTransSize;
|
||||
result->m_trans = new Float[m_transSize];
|
||||
result->m_diffTrans = new Float[m_diffTransSize];
|
||||
memcpy(result->m_trans, m_trans, m_transSize * sizeof(Float));
|
||||
memcpy(result->m_diffTrans, m_diffTrans, m_diffTransSize * sizeof(Float));
|
||||
return result;
|
||||
}
|
||||
protected:
|
||||
inline RoughTransmittance() { }
|
||||
protected:
|
||||
std::string m_name;
|
||||
size_t m_etaSamples;
|
||||
|
@ -403,6 +426,8 @@ protected:
|
|||
bool m_alphaFixed;
|
||||
Float m_etaMin, m_etaMax;
|
||||
Float m_alphaMin, m_alphaMax;
|
||||
size_t m_transSize;
|
||||
size_t m_diffTransSize;
|
||||
Float *m_trans, *m_diffTrans;
|
||||
};
|
||||
|
||||
|
|
|
@ -449,13 +449,13 @@ public:
|
|||
<< " float factor2 = H.x / alphaU, factor3 = H.y / alphaV;" << endl
|
||||
<< " float exponent = -(factor2*factor2 + factor3*factor3)/(H.z*H.z);" << endl
|
||||
<< " float specRef = factor1 * exp(exponent);" << endl
|
||||
<< " return (" << depNames[0] << "(uv) * 0.31831" << endl
|
||||
<< " return (" << depNames[0] << "(uv) * inv_pi" << endl
|
||||
<< " + " << depNames[1] << "(uv) * specRef) * cosTheta(wo);" << endl
|
||||
<< "}" << endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
<< " if (wi.z <= 0.0 || wo.z <= 0.0)" << endl
|
||||
<< " return vec3(0.0);" << endl
|
||||
<< " return " << depNames[0] << "(uv) * (0.31831 * cosTheta(wo));" << endl
|
||||
<< " return " << depNames[0] << "(uv) * (inv_pi * cosTheta(wo));" << endl
|
||||
<< "}" << endl;
|
||||
}
|
||||
|
||||
|
|
|
@ -503,6 +503,7 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
|
|||
<< "float sinPhi(vec3 v) { return v.y/sinTheta(v); }" << endl
|
||||
<< "float cosPhi(vec3 v) { return v.x/sinTheta(v); }" << endl
|
||||
<< "const float pi = 3.141592653589;" << endl
|
||||
<< "const float inv_pi = 0.318309886183791;" << endl
|
||||
<< endl;
|
||||
|
||||
std::string vplEvalName, bsdfEvalName, lumEvalName;
|
||||
|
|
Loading…
Reference in New Issue