irawan.cpp removed the need for external diffuse/specular texture files

metadata
Wenzel Jakob 2011-04-28 15:30:39 +02:00
parent 9cefc6ea97
commit 839d7773c8
2 changed files with 43 additions and 65 deletions

View File

@ -19,7 +19,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <mitsuba/render/bsdf.h> #include <mitsuba/render/bsdf.h>
#include <mitsuba/render/shape.h> #include <mitsuba/render/shape.h>
#include <mitsuba/render/texture.h> #include <mitsuba/render/texture.h>
@ -37,9 +36,9 @@ MTS_NAMESPACE_BEGIN
* This plugin implements the Irawan & Marschner woven cloth BRDF model * This plugin implements the Irawan & Marschner woven cloth BRDF model
* It is a port of a previous Java implementation by Piti Irawan. * It is a port of a previous Java implementation by Piti Irawan.
* *
* To use the model, you must provide a special weave pattern file, as well * To use the model, you must provide a special weave pattern file --
* as diffuse and specular texture maps. For an example of what these look * for an example of what these look like, please see the included
* like, please see the included example scenes. * example scenes.
* *
* For reference, the model is described in detail in the PhD * For reference, the model is described in detail in the PhD
* thesis of Piti Irawan ("The Appearance of Woven Cloth", * thesis of Piti Irawan ("The Appearance of Woven Cloth",
@ -74,26 +73,25 @@ public:
SAssert(m_pattern.pattern.size() == SAssert(m_pattern.pattern.size() ==
m_pattern.tileWidth * m_pattern.tileHeight); m_pattern.tileWidth * m_pattern.tileHeight);
for (size_t i=0; i<m_pattern.pattern.size(); ++i) for (size_t i=0; i<m_pattern.pattern.size(); ++i)
SAssert(m_pattern.pattern[i] <= m_pattern.yarns.size()); SAssert(m_pattern.pattern[i] > 0 &&
m_pattern.pattern[i] <= m_pattern.yarns.size());
/* U and V tile count */ /* U and V tile count */
m_repeatU = props.getFloat("repeatU"); m_repeatU = props.getFloat("repeatU");
m_repeatV = props.getFloat("repeatV"); m_repeatV = props.getFloat("repeatV");
/* Diffuse and specular multiplier */ /* Diffuse and specular multipliers */
m_kd = props.getFloat("kd"); m_kdMultiplier = props.getFloat("kdMultiplier");
m_ks = props.getFloat("ks"); m_ksMultiplier = props.getFloat("ksMultiplier");
} }
IrawanClothBRDF(Stream *stream, InstanceManager *manager) IrawanClothBRDF(Stream *stream, InstanceManager *manager)
: BSDF(stream, manager) { : BSDF(stream, manager) {
m_diffuseReflectance = static_cast<Texture2D *>(manager->getInstance(stream));
m_specularReflectance = static_cast<Texture2D *>(manager->getInstance(stream));
m_pattern = WeavePattern(stream); m_pattern = WeavePattern(stream);
m_repeatU = stream->readFloat(); m_repeatU = stream->readFloat();
m_repeatV = stream->readFloat(); m_repeatV = stream->readFloat();
m_kd = stream->readFloat(); m_kdMultiplier = stream->readFloat();
m_ks = stream->readFloat(); m_ksMultiplier = stream->readFloat();
m_componentCount = 1; m_componentCount = 1;
m_type = new unsigned int[m_componentCount]; m_type = new unsigned int[m_componentCount];
m_combinedType = m_type[0] = EGlossyReflection | EAnisotropicMaterial; m_combinedType = m_type[0] = EGlossyReflection | EAnisotropicMaterial;
@ -120,10 +118,6 @@ public:
int yarnID = m_pattern.pattern[lookup.x + lookup.y * m_pattern.tileWidth] - 1; int yarnID = m_pattern.pattern[lookup.x + lookup.y * m_pattern.tileWidth] - 1;
const Yarn &yarn = m_pattern.yarns.at(yarnID); const Yarn &yarn = m_pattern.yarns.at(yarnID);
Spectrum diffuse = m_diffuseReflectance->getValue(uv);
Spectrum specular = m_specularReflectance->getValue(uv);
// store center of the yarn segment // store center of the yarn segment
Point2 center Point2 center
(((int) xy.x / m_pattern.tileWidth) * m_pattern.tileWidth (((int) xy.x / m_pattern.tileWidth) * m_pattern.tileWidth
@ -195,7 +189,7 @@ public:
// Compute specular contribution. // Compute specular contribution.
Spectrum result(0.0f); Spectrum result(0.0f);
if (m_ks > 0.0f) { if (m_ksMultiplier > 0.0f) {
Float integrand; Float integrand;
if (psi != 0.0f) if (psi != 0.0f)
integrand = evalStapleIntegrand(u, v, om_i, om_r, m_pattern.alpha, integrand = evalStapleIntegrand(u, v, om_i, om_r, m_pattern.alpha,
@ -218,18 +212,27 @@ public:
intensityVariation = std::min(-std::log(xi), (Float) 10.0f); intensityVariation = std::min(-std::log(xi), (Float) 10.0f);
} }
result = specular * (intensityVariation * m_ks * integrand); result = yarn.ks * (intensityVariation * m_ksMultiplier * integrand);
if (type == Yarn::EWarp) if (type == Yarn::EWarp)
result *= (m_pattern.warpArea + m_pattern.weftArea) / m_pattern.warpArea; result *= (m_pattern.warpArea + m_pattern.weftArea) / m_pattern.warpArea;
else else
result *= (m_pattern.warpArea + m_pattern.weftArea) / m_pattern.weftArea; result *= (m_pattern.warpArea + m_pattern.weftArea) / m_pattern.weftArea;
} }
return result + diffuse * m_kd; return result + yarn.kd * m_kdMultiplier;
} }
Spectrum getDiffuseReflectance(const Intersection &its) const { Spectrum getDiffuseReflectance(const Intersection &its) const {
return m_diffuseReflectance->getValue(its); Point2 uv = Point2(its.uv.x * m_repeatU,
(1 - its.uv.y) * m_repeatV);
Point2 xy(uv.x * m_pattern.tileWidth, uv.y * m_pattern.tileHeight);
Point2i lookup(
modulo((int) xy.x, m_pattern.tileWidth),
modulo((int) xy.y, m_pattern.tileHeight));
int yarnID = m_pattern.pattern[lookup.x + lookup.y * m_pattern.tileWidth] - 1;
const Yarn &yarn = m_pattern.yarns.at(yarnID);
return yarn.kd * m_kdMultiplier;
} }
Float pdf(const BSDFQueryRecord &bRec) const { Float pdf(const BSDFQueryRecord &bRec) const {
@ -259,35 +262,14 @@ public:
return f(bRec); return f(bRec);
} }
void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(MTS_CLASS(Texture2D))
&& name == "diffuseReflectance") {
m_diffuseReflectance = static_cast<Texture2D *>(child);
} else if (child->getClass()->derivesFrom(MTS_CLASS(Texture2D))
&& name == "specularReflectance") {
m_specularReflectance = static_cast<Texture2D *>(child);
} else {
BSDF::addChild(name, child);
}
}
void configure() {
if (m_diffuseReflectance == NULL ||
m_specularReflectance == NULL)
Log(EError, "Missing texture component (diffuse "
"+ specular map are required)");
}
void serialize(Stream *stream, InstanceManager *manager) const { void serialize(Stream *stream, InstanceManager *manager) const {
BSDF::serialize(stream, manager); BSDF::serialize(stream, manager);
manager->serialize(stream, m_diffuseReflectance.get());
manager->serialize(stream, m_specularReflectance.get());
m_pattern.serialize(stream); m_pattern.serialize(stream);
stream->writeFloat(m_repeatU); stream->writeFloat(m_repeatU);
stream->writeFloat(m_repeatV); stream->writeFloat(m_repeatV);
stream->writeFloat(m_kd); stream->writeFloat(m_kdMultiplier);
stream->writeFloat(m_ks); stream->writeFloat(m_ksMultiplier);
} }
/** parameters: /** parameters:
@ -537,20 +519,21 @@ public:
std::string toString() const { std::string toString() const {
std::ostringstream oss; std::ostringstream oss;
oss << "IrawanClothBRDF[" << endl oss << "IrawanClothBRDF[" << endl
<< " diffuseReflectance = " << indent(m_diffuseReflectance.toString()) << "," << endl << " weavePattern = " << indent(m_pattern.toString()) << "," << endl
<< " specularReflectance = " << indent(m_specularReflectance.toString()) << endl << " repeatU = " << m_repeatU << "," << endl
<< " weavePattern = " << indent(m_pattern.toString()) << endl << " repeatV = " << m_repeatV << "," << endl
<< " kdMultiplier = " << m_kdMultiplier << "," << endl
<< " ksMultiplier = " << m_ksMultiplier << endl
<< "]"; << "]";
return oss.str(); return oss.str();
} }
MTS_DECLARE_CLASS() MTS_DECLARE_CLASS()
private: private:
ref<Texture2D> m_diffuseReflectance;
ref<Texture2D> m_specularReflectance;
WeavePattern m_pattern; WeavePattern m_pattern;
Float m_repeatU, m_repeatV; Float m_repeatU, m_repeatV;
Float m_kd, m_ks; Float m_kdMultiplier;
Float m_ksMultiplier;
}; };
MTS_IMPLEMENT_CLASS_S(IrawanClothBRDF, false, BSDF) MTS_IMPLEMENT_CLASS_S(IrawanClothBRDF, false, BSDF)

View File

@ -27,7 +27,6 @@
#include <boost/spirit/include/phoenix_bind.hpp> #include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_operator.hpp> #include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp> #include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/spirit/home/phoenix/bind/bind_member_variable.hpp> #include <boost/spirit/home/phoenix/bind/bind_member_variable.hpp>
#include <boost/spirit/home/phoenix/bind/bind_member_function.hpp> #include <boost/spirit/home/phoenix/bind/bind_member_function.hpp>
#include <boost/spirit/home/phoenix/statement/if.hpp> #include <boost/spirit/home/phoenix/statement/if.hpp>
@ -276,14 +275,6 @@ template <typename Iterator> struct SkipGrammar : qi::grammar<Iterator> {
qi::rule<Iterator> start; qi::rule<Iterator> start;
}; };
inline Spectrum lookupSpectrum(const std::map<std::string, Spectrum> &map, const std::vector<char> &_name) {
std::string name = std::string(&_name[0]);
std::map<std::string, Spectrum>::const_iterator it = map.find(name);
if (it == map.end())
SLog(EError, "Unable to find key \"%s\"", name.c_str());
return it->second;
}
template <typename Iterator> struct YarnGrammar : qi::grammar<Iterator, Yarn(), SkipGrammar<Iterator> > { template <typename Iterator> struct YarnGrammar : qi::grammar<Iterator, Yarn(), SkipGrammar<Iterator> > {
YarnGrammar(const Properties &props) YarnGrammar(const Properties &props)
: YarnGrammar::base_type(start), props(props) { : YarnGrammar::base_type(start), props(props) {
@ -297,14 +288,15 @@ template <typename Iterator> struct YarnGrammar : qi::grammar<Iterator, Yarn(),
type = (qi::string("warp") | qi::string("weft")) type = (qi::string("warp") | qi::string("weft"))
[ ph::if_else(_1 == "warp", _val = Yarn::EWarp, _val = Yarn::EWeft ) ]; [ ph::if_else(_1 == "warp", _val = Yarn::EWarp, _val = Yarn::EWeft ) ];
qi::rule<Iterator, std::string()> id = qi::lexeme[ lit('$') >> +char_("a-zA-Z0-9") ]; identifier = qi::lexeme[ lit('$') >> (qi::alpha | char_('_'))
>> *(qi::alnum | char_('_')) ];
spec = ((lit("{") >> float_ >> lit(",") >> float_ >> lit(",") >> float_ >> lit("}")) spec = ((lit("{") >> float_ >> lit(",") >> float_ >> lit(",") >> float_ >> lit("}"))
[ ph::bind(&Spectrum::fromLinearRGB, _val, _1, _2, _3) ]) [ ph::bind(&Spectrum::fromLinearRGB, _val, _1, _2, _3) ])
| (id [ _val = bind(&Properties::getSpectrum, ph::ref(props), _1)]); | (identifier [ _val = bind(&Properties::getSpectrum, ph::ref(props), _1)]);
flt = (float_ [ _val = _1 ]) flt = (float_ [ _val = _1 ])
| (id [ _val = bind(&Properties::getFloat, ph::ref(props), _1)]); | (identifier [ _val = bind(&Properties::getFloat, ph::ref(props), _1)]);
start = lit("yarn") start = lit("yarn")
>> lit("{") >> lit("{")
@ -327,6 +319,7 @@ template <typename Iterator> struct YarnGrammar : qi::grammar<Iterator, Yarn(),
qi::rule<Iterator, Yarn(), SkipGrammar<Iterator> > start; qi::rule<Iterator, Yarn(), SkipGrammar<Iterator> > start;
qi::rule<Iterator, Spectrum(), SkipGrammar<Iterator> > spec; qi::rule<Iterator, Spectrum(), SkipGrammar<Iterator> > spec;
qi::rule<Iterator, float(), SkipGrammar<Iterator> > flt; qi::rule<Iterator, float(), SkipGrammar<Iterator> > flt;
qi::rule<Iterator, std::string()> identifier;
const Properties &props; const Properties &props;
}; };
@ -346,12 +339,13 @@ template <typename Iterator> struct WeavePatternGrammar : qi::grammar<Iterator,
>> uint_ [ push_back(_val, _1) ] % ',' >> uint_ [ push_back(_val, _1) ] % ','
>> lit("}"); >> lit("}");
name = ("\"" >> *(char_ - "\"") >> "\""); name = qi::lexeme [ lit("\"") >> *(char_ - "\"") >> lit("\"") ];
qi::rule<Iterator, std::string()> id = qi::lexeme[ lit('$') >> +char_("a-zA-Z0-9") ]; identifier = qi::lexeme[ lit('$') >> (qi::alpha | char_('_'))
>> *(qi::alnum | char_('_')) ];
flt = (float_ [ _val = _1 ]) flt = (float_ [ _val = _1 ])
| (id [ _val = bind(&Properties::getFloat, ph::ref(props), _1)]); | (identifier [ _val = bind(&Properties::getFloat, ph::ref(props), _1)]);
start = lit("weave") >> lit("{") >> ( start = lit("weave") >> lit("{") >> (
lit("name") >> lit("=") >> name [ bind(&WeavePattern::name, _val) = _1 ] lit("name") >> lit("=") >> name [ bind(&WeavePattern::name, _val) = _1 ]
@ -372,13 +366,14 @@ template <typename Iterator> struct WeavePatternGrammar : qi::grammar<Iterator,
| pattern [ bind(&WeavePattern::pattern, _val) = _1 ] | pattern [ bind(&WeavePattern::pattern, _val) = _1 ]
| yarn [ push_back(bind(&WeavePattern::yarns, _val), _1) ] | yarn [ push_back(bind(&WeavePattern::yarns, _val), _1) ]
) % ',' ) % ','
>> lit("}"); >> lit("}") >> qi::eoi;
} }
qi::rule<Iterator, WeavePattern(), SkipGrammar<Iterator> > start; qi::rule<Iterator, WeavePattern(), SkipGrammar<Iterator> > start;
qi::rule<Iterator, std::vector<uint32_t>(), SkipGrammar<Iterator> > pattern; qi::rule<Iterator, std::vector<uint32_t>(), SkipGrammar<Iterator> > pattern;
qi::rule<Iterator, std::string(), SkipGrammar<Iterator> > name; qi::rule<Iterator, std::string(), SkipGrammar<Iterator> > name;
qi::rule<Iterator, float(), SkipGrammar<Iterator> > flt; qi::rule<Iterator, float(), SkipGrammar<Iterator> > flt;
qi::rule<Iterator, std::string()> identifier;
YarnGrammar<Iterator> yarn; YarnGrammar<Iterator> yarn;
const Properties &props; const Properties &props;
}; };