irawan.cpp removed the need for external diffuse/specular texture files
parent
9cefc6ea97
commit
839d7773c8
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue