/*
This file is part of Mitsuba, a physically based rendering system.
Copyright (c) 2007-2012 by Wenzel Jakob and others.
Mitsuba is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License Version 3
as published by the Free Software Foundation.
Mitsuba is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include
MTS_NAMESPACE_BEGIN
BSDF::BSDF(const Properties &props)
: ConfigurableObject(props) {
/* By default, verify whether energy conservation holds
for the user-specified parameter values. This step
is completely up to the particular BSDF implementations */
m_ensureEnergyConservation = props.getBoolean(
"ensureEnergyConservation", true);
m_usesRayDifferentials = false;
}
BSDF::BSDF(Stream *stream, InstanceManager *manager)
: ConfigurableObject(stream, manager) {
m_ensureEnergyConservation = stream->readBool();
m_usesRayDifferentials = false;
}
BSDF::~BSDF() { }
void BSDF::serialize(Stream *stream, InstanceManager *manager) const {
ConfigurableObject::serialize(stream, manager);
stream->writeBool(m_ensureEnergyConservation);
}
void BSDF::setParent(ConfigurableObject *parent) {
/* BSDF's don't need to reference their parent -> do nothing */
}
void BSDF::addChild(const std::string &name, ConfigurableObject *obj) {
ConfigurableObject::addChild(name, obj);
}
void BSDF::configure() {
m_combinedType = 0;
for (size_t i=0; igetMaximum().max();
if (actualMax > max) {
std::ostringstream oss;
Float scale = 0.99f * (max / actualMax);
oss << "The BSDF" << endl << toString() << endl
<< "violates energy conservation! The parameter \"" << paramName << "\" "
<< "has a component-wise maximum of "<< actualMax << " (which is > " << max << "!) "
<< "and will therefore be scaled by " << scale << " to prevent "
<< "issues. Specify the parameter ensureEnergyConservation=false "
<< "to the BSDF to prevent this from happening.";
Log(EWarn, "%s", oss.str().c_str());
Properties props("scale");
props.setFloat("scale", scale);
Texture *scaleTexture = static_cast (PluginManager::getInstance()->
createObject(MTS_CLASS(Texture), props));
scaleTexture->addChild(texture);
scaleTexture->configure();
return scaleTexture;
}
return texture;
}
std::pair BSDF::ensureEnergyConservation(
Texture *tex1, Texture *tex2, const std::string ¶mName1,
const std::string ¶mName2, Float max) const {
if (!m_ensureEnergyConservation)
return std::make_pair(tex1, tex2);
Float actualMax = (tex1->getMaximum() + tex2->getMaximum()).max();
if (actualMax > max) {
std::ostringstream oss;
Float scale = 0.99f * (max / actualMax);
oss << "The BSDF" << endl << toString() << endl
<< "violates energy conservation! The parameters \"" << paramName1 << "\" "
<< "and \"" << paramName2 << "\" sum to a component-wise maximum of "
<< actualMax << " (which is > " << max << "!) and will therefore be "
<< "scaled by " << scale << " to prevent issues. Specify the parameter "
<< "ensureEnergyConservation=false to the BSDF to prevent this from "
<< "happening.";
Log(EWarn, "%s", oss.str().c_str());
Properties props("scale");
props.setFloat("scale", scale);
Texture *scaleTexture1 = static_cast (PluginManager::getInstance()->
createObject(MTS_CLASS(Texture), props));
Texture *scaleTexture2 = static_cast (PluginManager::getInstance()->
createObject(MTS_CLASS(Texture), props));
scaleTexture1->addChild(tex1);
scaleTexture1->configure();
scaleTexture2->addChild(tex2);
scaleTexture2->configure();
return std::make_pair(scaleTexture1, scaleTexture2);
}
return std::make_pair(tex1, tex2);
}
static std::string typeMaskToString(unsigned int typeMask) {
std::ostringstream oss;
oss << "{ ";
#define isset(mask) (typeMask & mask) == mask
{
if (isset(BSDF::EAll)) { oss << "all "; typeMask &= ~BSDF::EAll; }
if (isset(BSDF::ESmooth)) { oss << "smooth "; typeMask &= ~BSDF::ESmooth; }
if (isset(BSDF::EDiffuse)) { oss << "diffuse "; typeMask &= ~BSDF::EDiffuse; }
if (isset(BSDF::EGlossy)) { oss << "glossy "; typeMask &= ~BSDF::EGlossy; }
if (isset(BSDF::EDelta)) { oss << "delta"; typeMask &= ~BSDF::EDelta; }
if (isset(BSDF::EDelta1D)) { oss << "delta1D "; typeMask &= ~BSDF::EDelta1D; }
if (isset(BSDF::EDiffuseReflection)) { oss << "diffuseReflection "; typeMask &= ~BSDF::EDiffuseReflection; }
if (isset(BSDF::EDiffuseTransmission)) { oss << "diffuseTransmission "; typeMask &= ~BSDF::EDiffuseTransmission; }
if (isset(BSDF::EGlossyReflection)) { oss << "glossyReflection "; typeMask &= ~BSDF::EGlossyReflection; }
if (isset(BSDF::EGlossyTransmission)) { oss << "glossyTransmission "; typeMask &= ~BSDF::EGlossyTransmission; }
if (isset(BSDF::EDeltaReflection)) { oss << "deltaReflection "; typeMask &= ~BSDF::EDeltaReflection; }
if (isset(BSDF::EDeltaTransmission)) { oss << "deltaTransmission "; typeMask &= ~BSDF::EDeltaTransmission; }
if (isset(BSDF::EDelta1DReflection)) { oss << "delta1DReflection "; typeMask &= ~BSDF::EDelta1DReflection; }
if (isset(BSDF::EDelta1DTransmission)) { oss << "delta1DTransmission "; typeMask &= ~BSDF::EDelta1DTransmission; }
if (isset(BSDF::ENull)) { oss << "null "; typeMask &= ~BSDF::ENull; }
if (isset(BSDF::EAnisotropic)) { oss << "anisotropic "; typeMask &= ~BSDF::EAnisotropic; }
if (isset(BSDF::EFrontSide)) { oss << "frontSide "; typeMask &= ~BSDF::EFrontSide; }
if (isset(BSDF::EBackSide)) { oss << "backSide "; typeMask &= ~BSDF::EBackSide; }
if (isset(BSDF::EUsesSampler)) { oss << "usesSampler "; typeMask &= ~BSDF::EUsesSampler; }
if (isset(BSDF::ESpatiallyVarying)) { oss << "spatiallyVarying"; typeMask &= ~BSDF::ESpatiallyVarying; }
if (isset(BSDF::ENonSymmetric)) { oss << "nonSymmetric"; typeMask &= ~BSDF::ENonSymmetric; }
}
#undef isset
SAssert(typeMask == 0);
oss << "}";
return oss.str();
}
std::string BSDFSamplingRecord::toString() const {
std::ostringstream oss;
oss << "BSDFSamplingRecord[" << endl
<< " wi = " << wi.toString() << "," << endl
<< " wo = " << wo.toString() << "," << endl
<< " mode = " << mode << "," << endl
<< " typeMask = " << typeMaskToString(typeMask) << "," << endl
<< " sampledType = " << typeMaskToString(sampledType) << "," << endl
<< " component = " << component << "," << endl
<< " sampledComponent = " << sampledComponent << endl
<< "]";
return oss.str();
}
MTS_IMPLEMENT_CLASS(BSDF, true, ConfigurableObject)
MTS_NAMESPACE_END