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 -->
|
||||
<xsl:template match="bsdf[@type='composite']/@type">
|
||||
<xsl:attribute name="type">mixture</xsl:attribute>
|
||||
<xsl:attribute name="type">mixturebsdf</xsl:attribute>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Update the name of the exrtexture plugin -->
|
||||
|
|
|
@ -126,6 +126,159 @@ protected:
|
|||
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
|
||||
|
||||
#endif /* __BASIC_SHADER_H */
|
||||
|
|
|
@ -13,7 +13,7 @@ plugins += env.SharedLibrary('roughplastic', ['roughplastic.cpp'])
|
|||
# Materials that act as modifiers
|
||||
plugins += env.SharedLibrary('twosided', ['twosided.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('bump', ['bump.cpp'])
|
||||
|
||||
|
|
|
@ -38,9 +38,10 @@ MTS_NAMESPACE_BEGIN
|
|||
*
|
||||
* This BSDF models a non-reflective material, where any entering light loses
|
||||
* its directionality and is diffusely scattered from the other side. This
|
||||
* model can be combined\footnote{For instance using the \pluginref{mixture}
|
||||
* plugin.} with a surface reflection model to describe translucent substances
|
||||
* that have internal multiple scattering processes (e.g. plant leaves).
|
||||
* model can be combined\footnote{For instance using the
|
||||
* \pluginref{mixturebsdf} plugin.} with a surface reflection model to
|
||||
* describe translucent substances that have internal multiple scattering
|
||||
* processes (e.g. plant leaves).
|
||||
*/
|
||||
class DiffuseTransmitter : public BSDF {
|
||||
public:
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
: BSDF(props) {
|
||||
|
||||
Spectrum sigmaS, sigmaA;
|
||||
Float eta;
|
||||
Float eta = 1.33f;
|
||||
lookupMaterial(props, sigmaS, sigmaA, &eta, false);
|
||||
|
||||
/* Specifies the internal index of refraction at the interface */
|
||||
|
@ -85,10 +85,23 @@ public:
|
|||
}
|
||||
|
||||
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.push_back(EDiffuseReflection | EFrontSide
|
||||
| (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())
|
||||
Log(EError, "Please specify nonzero sigmaS/sigmaA-values!");
|
||||
|
@ -176,6 +189,10 @@ public:
|
|||
m_sigmaS = static_cast<Texture *>(child);
|
||||
else if (name == "sigmaA")
|
||||
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
|
||||
BSDF::addChild(name, child);
|
||||
} else {
|
||||
|
@ -212,6 +229,9 @@ public:
|
|||
private:
|
||||
Float m_intIOR, m_extIOR, m_g, m_A;
|
||||
ref<Texture> m_sigmaS, m_sigmaA;
|
||||
/* Temporary fields */
|
||||
ref<Texture> m_sigmaT;
|
||||
ref<Texture> m_albedo;
|
||||
};
|
||||
|
||||
// ================ Hardware shader implementation ================
|
||||
|
|
|
@ -36,6 +36,12 @@ MTS_NAMESPACE_BEGIN
|
|||
* of the internal layer. \default{based on \code{material}}}
|
||||
* \parameter{sigmaA}{\Spectrum\Or\Texture}{Specifies the absorption coefficient
|
||||
* 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.
|
||||
* (should be specified in inverse units of \code{sigmaA} and \code{sigmaS})\default{1}}
|
||||
* \parameter{\Unnamed}{\Phase}{A nested phase function instance that represents
|
||||
|
@ -45,12 +51,11 @@ MTS_NAMESPACE_BEGIN
|
|||
* \renderings{
|
||||
* \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}
|
||||
* \vspace{-3mm}
|
||||
* \caption{
|
||||
* \label{fig:hk-example}
|
||||
* 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
|
||||
|
@ -62,7 +67,7 @@ MTS_NAMESPACE_BEGIN
|
|||
* This BSDF requires a phase function to model scattering interactions within the
|
||||
* random medium. When no phase function is explicitly specified, it uses an
|
||||
* 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}
|
||||
* <bsdf type="hk">
|
||||
* <spectrum name="sigmaS" value="2"/>
|
||||
|
@ -123,7 +128,6 @@ public:
|
|||
|
||||
/* Slab thickness in inverse units of sigmaS and sigmaA */
|
||||
m_thickness = props.getFloat("thickness", 1);
|
||||
|
||||
}
|
||||
|
||||
HanrahanKrueger(Stream *stream, InstanceManager *manager)
|
||||
|
@ -140,13 +144,29 @@ public:
|
|||
m_phase = static_cast<PhaseFunction *> (PluginManager::getInstance()->
|
||||
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())
|
||||
Log(EError, "Please specify nonzero sigmaS/sigmaA-values!");
|
||||
|
||||
int extraFlags = m_sigmaS->isConstant() && m_sigmaA->isConstant() ? 0 : ESpatiallyVarying;
|
||||
m_components.clear();
|
||||
m_components.push_back(EGlossyReflection | EFrontSide | EBackSide | ECanUseSampler);
|
||||
m_components.push_back(EGlossyTransmission | EFrontSide | EBackSide | ECanUseSampler);
|
||||
m_components.push_back(EDeltaTransmission | EFrontSide | EBackSide | ECanUseSampler);
|
||||
m_components.push_back(EGlossyReflection | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
|
||||
m_components.push_back(EGlossyTransmission | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
|
||||
m_components.push_back(EDeltaTransmission | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
|
||||
|
||||
m_usesRayDifferentials = m_sigmaS->usesRayDifferentials()
|
||||
|| m_sigmaA->usesRayDifferentials();
|
||||
|
||||
BSDF::configure();
|
||||
}
|
||||
|
@ -369,6 +389,10 @@ public:
|
|||
m_sigmaS = static_cast<Texture *>(child);
|
||||
else if (name == "sigmaA")
|
||||
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
|
||||
BSDF::addChild(name, child);
|
||||
} else {
|
||||
|
@ -395,6 +419,9 @@ private:
|
|||
ref<Texture> m_sigmaS;
|
||||
ref<Texture> m_sigmaA;
|
||||
Float m_thickness;
|
||||
/* Temporary fields */
|
||||
ref<Texture> m_sigmaT;
|
||||
ref<Texture> m_albedo;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/*! \plugin{mixture}{Mixture material}
|
||||
/*! \plugin{mixturebsdf}{Mixture material}
|
||||
*
|
||||
* \parameters{
|
||||
* \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
|
||||
* chromium, 20% of a greenish rough diffuse material (and 10% absorption)},
|
||||
* label=lst:mixture-example]
|
||||
* <bsdf type="mixture">
|
||||
* <bsdf type="mixturebsdf">
|
||||
* <string name="weights" value="0.7, 0.2"/>
|
||||
*
|
||||
* <bsdf type="conductor">
|
|
@ -34,6 +34,12 @@ MTS_NAMESPACE_BEGIN
|
|||
* of the layer. \default{based on \code{material}}}
|
||||
* \parameter{sigmaA}{\Spectrum\Or\Texture}{Specifies the absorption coefficient
|
||||
* 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
|
||||
* numerically or using a known material name. \default{based on \code{material}}}
|
||||
* \parameter{extIOR}{\Float\Or\String}{Exterior index of refraction specified
|
||||
|
@ -97,7 +103,7 @@ public:
|
|||
m_dipole = static_cast<BSDF *> (PluginManager::getInstance()->
|
||||
createObject(MTS_CLASS(BSDF), dipoleProps));
|
||||
|
||||
Properties mixtureProps("mixture");
|
||||
Properties mixtureProps("mixturebsdf");
|
||||
mixtureProps.setString("weights", "1.0, 1.0");
|
||||
mixtureProps.setBoolean("ensureEnergyConservation", false);
|
||||
m_mixture = static_cast<BSDF *> (PluginManager::getInstance()->
|
||||
|
@ -106,6 +112,8 @@ public:
|
|||
props.markQueried("material");
|
||||
props.markQueried("sigmaS");
|
||||
props.markQueried("sigmaA");
|
||||
props.markQueried("coating");
|
||||
props.markQueried("sigmaT");
|
||||
props.markQueried("intIOR");
|
||||
props.markQueried("extIOR");
|
||||
}
|
||||
|
|
|
@ -41,6 +41,42 @@ void ConstantFloatTexture::serialize(Stream *stream, InstanceManager *manager) c
|
|||
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 {
|
||||
public:
|
||||
ConstantSpectrumTextureShader(Renderer *renderer, const Spectrum &value)
|
||||
|
@ -99,6 +135,114 @@ private:
|
|||
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 {
|
||||
return new ConstantSpectrumTextureShader(renderer, m_value);
|
||||
}
|
||||
|
@ -107,8 +251,26 @@ Shader *ConstantFloatTexture::createShader(Renderer *renderer) const {
|
|||
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(ConstantSpectrumTextureShader, false, Shader)
|
||||
MTS_IMPLEMENT_CLASS_S(ConstantFloatTexture, false, Texture)
|
||||
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
|
||||
|
|
|
@ -49,12 +49,14 @@ static MaterialEntry materialData[] = {
|
|||
};
|
||||
|
||||
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 preset = props.hasProperty("material");
|
||||
bool hasSigmaAS = props.hasProperty("sigmaS") || props.hasProperty("sigmaA"),
|
||||
hasSigmaTAlbedo = props.hasProperty("sigmaT") || props.hasProperty("albedo"),
|
||||
manual = hasSigmaAS || hasSigmaTAlbedo,
|
||||
hasPreset = props.hasProperty("material");
|
||||
|
||||
if (manual && preset)
|
||||
SLog(EError, "Please specify either a preset material, or "
|
||||
"sigmaS & sigmaA (you provided both!)");
|
||||
if (manual && hasPreset)
|
||||
SLog(EError, "Please specify either a preset material or "
|
||||
"scattering coefficients (you provided both!)");
|
||||
|
||||
SAssertEx(!props.hasProperty("sizeMultiplier"),
|
||||
"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);
|
||||
|
||||
if (manual) {
|
||||
if (requireValues) {
|
||||
sigmaS = props.getSpectrum("sigmaS") * densityMultiplier;
|
||||
sigmaA = props.getSpectrum("sigmaA") * densityMultiplier;
|
||||
if (hasSigmaAS && hasSigmaTAlbedo) {
|
||||
SLog(EError, "You can either specify sigmaS & sigmaA *or* "
|
||||
"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 {
|
||||
sigmaS = props.getSpectrum("sigmaS", Spectrum(0.0f)) * densityMultiplier;
|
||||
sigmaA = props.getSpectrum("sigmaA", Spectrum(0.0f)) * densityMultiplier;
|
||||
Spectrum albedo, sigmaT;
|
||||
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)
|
||||
*eta = props.getFloat("eta", 1.3f);
|
||||
|
|
Loading…
Reference in New Issue