added a normalization feature

metadata
Wenzel Jakob 2012-05-04 23:54:45 -04:00
parent 2f553660c4
commit 854cd049e7
1 changed files with 70 additions and 39 deletions

View File

@ -28,6 +28,7 @@
#include <mitsuba/core/fresolver.h>
#include <mitsuba/core/fstream.h>
#include <mitsuba/core/bitmap.h>
#include <mitsuba/render/scene.h>
#include "irawan.h"
MTS_NAMESPACE_BEGIN
@ -76,7 +77,7 @@ MTS_NAMESPACE_BEGIN
class IrawanClothBRDF : public BSDF {
public:
IrawanClothBRDF(const Properties &props)
: BSDF(props) {
: BSDF(props), m_specularNormalization(0) {
FileResolver *fResolver = Thread::getThread()->getFileResolver();
fs::path path = fResolver->resolve(props.getString("filename"));
@ -90,8 +91,8 @@ public:
WeavePatternGrammar<iterator_type> g(props);
SkipGrammar<iterator_type> sg;
bool result = phrase_parse(begin, end, g, sg, m_pattern);
if (!result)
bool success = phrase_parse(begin, end, g, sg, m_pattern);
if (!success)
Log(EError, "Unable to parse the weave pattern file \"%s\"!",
path.file_string().c_str());
@ -106,9 +107,10 @@ public:
m_repeatU = props.getFloat("repeatU");
m_repeatV = props.getFloat("repeatV");
/* Diffuse and specular multipliers */
m_kdMultiplier = props.getFloat("kdMultiplier");
m_ksMultiplier = props.getFloat("ksMultiplier");
if (props.hasProperty("ksMultiplier") || props.hasProperty("kdMultiplier"))
Log(EError, "The 'ksMultiplier' and 'kdMultiplier' parameters were "
"replaced by a normalization scheme. Please remove them and"
"potentially adapt the 'kd' and 'ks'-values used in your model.");
}
IrawanClothBRDF(Stream *stream, InstanceManager *manager)
@ -116,17 +118,54 @@ public:
m_pattern = WeavePattern(stream);
m_repeatU = stream->readFloat();
m_repeatV = stream->readFloat();
m_kdMultiplier = stream->readFloat();
m_ksMultiplier = stream->readFloat();
m_specularNormalization = stream->readFloat();
configure();
}
void serialize(Stream *stream, InstanceManager *manager) const {
BSDF::serialize(stream, manager);
m_pattern.serialize(stream);
stream->writeFloat(m_repeatU);
stream->writeFloat(m_repeatV);
stream->writeFloat(m_specularNormalization);
}
void configure() {
m_components.clear();
m_components.push_back(EGlossyReflection | EFrontSide
| EAnisotropic | ESpatiallyVarying);
m_components.push_back(EDiffuseReflection | EFrontSide
| ESpatiallyVarying);
/* Estimate the average reflectance under diffuse
illumination and use it to normalize the specular
component */
ref<Random> random = new Random();
size_t nSamples = 10000;
if (m_specularNormalization == 0) {
Intersection its;
BSDFQueryRecord bRec(its, NULL, ERadiance);
Spectrum result(0.0f);
m_initialization = true;
for (size_t i=0; i<nSamples; ++i) {
bRec.wi = squareToHemispherePSA(Point2(random->nextFloat(), random->nextFloat()));
bRec.wo = squareToHemispherePSA(Point2(random->nextFloat(), random->nextFloat()));
its.uv = Point2(random->nextFloat(), random->nextFloat());
result += eval(bRec, ESolidAngle) / Frame::cosTheta(bRec.wo);
}
m_initialization = false;
if (result.max() == 0)
m_specularNormalization = 0;
else
m_specularNormalization = nSamples / (result.max() * M_PI);
Log(EDebug, "Specular normalization factor = %f",
m_specularNormalization);
}
BSDF::configure();
}
@ -140,15 +179,15 @@ public:
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;
return yarn.kd;
}
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
bool hasSpecular = (bRec.typeMask & EGlossyReflection) &&
(bRec.component == -1 || bRec.component == 0) && m_ksMultiplier > 0;
(bRec.component == -1 || bRec.component == 0);
bool hasDiffuse = (bRec.typeMask & EDiffuseReflection) &&
(bRec.component == -1 || bRec.component == 1) && m_kdMultiplier > 0;
(bRec.component == -1 || bRec.component == 1);
if (Frame::cosTheta(bRec.wi) <= 0 ||
Frame::cosTheta(bRec.wo) <= 0 ||
@ -261,24 +300,28 @@ public:
intensityVariation = std::min(-std::fastlog(xi), (Float) 10.0f);
}
result = yarn.ks * (intensityVariation * m_ksMultiplier * integrand);
if (!m_initialization)
result = yarn.ks * (intensityVariation * integrand * m_specularNormalization);
else
result = Spectrum(intensityVariation * integrand);
if (type == Yarn::EWarp)
result *= (m_pattern.warpArea + m_pattern.weftArea) / m_pattern.warpArea;
else
result *= (m_pattern.warpArea + m_pattern.weftArea) / m_pattern.weftArea;
}
if (hasDiffuse)
result += yarn.kd * m_kdMultiplier * INV_PI;
if (hasDiffuse && !m_initialization)
result += yarn.kd * INV_PI;
return result * Frame::cosTheta(bRec.wo);
}
Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const {
bool hasSpecular = (bRec.typeMask & EGlossyReflection) &&
(bRec.component == -1 || bRec.component == 0) && m_ksMultiplier > 0;
(bRec.component == -1 || bRec.component == 0);
bool hasDiffuse = (bRec.typeMask & EDiffuseReflection) &&
(bRec.component == -1 || bRec.component == 1) && m_kdMultiplier > 0;
(bRec.component == -1 || bRec.component == 1);
if (Frame::cosTheta(bRec.wi) <= 0 ||
Frame::cosTheta(bRec.wo) <= 0 ||
@ -291,9 +334,9 @@ public:
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
bool hasSpecular = (bRec.typeMask & EGlossyReflection) &&
(bRec.component == -1 || bRec.component == 0) && m_ksMultiplier > 0;
(bRec.component == -1 || bRec.component == 0);
bool hasDiffuse = (bRec.typeMask & EDiffuseReflection) &&
(bRec.component == -1 || bRec.component == 1) && m_kdMultiplier > 0;
(bRec.component == -1 || bRec.component == 1);
if (Frame::cosTheta(bRec.wi) <= 0 ||
(!hasDiffuse && !hasSpecular))
@ -308,9 +351,9 @@ public:
Spectrum sample(BSDFQueryRecord &bRec, Float &pdf, const Point2 &sample) const {
bool hasSpecular = (bRec.typeMask & EGlossyReflection) &&
(bRec.component == -1 || bRec.component == 0) && m_ksMultiplier > 0;
(bRec.component == -1 || bRec.component == 0);
bool hasDiffuse = (bRec.typeMask & EDiffuseReflection) &&
(bRec.component == -1 || bRec.component == 1) && m_kdMultiplier > 0;
(bRec.component == -1 || bRec.component == 1);
if (Frame::cosTheta(bRec.wi) <= 0 ||
(!hasDiffuse && !hasSpecular))
@ -324,16 +367,6 @@ public:
return eval(bRec, ESolidAngle) / pdf;
}
void serialize(Stream *stream, InstanceManager *manager) const {
BSDF::serialize(stream, manager);
m_pattern.serialize(stream);
stream->writeFloat(m_repeatU);
stream->writeFloat(m_repeatV);
stream->writeFloat(m_kdMultiplier);
stream->writeFloat(m_ksMultiplier);
}
/** parameters:
* u to be compared to u(v) in texturing
* v for filament, we compute u(v)
@ -583,9 +616,7 @@ public:
oss << "IrawanClothBRDF[" << endl
<< " weavePattern = " << indent(m_pattern.toString()) << "," << endl
<< " repeatU = " << m_repeatU << "," << endl
<< " repeatV = " << m_repeatV << "," << endl
<< " kdMultiplier = " << m_kdMultiplier << "," << endl
<< " ksMultiplier = " << m_ksMultiplier << endl
<< " repeatV = " << m_repeatV << endl
<< "]";
return oss.str();
}
@ -596,8 +627,8 @@ public:
private:
WeavePattern m_pattern;
Float m_repeatU, m_repeatV;
Float m_kdMultiplier;
Float m_ksMultiplier;
Float m_specularNormalization;
bool m_initialization;
};
// ================ Hardware shader implementation ================
@ -638,7 +669,7 @@ Shader *IrawanClothBRDF::createShader(Renderer *renderer) const {
Spectrum albedo(0.0f);
for (size_t i=0; i<m_pattern.yarns.size(); ++i)
albedo += m_pattern.yarns[i].kd;
albedo *= m_kdMultiplier / (Float) m_pattern.yarns.size();
albedo /= (Float) m_pattern.yarns.size();
return new IrawanShader(renderer, albedo);
}