renamed the mixture BSDF, added support for reparameterizing the HK & SSBRDF plugins in terms of albedo
parent
cd69e50a73
commit
bc16235f6f
|
@ -205,7 +205,7 @@
|
||||||
|
|
||||||
<!-- Update the name of the composite plugin -->
|
<!-- Update the name of the composite plugin -->
|
||||||
<xsl:template match="bsdf[@type='composite']/@type">
|
<xsl:template match="bsdf[@type='composite']/@type">
|
||||||
<xsl:attribute name="type">mixture</xsl:attribute>
|
<xsl:attribute name="type">mixturebsdf</xsl:attribute>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
|
||||||
<!-- Update the name of the exrtexture plugin -->
|
<!-- Update the name of the exrtexture plugin -->
|
||||||
|
|
|
@ -126,6 +126,159 @@ protected:
|
||||||
Float m_value;
|
Float m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Componentwise addition of two textures
|
||||||
|
*
|
||||||
|
* Includes a \ref Shader implementation for hardware rendering
|
||||||
|
*/
|
||||||
|
class MTS_EXPORT_HW SpectrumAdditionTexture : public Texture {
|
||||||
|
public:
|
||||||
|
inline SpectrumAdditionTexture(const Texture *a, const Texture *b)
|
||||||
|
: Texture(Properties()), m_a(a), m_b(b) { }
|
||||||
|
|
||||||
|
SpectrumAdditionTexture(Stream *stream, InstanceManager *manager);
|
||||||
|
|
||||||
|
inline Spectrum getValue(const Intersection &its) const {
|
||||||
|
return m_a->getValue(its) + m_b->getValue(its);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Spectrum getAverage() const {
|
||||||
|
return m_a->getAverage() + m_b->getAverage();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Spectrum getMaximum() const {
|
||||||
|
SLog(EError, "SpectrumAdditionTexture::getMaximum() -- information unavailable!");
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isConstant() const {
|
||||||
|
return m_a->isConstant() && m_b->isConstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string toString() const {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "SpectrumAdditionTexture[" << endl
|
||||||
|
<< " a = " << indent(m_a->toString()) << "," << endl
|
||||||
|
<< " b = " << indent(m_a->toString()) << endl
|
||||||
|
<< "]";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool usesRayDifferentials() const {
|
||||||
|
return m_a->usesRayDifferentials() || m_b->usesRayDifferentials();
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader *createShader(Renderer *renderer) const;
|
||||||
|
|
||||||
|
void serialize(Stream *stream, InstanceManager *manager) const;
|
||||||
|
|
||||||
|
MTS_DECLARE_CLASS()
|
||||||
|
protected:
|
||||||
|
ref<const Texture> m_a, m_b;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Componentwise subtraction of two textures
|
||||||
|
*
|
||||||
|
* Includes a \ref Shader implementation for hardware rendering
|
||||||
|
*/
|
||||||
|
class MTS_EXPORT_HW SpectrumSubtractionTexture : public Texture {
|
||||||
|
public:
|
||||||
|
inline SpectrumSubtractionTexture(const Texture *a, const Texture *b)
|
||||||
|
: Texture(Properties()), m_a(a), m_b(b) { }
|
||||||
|
|
||||||
|
SpectrumSubtractionTexture(Stream *stream, InstanceManager *manager);
|
||||||
|
|
||||||
|
inline Spectrum getValue(const Intersection &its) const {
|
||||||
|
return m_a->getValue(its) - m_b->getValue(its);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Spectrum getAverage() const {
|
||||||
|
return m_a->getAverage() - m_b->getAverage();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Spectrum getMaximum() const {
|
||||||
|
SLog(EError, "SpectrumSubtractionTexture::getMaximum() -- information unavailable!");
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isConstant() const {
|
||||||
|
return m_a->isConstant() && m_b->isConstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string toString() const {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "SpectrumSubtractionTexture[" << endl
|
||||||
|
<< " a = " << indent(m_a->toString()) << "," << endl
|
||||||
|
<< " b = " << indent(m_b->toString()) << endl
|
||||||
|
<< "]";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool usesRayDifferentials() const {
|
||||||
|
return m_a->usesRayDifferentials() || m_b->usesRayDifferentials();
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader *createShader(Renderer *renderer) const;
|
||||||
|
|
||||||
|
void serialize(Stream *stream, InstanceManager *manager) const;
|
||||||
|
|
||||||
|
MTS_DECLARE_CLASS()
|
||||||
|
protected:
|
||||||
|
ref<const Texture> m_a, m_b;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Componentwise product of two textures
|
||||||
|
*
|
||||||
|
* Includes a \ref Shader implementation for hardware rendering
|
||||||
|
*/
|
||||||
|
class MTS_EXPORT_HW SpectrumProductTexture : public Texture {
|
||||||
|
public:
|
||||||
|
inline SpectrumProductTexture(const Texture *a, const Texture *b)
|
||||||
|
: Texture(Properties()), m_a(a), m_b(b) { }
|
||||||
|
|
||||||
|
SpectrumProductTexture(Stream *stream, InstanceManager *manager);
|
||||||
|
|
||||||
|
inline Spectrum getValue(const Intersection &its) const {
|
||||||
|
return m_a->getValue(its) * m_b->getValue(its);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Spectrum getAverage() const {
|
||||||
|
SLog(EError, "SpectrumProductTexture::getAverage() -- information unavailable!");
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Spectrum getMaximum() const {
|
||||||
|
return m_a->getMaximum() * m_b->getMaximum();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isConstant() const {
|
||||||
|
return m_a->isConstant() && m_b->isConstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string toString() const {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "SpectrumProductTexture[" << endl
|
||||||
|
<< " a = " << indent(m_a->toString()) << "," << endl
|
||||||
|
<< " b = " << indent(m_b->toString()) << endl
|
||||||
|
<< "]";
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool usesRayDifferentials() const {
|
||||||
|
return m_a->usesRayDifferentials() || m_b->usesRayDifferentials();
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader *createShader(Renderer *renderer) const;
|
||||||
|
|
||||||
|
void serialize(Stream *stream, InstanceManager *manager) const;
|
||||||
|
|
||||||
|
MTS_DECLARE_CLASS()
|
||||||
|
protected:
|
||||||
|
ref<const Texture> m_a, m_b;
|
||||||
|
};
|
||||||
|
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
||||||
#endif /* __BASIC_SHADER_H */
|
#endif /* __BASIC_SHADER_H */
|
||||||
|
|
|
@ -13,7 +13,7 @@ plugins += env.SharedLibrary('roughplastic', ['roughplastic.cpp'])
|
||||||
# Materials that act as modifiers
|
# Materials that act as modifiers
|
||||||
plugins += env.SharedLibrary('twosided', ['twosided.cpp'])
|
plugins += env.SharedLibrary('twosided', ['twosided.cpp'])
|
||||||
plugins += env.SharedLibrary('mask', ['mask.cpp'])
|
plugins += env.SharedLibrary('mask', ['mask.cpp'])
|
||||||
plugins += env.SharedLibrary('mixture', ['mixture.cpp'])
|
plugins += env.SharedLibrary('mixturebsdf', ['mixturebsdf.cpp'])
|
||||||
plugins += env.SharedLibrary('coating', ['coating.cpp'])
|
plugins += env.SharedLibrary('coating', ['coating.cpp'])
|
||||||
plugins += env.SharedLibrary('bump', ['bump.cpp'])
|
plugins += env.SharedLibrary('bump', ['bump.cpp'])
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,10 @@ MTS_NAMESPACE_BEGIN
|
||||||
*
|
*
|
||||||
* This BSDF models a non-reflective material, where any entering light loses
|
* This BSDF models a non-reflective material, where any entering light loses
|
||||||
* its directionality and is diffusely scattered from the other side. This
|
* its directionality and is diffusely scattered from the other side. This
|
||||||
* model can be combined\footnote{For instance using the \pluginref{mixture}
|
* model can be combined\footnote{For instance using the
|
||||||
* plugin.} with a surface reflection model to describe translucent substances
|
* \pluginref{mixturebsdf} plugin.} with a surface reflection model to
|
||||||
* that have internal multiple scattering processes (e.g. plant leaves).
|
* describe translucent substances that have internal multiple scattering
|
||||||
|
* processes (e.g. plant leaves).
|
||||||
*/
|
*/
|
||||||
class DiffuseTransmitter : public BSDF {
|
class DiffuseTransmitter : public BSDF {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
: BSDF(props) {
|
: BSDF(props) {
|
||||||
|
|
||||||
Spectrum sigmaS, sigmaA;
|
Spectrum sigmaS, sigmaA;
|
||||||
Float eta;
|
Float eta = 1.33f;
|
||||||
lookupMaterial(props, sigmaS, sigmaA, &eta, false);
|
lookupMaterial(props, sigmaS, sigmaA, &eta, false);
|
||||||
|
|
||||||
/* Specifies the internal index of refraction at the interface */
|
/* Specifies the internal index of refraction at the interface */
|
||||||
|
@ -85,10 +85,23 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void configure() {
|
void configure() {
|
||||||
|
if (m_sigmaT != NULL || m_albedo != NULL) {
|
||||||
|
/* Support for the alternative scattering/absorption
|
||||||
|
* coefficient parameter passing convention */
|
||||||
|
if (m_sigmaT == NULL || m_albedo == NULL)
|
||||||
|
SLog(EError, "Please provide *both* sigmaT & albedo!");
|
||||||
|
|
||||||
|
m_sigmaS = new SpectrumProductTexture(m_sigmaT, m_albedo);
|
||||||
|
m_sigmaA = new SpectrumSubtractionTexture(m_sigmaT, m_sigmaS);
|
||||||
|
m_sigmaT = NULL;
|
||||||
|
m_albedo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
m_components.clear();
|
m_components.clear();
|
||||||
m_components.push_back(EDiffuseReflection | EFrontSide
|
m_components.push_back(EDiffuseReflection | EFrontSide
|
||||||
| (m_sigmaS->isConstant() && m_sigmaA->isConstant() ? 0 : ESpatiallyVarying));
|
| (m_sigmaS->isConstant() && m_sigmaA->isConstant() ? 0 : ESpatiallyVarying));
|
||||||
m_usesRayDifferentials = m_sigmaS->usesRayDifferentials() || m_sigmaA->usesRayDifferentials();
|
m_usesRayDifferentials = m_sigmaS->usesRayDifferentials()
|
||||||
|
|| m_sigmaA->usesRayDifferentials();
|
||||||
|
|
||||||
if ((m_sigmaS->getMaximum()+m_sigmaA->getMaximum()).isZero())
|
if ((m_sigmaS->getMaximum()+m_sigmaA->getMaximum()).isZero())
|
||||||
Log(EError, "Please specify nonzero sigmaS/sigmaA-values!");
|
Log(EError, "Please specify nonzero sigmaS/sigmaA-values!");
|
||||||
|
@ -176,6 +189,10 @@ public:
|
||||||
m_sigmaS = static_cast<Texture *>(child);
|
m_sigmaS = static_cast<Texture *>(child);
|
||||||
else if (name == "sigmaA")
|
else if (name == "sigmaA")
|
||||||
m_sigmaA = static_cast<Texture *>(child);
|
m_sigmaA = static_cast<Texture *>(child);
|
||||||
|
else if (name == "sigmaT")
|
||||||
|
m_sigmaT = static_cast<Texture *>(child);
|
||||||
|
else if (name == "albedo")
|
||||||
|
m_albedo = static_cast<Texture *>(child);
|
||||||
else
|
else
|
||||||
BSDF::addChild(name, child);
|
BSDF::addChild(name, child);
|
||||||
} else {
|
} else {
|
||||||
|
@ -212,6 +229,9 @@ public:
|
||||||
private:
|
private:
|
||||||
Float m_intIOR, m_extIOR, m_g, m_A;
|
Float m_intIOR, m_extIOR, m_g, m_A;
|
||||||
ref<Texture> m_sigmaS, m_sigmaA;
|
ref<Texture> m_sigmaS, m_sigmaA;
|
||||||
|
/* Temporary fields */
|
||||||
|
ref<Texture> m_sigmaT;
|
||||||
|
ref<Texture> m_albedo;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ================ Hardware shader implementation ================
|
// ================ Hardware shader implementation ================
|
||||||
|
|
|
@ -36,6 +36,12 @@ MTS_NAMESPACE_BEGIN
|
||||||
* of the internal layer. \default{based on \code{material}}}
|
* of the internal layer. \default{based on \code{material}}}
|
||||||
* \parameter{sigmaA}{\Spectrum\Or\Texture}{Specifies the absorption coefficient
|
* \parameter{sigmaA}{\Spectrum\Or\Texture}{Specifies the absorption coefficient
|
||||||
* of the internal layer. \default{based on \code{material}}}
|
* of the internal layer. \default{based on \code{material}}}
|
||||||
|
* \parameter{sigmaT \& albedo}{\Spectrum\Or\Texture}{
|
||||||
|
* Optional: Alternatively, the scattering and absorption coefficients may also be
|
||||||
|
* specified using the extinction coefficient \code{sigmaT} and the
|
||||||
|
* single-scattering albedo. Note that only one of the parameter passing
|
||||||
|
* conventions can be used at a time (i.e. use either \code{sigmaS\&sigmaA}
|
||||||
|
* \emph{or} \code{sigmaT\&albedo})}
|
||||||
* \parameter{thickness}{\Float}{Denotes the thickness of the layer.
|
* \parameter{thickness}{\Float}{Denotes the thickness of the layer.
|
||||||
* (should be specified in inverse units of \code{sigmaA} and \code{sigmaS})\default{1}}
|
* (should be specified in inverse units of \code{sigmaA} and \code{sigmaS})\default{1}}
|
||||||
* \parameter{\Unnamed}{\Phase}{A nested phase function instance that represents
|
* \parameter{\Unnamed}{\Phase}{A nested phase function instance that represents
|
||||||
|
@ -45,12 +51,11 @@ MTS_NAMESPACE_BEGIN
|
||||||
* \renderings{
|
* \renderings{
|
||||||
* \rendering{An index-matched scattering layer with parameters $\sigma_s=2$, $\sigma_a=0.1$, thickness$=0.1$}{bsdf_hk_1}
|
* \rendering{An index-matched scattering layer with parameters $\sigma_s=2$, $\sigma_a=0.1$, thickness$=0.1$}{bsdf_hk_1}
|
||||||
* \rendering{Example of the HK model with a dielectric coating (and the \code{ketchup} material preset, see \lstref{hk-coated})}{bsdf_hk_2}
|
* \rendering{Example of the HK model with a dielectric coating (and the \code{ketchup} material preset, see \lstref{hk-coated})}{bsdf_hk_2}
|
||||||
* \vspace{-3mm}
|
|
||||||
* \caption{
|
* \caption{
|
||||||
* \label{fig:hk-example}
|
* \label{fig:hk-example}
|
||||||
* Renderings using the uncoated and coated form of the Hanrahan-Krueger model.
|
* Renderings using the uncoated and coated form of the Hanrahan-Krueger model.
|
||||||
* }
|
* }
|
||||||
* \vspace{1mm}
|
* \vspace{3mm}
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* This plugin provides an implementation of the Hanrahan-Krueger BSDF
|
* This plugin provides an implementation of the Hanrahan-Krueger BSDF
|
||||||
|
@ -62,7 +67,7 @@ MTS_NAMESPACE_BEGIN
|
||||||
* This BSDF requires a phase function to model scattering interactions within the
|
* This BSDF requires a phase function to model scattering interactions within the
|
||||||
* random medium. When no phase function is explicitly specified, it uses an
|
* random medium. When no phase function is explicitly specified, it uses an
|
||||||
* isotropic one ($g=0$) by default. A sample usage for instantiating the
|
* isotropic one ($g=0$) by default. A sample usage for instantiating the
|
||||||
* plugin is given below:
|
* plugin is given on the next page:\newpage
|
||||||
* \begin{xml}
|
* \begin{xml}
|
||||||
* <bsdf type="hk">
|
* <bsdf type="hk">
|
||||||
* <spectrum name="sigmaS" value="2"/>
|
* <spectrum name="sigmaS" value="2"/>
|
||||||
|
@ -123,7 +128,6 @@ public:
|
||||||
|
|
||||||
/* Slab thickness in inverse units of sigmaS and sigmaA */
|
/* Slab thickness in inverse units of sigmaS and sigmaA */
|
||||||
m_thickness = props.getFloat("thickness", 1);
|
m_thickness = props.getFloat("thickness", 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HanrahanKrueger(Stream *stream, InstanceManager *manager)
|
HanrahanKrueger(Stream *stream, InstanceManager *manager)
|
||||||
|
@ -140,13 +144,29 @@ public:
|
||||||
m_phase = static_cast<PhaseFunction *> (PluginManager::getInstance()->
|
m_phase = static_cast<PhaseFunction *> (PluginManager::getInstance()->
|
||||||
createObject(MTS_CLASS(PhaseFunction), Properties("isotropic")));
|
createObject(MTS_CLASS(PhaseFunction), Properties("isotropic")));
|
||||||
|
|
||||||
|
if (m_sigmaT != NULL || m_albedo != NULL) {
|
||||||
|
/* Support for the alternative scattering/absorption
|
||||||
|
* coefficient parameter passing convention */
|
||||||
|
if (m_sigmaT == NULL || m_albedo == NULL)
|
||||||
|
SLog(EError, "Please provide *both* sigmaT & albedo!");
|
||||||
|
|
||||||
|
m_sigmaS = new SpectrumProductTexture(m_sigmaT, m_albedo);
|
||||||
|
m_sigmaA = new SpectrumSubtractionTexture(m_sigmaT, m_sigmaS);
|
||||||
|
m_sigmaT = NULL;
|
||||||
|
m_albedo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if ((m_sigmaS->getMaximum()+m_sigmaA->getMaximum()).isZero())
|
if ((m_sigmaS->getMaximum()+m_sigmaA->getMaximum()).isZero())
|
||||||
Log(EError, "Please specify nonzero sigmaS/sigmaA-values!");
|
Log(EError, "Please specify nonzero sigmaS/sigmaA-values!");
|
||||||
|
|
||||||
|
int extraFlags = m_sigmaS->isConstant() && m_sigmaA->isConstant() ? 0 : ESpatiallyVarying;
|
||||||
m_components.clear();
|
m_components.clear();
|
||||||
m_components.push_back(EGlossyReflection | EFrontSide | EBackSide | ECanUseSampler);
|
m_components.push_back(EGlossyReflection | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
|
||||||
m_components.push_back(EGlossyTransmission | EFrontSide | EBackSide | ECanUseSampler);
|
m_components.push_back(EGlossyTransmission | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
|
||||||
m_components.push_back(EDeltaTransmission | EFrontSide | EBackSide | ECanUseSampler);
|
m_components.push_back(EDeltaTransmission | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
|
||||||
|
|
||||||
|
m_usesRayDifferentials = m_sigmaS->usesRayDifferentials()
|
||||||
|
|| m_sigmaA->usesRayDifferentials();
|
||||||
|
|
||||||
BSDF::configure();
|
BSDF::configure();
|
||||||
}
|
}
|
||||||
|
@ -369,6 +389,10 @@ public:
|
||||||
m_sigmaS = static_cast<Texture *>(child);
|
m_sigmaS = static_cast<Texture *>(child);
|
||||||
else if (name == "sigmaA")
|
else if (name == "sigmaA")
|
||||||
m_sigmaA = static_cast<Texture *>(child);
|
m_sigmaA = static_cast<Texture *>(child);
|
||||||
|
else if (name == "sigmaT")
|
||||||
|
m_sigmaT = static_cast<Texture *>(child);
|
||||||
|
else if (name == "albedo")
|
||||||
|
m_albedo = static_cast<Texture *>(child);
|
||||||
else
|
else
|
||||||
BSDF::addChild(name, child);
|
BSDF::addChild(name, child);
|
||||||
} else {
|
} else {
|
||||||
|
@ -395,6 +419,9 @@ private:
|
||||||
ref<Texture> m_sigmaS;
|
ref<Texture> m_sigmaS;
|
||||||
ref<Texture> m_sigmaA;
|
ref<Texture> m_sigmaA;
|
||||||
Float m_thickness;
|
Float m_thickness;
|
||||||
|
/* Temporary fields */
|
||||||
|
ref<Texture> m_sigmaT;
|
||||||
|
ref<Texture> m_albedo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
MTS_NAMESPACE_BEGIN
|
MTS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
/*! \plugin{mixture}{Mixture material}
|
/*! \plugin{mixturebsdf}{Mixture material}
|
||||||
*
|
*
|
||||||
* \parameters{
|
* \parameters{
|
||||||
* \parameter{weights}{\String}{A comma-separated list of BSDF weights}
|
* \parameter{weights}{\String}{A comma-separated list of BSDF weights}
|
||||||
|
@ -46,7 +46,7 @@ MTS_NAMESPACE_BEGIN
|
||||||
* \begin{xml}[caption={A material definition for a mixture of 70% smooth
|
* \begin{xml}[caption={A material definition for a mixture of 70% smooth
|
||||||
* chromium, 20% of a greenish rough diffuse material (and 10% absorption)},
|
* chromium, 20% of a greenish rough diffuse material (and 10% absorption)},
|
||||||
* label=lst:mixture-example]
|
* label=lst:mixture-example]
|
||||||
* <bsdf type="mixture">
|
* <bsdf type="mixturebsdf">
|
||||||
* <string name="weights" value="0.7, 0.2"/>
|
* <string name="weights" value="0.7, 0.2"/>
|
||||||
*
|
*
|
||||||
* <bsdf type="conductor">
|
* <bsdf type="conductor">
|
|
@ -34,6 +34,12 @@ MTS_NAMESPACE_BEGIN
|
||||||
* of the layer. \default{based on \code{material}}}
|
* of the layer. \default{based on \code{material}}}
|
||||||
* \parameter{sigmaA}{\Spectrum\Or\Texture}{Specifies the absorption coefficient
|
* \parameter{sigmaA}{\Spectrum\Or\Texture}{Specifies the absorption coefficient
|
||||||
* of the layer. \default{based on \code{material}}}
|
* of the layer. \default{based on \code{material}}}
|
||||||
|
* \parameter{sigmaT \& albedo}{\Spectrum\Or\Texture}{
|
||||||
|
* Optional: Alternatively, the scattering and absorption coefficients may also be
|
||||||
|
* specified using the extinction coefficient \code{sigmaT} and the
|
||||||
|
* single-scattering albedo. Note that only one of the parameter passing
|
||||||
|
* conventions can be used at a time (i.e. use either \code{sigmaS\&sigmaA}
|
||||||
|
* \emph{or} \code{sigmaT\&albedo})}
|
||||||
* \parameter{intIOR}{\Float\Or\String}{Interior index of refraction specified
|
* \parameter{intIOR}{\Float\Or\String}{Interior index of refraction specified
|
||||||
* numerically or using a known material name. \default{based on \code{material}}}
|
* numerically or using a known material name. \default{based on \code{material}}}
|
||||||
* \parameter{extIOR}{\Float\Or\String}{Exterior index of refraction specified
|
* \parameter{extIOR}{\Float\Or\String}{Exterior index of refraction specified
|
||||||
|
@ -97,7 +103,7 @@ public:
|
||||||
m_dipole = static_cast<BSDF *> (PluginManager::getInstance()->
|
m_dipole = static_cast<BSDF *> (PluginManager::getInstance()->
|
||||||
createObject(MTS_CLASS(BSDF), dipoleProps));
|
createObject(MTS_CLASS(BSDF), dipoleProps));
|
||||||
|
|
||||||
Properties mixtureProps("mixture");
|
Properties mixtureProps("mixturebsdf");
|
||||||
mixtureProps.setString("weights", "1.0, 1.0");
|
mixtureProps.setString("weights", "1.0, 1.0");
|
||||||
mixtureProps.setBoolean("ensureEnergyConservation", false);
|
mixtureProps.setBoolean("ensureEnergyConservation", false);
|
||||||
m_mixture = static_cast<BSDF *> (PluginManager::getInstance()->
|
m_mixture = static_cast<BSDF *> (PluginManager::getInstance()->
|
||||||
|
@ -106,6 +112,8 @@ public:
|
||||||
props.markQueried("material");
|
props.markQueried("material");
|
||||||
props.markQueried("sigmaS");
|
props.markQueried("sigmaS");
|
||||||
props.markQueried("sigmaA");
|
props.markQueried("sigmaA");
|
||||||
|
props.markQueried("coating");
|
||||||
|
props.markQueried("sigmaT");
|
||||||
props.markQueried("intIOR");
|
props.markQueried("intIOR");
|
||||||
props.markQueried("extIOR");
|
props.markQueried("extIOR");
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,42 @@ void ConstantFloatTexture::serialize(Stream *stream, InstanceManager *manager) c
|
||||||
stream->writeFloat(m_value);
|
stream->writeFloat(m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpectrumProductTexture::SpectrumProductTexture(Stream *stream, InstanceManager *manager)
|
||||||
|
: Texture(stream, manager) {
|
||||||
|
m_a = static_cast<Texture *>(manager->getInstance(stream));
|
||||||
|
m_b = static_cast<Texture *>(manager->getInstance(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpectrumProductTexture::serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
|
Texture::serialize(stream, manager);
|
||||||
|
manager->serialize(stream, m_a.get());
|
||||||
|
manager->serialize(stream, m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
SpectrumAdditionTexture::SpectrumAdditionTexture(Stream *stream, InstanceManager *manager)
|
||||||
|
: Texture(stream, manager) {
|
||||||
|
m_a = static_cast<Texture *>(manager->getInstance(stream));
|
||||||
|
m_b = static_cast<Texture *>(manager->getInstance(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpectrumAdditionTexture::serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
|
Texture::serialize(stream, manager);
|
||||||
|
manager->serialize(stream, m_a.get());
|
||||||
|
manager->serialize(stream, m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
SpectrumSubtractionTexture::SpectrumSubtractionTexture(Stream *stream, InstanceManager *manager)
|
||||||
|
: Texture(stream, manager) {
|
||||||
|
m_a = static_cast<Texture *>(manager->getInstance(stream));
|
||||||
|
m_b = static_cast<Texture *>(manager->getInstance(stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpectrumSubtractionTexture::serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
|
Texture::serialize(stream, manager);
|
||||||
|
manager->serialize(stream, m_a.get());
|
||||||
|
manager->serialize(stream, m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
class ConstantSpectrumTextureShader : public Shader {
|
class ConstantSpectrumTextureShader : public Shader {
|
||||||
public:
|
public:
|
||||||
ConstantSpectrumTextureShader(Renderer *renderer, const Spectrum &value)
|
ConstantSpectrumTextureShader(Renderer *renderer, const Spectrum &value)
|
||||||
|
@ -99,6 +135,114 @@ private:
|
||||||
Float m_value;
|
Float m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SpectrumProductTextureShader : public Shader {
|
||||||
|
public:
|
||||||
|
SpectrumProductTextureShader(Renderer *renderer, const Texture *a, const Texture *b)
|
||||||
|
: Shader(renderer, ETextureShader), m_a(a), m_b(b) {
|
||||||
|
m_aShader = renderer->registerShaderForResource(m_a.get());
|
||||||
|
m_bShader = renderer->registerShaderForResource(m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isComplete() const {
|
||||||
|
return m_a.get() != NULL && m_b.get() != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup(Renderer *renderer) {
|
||||||
|
renderer->unregisterShaderForResource(m_a.get());
|
||||||
|
renderer->unregisterShaderForResource(m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void putDependencies(std::vector<Shader *> &deps) {
|
||||||
|
deps.push_back(m_aShader.get());
|
||||||
|
deps.push_back(m_bShader.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateCode(std::ostringstream &oss,
|
||||||
|
const std::string &evalName,
|
||||||
|
const std::vector<std::string> &depNames) const {
|
||||||
|
oss << "vec3 " << evalName << "(vec2 uv) {" << endl
|
||||||
|
<< " return " << depNames[0] << "(uv) * " << depNames[1] << "(uv);" << endl
|
||||||
|
<< "}" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTS_DECLARE_CLASS()
|
||||||
|
private:
|
||||||
|
ref<const Texture> m_a, m_b;
|
||||||
|
ref<Shader> m_aShader, m_bShader;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SpectrumAdditionTextureShader : public Shader {
|
||||||
|
public:
|
||||||
|
SpectrumAdditionTextureShader(Renderer *renderer, const Texture *a, const Texture *b)
|
||||||
|
: Shader(renderer, ETextureShader), m_a(a), m_b(b) {
|
||||||
|
m_aShader = renderer->registerShaderForResource(m_a.get());
|
||||||
|
m_bShader = renderer->registerShaderForResource(m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isComplete() const {
|
||||||
|
return m_a.get() != NULL && m_b.get() != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup(Renderer *renderer) {
|
||||||
|
renderer->unregisterShaderForResource(m_a.get());
|
||||||
|
renderer->unregisterShaderForResource(m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void putDependencies(std::vector<Shader *> &deps) {
|
||||||
|
deps.push_back(m_aShader.get());
|
||||||
|
deps.push_back(m_bShader.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateCode(std::ostringstream &oss,
|
||||||
|
const std::string &evalName,
|
||||||
|
const std::vector<std::string> &depNames) const {
|
||||||
|
oss << "vec3 " << evalName << "(vec2 uv) {" << endl
|
||||||
|
<< " return " << depNames[0] << "(uv) + " << depNames[1] << "(uv);" << endl
|
||||||
|
<< "}" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTS_DECLARE_CLASS()
|
||||||
|
private:
|
||||||
|
ref<const Texture> m_a, m_b;
|
||||||
|
ref<Shader> m_aShader, m_bShader;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SpectrumSubtractionTextureShader : public Shader {
|
||||||
|
public:
|
||||||
|
SpectrumSubtractionTextureShader(Renderer *renderer, const Texture *a, const Texture *b)
|
||||||
|
: Shader(renderer, ETextureShader), m_a(a), m_b(b) {
|
||||||
|
m_aShader = renderer->registerShaderForResource(m_a.get());
|
||||||
|
m_bShader = renderer->registerShaderForResource(m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isComplete() const {
|
||||||
|
return m_a.get() != NULL && m_b.get() != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup(Renderer *renderer) {
|
||||||
|
renderer->unregisterShaderForResource(m_a.get());
|
||||||
|
renderer->unregisterShaderForResource(m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void putDependencies(std::vector<Shader *> &deps) {
|
||||||
|
deps.push_back(m_aShader.get());
|
||||||
|
deps.push_back(m_bShader.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateCode(std::ostringstream &oss,
|
||||||
|
const std::string &evalName,
|
||||||
|
const std::vector<std::string> &depNames) const {
|
||||||
|
oss << "vec3 " << evalName << "(vec2 uv) {" << endl
|
||||||
|
<< " return " << depNames[0] << "(uv) - " << depNames[1] << "(uv);" << endl
|
||||||
|
<< "}" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTS_DECLARE_CLASS()
|
||||||
|
private:
|
||||||
|
ref<const Texture> m_a, m_b;
|
||||||
|
ref<Shader> m_aShader, m_bShader;
|
||||||
|
};
|
||||||
|
|
||||||
Shader *ConstantSpectrumTexture::createShader(Renderer *renderer) const {
|
Shader *ConstantSpectrumTexture::createShader(Renderer *renderer) const {
|
||||||
return new ConstantSpectrumTextureShader(renderer, m_value);
|
return new ConstantSpectrumTextureShader(renderer, m_value);
|
||||||
}
|
}
|
||||||
|
@ -107,8 +251,26 @@ Shader *ConstantFloatTexture::createShader(Renderer *renderer) const {
|
||||||
return new ConstantFloatTextureShader(renderer, m_value);
|
return new ConstantFloatTextureShader(renderer, m_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shader *SpectrumProductTexture::createShader(Renderer *renderer) const {
|
||||||
|
return new SpectrumProductTextureShader(renderer, m_a.get(), m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader *SpectrumAdditionTexture::createShader(Renderer *renderer) const {
|
||||||
|
return new SpectrumAdditionTextureShader(renderer, m_a.get(), m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader *SpectrumSubtractionTexture::createShader(Renderer *renderer) const {
|
||||||
|
return new SpectrumSubtractionTextureShader(renderer, m_a.get(), m_b.get());
|
||||||
|
}
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS_S(ConstantSpectrumTexture, false, Texture)
|
MTS_IMPLEMENT_CLASS_S(ConstantSpectrumTexture, false, Texture)
|
||||||
MTS_IMPLEMENT_CLASS(ConstantSpectrumTextureShader, false, Shader)
|
MTS_IMPLEMENT_CLASS(ConstantSpectrumTextureShader, false, Shader)
|
||||||
MTS_IMPLEMENT_CLASS_S(ConstantFloatTexture, false, Texture)
|
MTS_IMPLEMENT_CLASS_S(ConstantFloatTexture, false, Texture)
|
||||||
MTS_IMPLEMENT_CLASS(ConstantFloatTextureShader, false, Shader)
|
MTS_IMPLEMENT_CLASS(ConstantFloatTextureShader, false, Shader)
|
||||||
|
MTS_IMPLEMENT_CLASS_S(SpectrumProductTexture, false, Texture)
|
||||||
|
MTS_IMPLEMENT_CLASS(SpectrumProductTextureShader, false, Shader)
|
||||||
|
MTS_IMPLEMENT_CLASS_S(SpectrumAdditionTexture, false, Texture)
|
||||||
|
MTS_IMPLEMENT_CLASS(SpectrumAdditionTextureShader, false, Shader)
|
||||||
|
MTS_IMPLEMENT_CLASS_S(SpectrumSubtractionTexture, false, Texture)
|
||||||
|
MTS_IMPLEMENT_CLASS(SpectrumSubtractionTextureShader, false, Shader)
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
|
@ -49,12 +49,14 @@ static MaterialEntry materialData[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void lookupMaterial(const Properties &props, Spectrum &sigmaS, Spectrum &sigmaA, Float *eta = NULL, bool requireValues = true) {
|
static void lookupMaterial(const Properties &props, Spectrum &sigmaS, Spectrum &sigmaA, Float *eta = NULL, bool requireValues = true) {
|
||||||
bool manual = (props.hasProperty("sigmaS") || props.hasProperty("sigmaA"));
|
bool hasSigmaAS = props.hasProperty("sigmaS") || props.hasProperty("sigmaA"),
|
||||||
bool preset = props.hasProperty("material");
|
hasSigmaTAlbedo = props.hasProperty("sigmaT") || props.hasProperty("albedo"),
|
||||||
|
manual = hasSigmaAS || hasSigmaTAlbedo,
|
||||||
|
hasPreset = props.hasProperty("material");
|
||||||
|
|
||||||
if (manual && preset)
|
if (manual && hasPreset)
|
||||||
SLog(EError, "Please specify either a preset material, or "
|
SLog(EError, "Please specify either a preset material or "
|
||||||
"sigmaS & sigmaA (you provided both!)");
|
"scattering coefficients (you provided both!)");
|
||||||
|
|
||||||
SAssertEx(!props.hasProperty("sizeMultiplier"),
|
SAssertEx(!props.hasProperty("sizeMultiplier"),
|
||||||
"The sizeMultiplier property was deprecated!");
|
"The sizeMultiplier property was deprecated!");
|
||||||
|
@ -62,12 +64,29 @@ static void lookupMaterial(const Properties &props, Spectrum &sigmaS, Spectrum &
|
||||||
Float densityMultiplier = props.getFloat("densityMultiplier", 1.0f);
|
Float densityMultiplier = props.getFloat("densityMultiplier", 1.0f);
|
||||||
|
|
||||||
if (manual) {
|
if (manual) {
|
||||||
if (requireValues) {
|
if (hasSigmaAS && hasSigmaTAlbedo) {
|
||||||
sigmaS = props.getSpectrum("sigmaS") * densityMultiplier;
|
SLog(EError, "You can either specify sigmaS & sigmaA *or* "
|
||||||
sigmaA = props.getSpectrum("sigmaA") * densityMultiplier;
|
"sigmaT & albedo, but no other combinations!");
|
||||||
|
}
|
||||||
|
if (hasSigmaAS) {
|
||||||
|
if (requireValues) {
|
||||||
|
sigmaS = props.getSpectrum("sigmaS") * densityMultiplier;
|
||||||
|
sigmaA = props.getSpectrum("sigmaA") * densityMultiplier;
|
||||||
|
} else {
|
||||||
|
sigmaS = props.getSpectrum("sigmaS", Spectrum(0.0f)) * densityMultiplier;
|
||||||
|
sigmaA = props.getSpectrum("sigmaA", Spectrum(0.0f)) * densityMultiplier;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sigmaS = props.getSpectrum("sigmaS", Spectrum(0.0f)) * densityMultiplier;
|
Spectrum albedo, sigmaT;
|
||||||
sigmaA = props.getSpectrum("sigmaA", Spectrum(0.0f)) * densityMultiplier;
|
if (requireValues) {
|
||||||
|
albedo = props.getSpectrum("albedo");
|
||||||
|
sigmaT = props.getSpectrum("sigmaT") * densityMultiplier;
|
||||||
|
} else {
|
||||||
|
albedo = props.getSpectrum("albedo", Spectrum(0.0f));
|
||||||
|
sigmaT = props.getSpectrum("sigmaT", Spectrum(0.0f)) * densityMultiplier;
|
||||||
|
}
|
||||||
|
sigmaS = albedo * sigmaT;
|
||||||
|
sigmaA = sigmaT - sigmaS;
|
||||||
}
|
}
|
||||||
if (eta)
|
if (eta)
|
||||||
*eta = props.getFloat("eta", 1.3f);
|
*eta = props.getFloat("eta", 1.3f);
|
||||||
|
|
Loading…
Reference in New Issue