fixed a glaring bug related to Phong/Ward/Microfacet and textures, Faster ldrtexture loading times

metadata
Wenzel Jakob 2010-09-07 21:50:30 +02:00
parent e05818a1a6
commit ae39518ca0
6 changed files with 132 additions and 152 deletions

View File

@ -44,25 +44,8 @@ public:
m_kd = props.getFloat("diffuseAmount", 1.0f);
m_ks = props.getFloat("specularAmount", 1.0f);
bool verifyEnergyConservation = props.getBoolean("verifyEnergyConservation", true);
if (verifyEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
+ m_ks * m_specularReflectance->getMaximum().max() > 1.0f)) {
Log(EWarn, "%s: Energy conservation is potentially violated!", props.getID().c_str());
Log(EWarn, "Max. diffuse reflectance = %f * %f = %f", m_kd, m_diffuseReflectance->getMaximum().max(), m_kd*m_diffuseReflectance->getMaximum().max());
Log(EWarn, "Max. specular reflectance = %f * %f = %f", m_ks, m_specularReflectance->getMaximum().max(), m_ks*m_specularReflectance->getMaximum().max());
Float normalization = 1/(m_kd * m_diffuseReflectance->getMaximum().max() + m_ks * m_specularReflectance->getMaximum().max());
Log(EWarn, "Reducing the albedo to %.1f%% of the original value to be on the safe side. "
"Specify verifyEnergyConservation=false to prevent this.", normalization * 100);
m_kd *= normalization; m_ks *= normalization;
}
Float avgDiffReflectance = m_diffuseReflectance->getAverage().average() * m_kd;
Float avgSpecularReflectance = m_specularReflectance->getAverage().average() * m_ks;
m_specularSamplingWeight = props.getFloat("specularSamplingWeight",
avgSpecularReflectance / (avgDiffReflectance + avgSpecularReflectance));
m_diffuseSamplingWeight = 1.0f - m_specularSamplingWeight;
m_verifyEnergyConservation = props.getBoolean("verifyEnergyConservation", true);
m_specularSamplingWeight = props.getFloat("specularSamplingWeight", -1);
m_alphaB = props.getFloat("alphaB", .1f);
m_intIOR = props.getFloat("intIOR", 1.5f);
@ -104,6 +87,26 @@ public:
delete[] m_type;
}
void configure() {
if (m_verifyEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
+ m_ks * m_specularReflectance->getMaximum().max() > 1.0f)) {
Log(EWarn, "Material \"%s\": Energy conservation is potentially violated!", getName().c_str());
Log(EWarn, "Max. diffuse reflectance = %f * %f = %f", m_kd, m_diffuseReflectance->getMaximum().max(), m_kd*m_diffuseReflectance->getMaximum().max());
Log(EWarn, "Max. specular reflectance = %f * %f = %f", m_ks, m_specularReflectance->getMaximum().max(), m_ks*m_specularReflectance->getMaximum().max());
Float normalization = 1/(m_kd * m_diffuseReflectance->getMaximum().max() + m_ks * m_specularReflectance->getMaximum().max());
Log(EWarn, "Reducing the albedo to %.1f%% of the original value to be on the safe side. "
"Specify verifyEnergyConservation=false to prevent this.", normalization * 100);
m_kd *= normalization; m_ks *= normalization;
}
if (m_specularSamplingWeight == -1) {
Float avgDiffReflectance = m_diffuseReflectance->getAverage().average() * m_kd;
Float avgSpecularReflectance = m_specularReflectance->getAverage().average() * m_ks;
m_specularSamplingWeight = avgSpecularReflectance / (avgDiffReflectance + avgSpecularReflectance);
}
m_diffuseSamplingWeight = 1.0f - m_specularSamplingWeight;
}
Spectrum getDiffuseReflectance(const Intersection &its) const {
return m_diffuseReflectance->getValue(its) * m_kd;
}
@ -306,6 +309,9 @@ public:
oss << "Microfacet[" << endl
<< " diffuseReflectance = " << indent(m_diffuseReflectance->toString()) << "," << endl
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << "," << endl
<< " diffuseAmount = " << m_kd << "," << endl
<< " specularAmount = " << m_ks << "," << endl
<< " specularSamplingWeight = " << m_specularSamplingWeight << "," << endl
<< " intIOR = " << m_intIOR << "," << endl
<< " extIOR = " << m_extIOR << "," << endl
<< " alphaB = " << m_alphaB << endl
@ -321,6 +327,7 @@ private:
Float m_specularSamplingWeight;
Float m_diffuseSamplingWeight;
Float m_ks, m_kd;
bool m_verifyEnergyConservation;
};
// ================ Hardware shader implementation ================

View File

@ -41,25 +41,8 @@ public:
m_exponent = props.getFloat("exponent", 10.0f);
bool verifyEnergyConservation = props.getBoolean("verifyEnergyConservation", true);
if (verifyEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
+ m_ks * m_specularReflectance->getMaximum().max() > 1.0f)) {
Log(EWarn, "%s: Energy conservation is potentially violated!", props.getID().c_str());
Log(EWarn, "Max. diffuse reflectance = %f * %f = %f", m_kd, m_diffuseReflectance->getMaximum().max(), m_kd*m_diffuseReflectance->getMaximum().max());
Log(EWarn, "Max. specular reflectance = %f * %f = %f", m_ks, m_specularReflectance->getMaximum().max(), m_ks*m_specularReflectance->getMaximum().max());
Float normalization = 1/(m_kd * m_diffuseReflectance->getMaximum().max() + m_ks * m_specularReflectance->getMaximum().max());
Log(EWarn, "Reducing the albedo to %.1f%% of the original value to be on the safe side. "
"Specify verifyEnergyConservation=false to prevent this.", normalization * 100);
m_kd *= normalization; m_ks *= normalization;
}
Float avgDiffReflectance = m_diffuseReflectance->getAverage().average() * m_kd;
Float avgSpecularReflectance = m_specularReflectance->getAverage().average() * m_ks;
m_specularSamplingWeight = props.getFloat("specularSamplingWeight",
avgSpecularReflectance / (avgDiffReflectance + avgSpecularReflectance));
m_diffuseSamplingWeight = 1.0f - m_specularSamplingWeight;
m_verifyEnergyConservation = props.getBoolean("verifyEnergyConservation", true);
m_specularSamplingWeight = props.getFloat("specularSamplingWeight", -1);
m_componentCount = 2;
m_type = new unsigned int[m_componentCount];
@ -88,11 +71,31 @@ public:
m_diffuseReflectance->usesRayDifferentials() ||
m_specularReflectance->usesRayDifferentials();
}
virtual ~Phong() {
delete[] m_type;
}
void configure() {
if (m_verifyEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
+ m_ks * m_specularReflectance->getMaximum().max() > 1.0f)) {
Log(EWarn, "Material \"%s\": Energy conservation is potentially violated!", getName().c_str());
Log(EWarn, "Max. diffuse reflectance = %f * %f = %f", m_kd, m_diffuseReflectance->getMaximum().max(), m_kd*m_diffuseReflectance->getMaximum().max());
Log(EWarn, "Max. specular reflectance = %f * %f = %f", m_ks, m_specularReflectance->getMaximum().max(), m_ks*m_specularReflectance->getMaximum().max());
Float normalization = 1/(m_kd * m_diffuseReflectance->getMaximum().max() + m_ks * m_specularReflectance->getMaximum().max());
Log(EWarn, "Reducing the albedo to %.1f%% of the original value to be on the safe side. "
"Specify verifyEnergyConservation=false to prevent this.", normalization * 100);
m_kd *= normalization; m_ks *= normalization;
}
if (m_specularSamplingWeight == -1) {
Float avgDiffReflectance = m_diffuseReflectance->getAverage().average() * m_kd;
Float avgSpecularReflectance = m_specularReflectance->getAverage().average() * m_ks;
m_specularSamplingWeight = avgSpecularReflectance / (avgDiffReflectance + avgSpecularReflectance);
}
m_diffuseSamplingWeight = 1.0f - m_specularSamplingWeight;
}
Spectrum getDiffuseReflectance(const Intersection &its) const {
return m_diffuseReflectance->getValue(its) * m_kd;
}
@ -222,10 +225,10 @@ public:
}
void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "diffuseColor") {
if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "diffuseReflectance") {
m_diffuseReflectance = static_cast<Texture *>(child);
m_usesRayDifferentials |= m_diffuseReflectance->usesRayDifferentials();
} else if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "specularColor") {
} else if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "specularReflectance") {
m_specularReflectance = static_cast<Texture *>(child);
m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials();
} else {
@ -250,8 +253,11 @@ public:
std::string toString() const {
std::ostringstream oss;
oss << "Phong[" << endl
<< " diffuseColor = " << indent(m_diffuseReflectance->toString()) << "," << endl
<< " specularColor = " << indent(m_specularReflectance->toString()) << "," << endl
<< " diffuseReflectance = " << indent(m_diffuseReflectance->toString()) << "," << endl
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << "," << endl
<< " diffuseAmount = " << m_kd << "," << endl
<< " specularAmount = " << m_ks << "," << endl
<< " specularSamplingWeight = " << m_specularSamplingWeight << "," << endl
<< " exponent = " << m_exponent << endl
<< "]";
return oss.str();
@ -266,6 +272,7 @@ private:
Float m_kd, m_ks;
Float m_specularSamplingWeight;
Float m_diffuseSamplingWeight;
bool m_verifyEnergyConservation;
};
// ================ Hardware shader implementation ================

View File

@ -41,25 +41,8 @@ public:
m_kd = props.getFloat("diffuseAmount", 1.0f);
m_ks = props.getFloat("specularAmount", 1.0f);
bool verifyEnergyConservation = props.getBoolean("verifyEnergyConservation", true);
if (verifyEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
+ m_ks * m_specularReflectance->getMaximum().max() > 1.0f)) {
Log(EWarn, "%s: Energy conservation is potentially violated!", props.getID().c_str());
Log(EWarn, "Max. diffuse reflectance = %f * %f = %f", m_kd, m_diffuseReflectance->getMaximum().max(), m_kd*m_diffuseReflectance->getMaximum().max());
Log(EWarn, "Max. specular reflectance = %f * %f = %f", m_ks, m_specularReflectance->getMaximum().max(), m_ks*m_specularReflectance->getMaximum().max());
Float normalization = 1/(m_kd * m_diffuseReflectance->getMaximum().max() + m_ks * m_specularReflectance->getMaximum().max());
Log(EWarn, "Reducing the albedo to %.1f%% of the original value to be on the safe side. "
"Specify verifyEnergyConservation=false to prevent this.", normalization * 100);
m_kd *= normalization; m_ks *= normalization;
}
Float avgDiffReflectance = m_diffuseReflectance->getAverage().average() * m_kd;
Float avgSpecularReflectance = m_specularReflectance->getAverage().average() * m_ks;
m_specularSamplingWeight = props.getFloat("specularSamplingWeight",
avgSpecularReflectance / (avgDiffReflectance + avgSpecularReflectance));
m_diffuseSamplingWeight = 1.0f - m_specularSamplingWeight;
m_verifyEnergyConservation = props.getBoolean("verifyEnergyConservation", true);
m_specularSamplingWeight = props.getFloat("specularSamplingWeight", -1);
m_alphaX = props.getFloat("alphaX", .1f);
m_alphaY = props.getFloat("alphaY", .1f);
@ -96,6 +79,26 @@ public:
delete[] m_type;
}
void configure() {
if (m_verifyEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
+ m_ks * m_specularReflectance->getMaximum().max() > 1.0f)) {
Log(EWarn, "Material \"%s\": Energy conservation is potentially violated!", getName().c_str());
Log(EWarn, "Max. diffuse reflectance = %f * %f = %f", m_kd, m_diffuseReflectance->getMaximum().max(), m_kd*m_diffuseReflectance->getMaximum().max());
Log(EWarn, "Max. specular reflectance = %f * %f = %f", m_ks, m_specularReflectance->getMaximum().max(), m_ks*m_specularReflectance->getMaximum().max());
Float normalization = 1/(m_kd * m_diffuseReflectance->getMaximum().max() + m_ks * m_specularReflectance->getMaximum().max());
Log(EWarn, "Reducing the albedo to %.1f%% of the original value to be on the safe side. "
"Specify verifyEnergyConservation=false to prevent this.", normalization * 100);
m_kd *= normalization; m_ks *= normalization;
}
if (m_specularSamplingWeight == -1) {
Float avgDiffReflectance = m_diffuseReflectance->getAverage().average() * m_kd;
Float avgSpecularReflectance = m_specularReflectance->getAverage().average() * m_ks;
m_specularSamplingWeight = avgSpecularReflectance / (avgDiffReflectance + avgSpecularReflectance);
}
m_diffuseSamplingWeight = 1.0f - m_specularSamplingWeight;
}
Spectrum getDiffuseReflectance(const Intersection &its) const {
return m_diffuseReflectance->getValue(its) * m_kd;
}
@ -223,10 +226,10 @@ public:
}
void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "diffuseColor") {
if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "diffuseReflectance") {
m_diffuseReflectance = static_cast<Texture *>(child);
m_usesRayDifferentials |= m_diffuseReflectance->usesRayDifferentials();
} else if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "specularColor") {
} else if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "specularReflectance") {
m_specularReflectance = static_cast<Texture *>(child);
m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials();
} else {
@ -234,7 +237,6 @@ public:
}
}
void serialize(Stream *stream, InstanceManager *manager) const {
BSDF::serialize(stream, manager);
@ -251,8 +253,11 @@ public:
std::string toString() const {
std::ostringstream oss;
oss << "Ward[" << endl
<< " diffuseColor = " << indent(m_diffuseReflectance->toString()) << "," << endl
<< " specularColor = " << indent(m_specularReflectance->toString()) << "," << endl
<< " diffuseReflectance = " << indent(m_diffuseReflectance->toString()) << "," << endl
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << "," << endl
<< " diffuseAmount = " << m_kd << "," << endl
<< " specularAmount = " << m_ks << "," << endl
<< " specularSamplingWeight = " << m_specularSamplingWeight << "," << endl
<< " alphaX = " << m_alphaX << "," << endl
<< " alphaY = " << m_alphaY << endl
<< "]";
@ -267,6 +272,7 @@ private:
Float m_kd, m_ks;
Float m_specularSamplingWeight;
Float m_diffuseSamplingWeight;
bool m_verifyEnergyConservation;
};
MTS_IMPLEMENT_CLASS_S(Ward, false, BSDF);

View File

@ -658,11 +658,11 @@ void loadMaterial(GeometryConverter *cvt, std::ostream &os, domMaterial &mat, St
os << "\t<bsdf id=\"" << identifier << "\" type=\"blinn\">" << endl;
os << "\t\t<float name=\"specularReflectance\" value=\"1\"/>" << endl;
os << "\t\t<float name=\"diffuseReflectance\" value=\"1\"/>" << endl;
loadMaterialParam(cvt, os, "diffuseColor", idToTexture, diffuse, false);
loadMaterialParam(cvt, os, "specularColor", idToTexture, specular, false);
loadMaterialParam(cvt, os, "diffuseReflectance", idToTexture, diffuse, false);
loadMaterialParam(cvt, os, "specularReflectance", idToTexture, specular, false);
loadMaterialParam(cvt, os, "exponent", idToTexture, shininess, false);
loadMaterialParam(cvt, os, "diffuseColor", idToTexture, diffuse, true);
loadMaterialParam(cvt, os, "specularColor", idToTexture, specular, true);
loadMaterialParam(cvt, os, "diffuseReflectance", idToTexture, diffuse, true);
loadMaterialParam(cvt, os, "specularReflectance", idToTexture, specular, true);
loadMaterialParam(cvt, os, "exponent", idToTexture, shininess, true);
os << "\t</bsdf>" << endl << endl;
}

View File

@ -129,8 +129,9 @@ Spectrum MIPMap::getMaximum() const {
for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x) {
Spectrum value = *pixels++;
for (int j=0; j<SPECTRUM_SAMPLES; ++j)
for (int j=0; j<SPECTRUM_SAMPLES; ++j) {
max[j] = std::max(max[j], value[j]);
}
}
}
return max;

View File

@ -90,108 +90,67 @@ public:
void initializeFrom(Bitmap *bitmap) {
ref<Bitmap> corrected = new Bitmap(bitmap->getWidth(), bitmap->getHeight(), 128);
Float tbl[256];
if (m_gamma == -1) {
for (int i=0; i<255; ++i)
tbl[i] = fromSRGBComponent(i/255.0f);
} else {
for (int i=0; i<255; ++i)
tbl[i] = std::pow(i/255.0f, m_gamma);
}
unsigned char *data = bitmap->getData();
float *flData = corrected->getFloatData();
Spectrum spec;
if (bitmap->getBitsPerPixel() == 32) {
for (int y=0; y<bitmap->getHeight(); ++y) {
for (int x=0; x<bitmap->getWidth(); ++x) {
if (m_gamma == -1) {
Float r = (*data++)/255.0f,
g = (*data++)/255.0f,
b = (*data++)/255.0f,
a = (*data++)/255.0f;
spec.fromSRGB(r, g, b);
spec.toLinearRGB(r, g, b);
*flData++ = r;
*flData++ = g;
*flData++ = b;
*flData++ = a;
} else {
Float r = std::pow((Float) (*data++)/255.0f, m_gamma),
g = std::pow((Float) (*data++)/255.0f, m_gamma),
b = std::pow((Float) (*data++)/255.0f, m_gamma),
a = (*data++)/255.0f;
*flData++ = r;
*flData++ = g;
*flData++ = b;
*flData++ = a;
}
float
r = tbl[*data++],
g = tbl[*data++],
b = tbl[*data++],
a = *data++ / 255.0f;
*flData++ = r;
*flData++ = g;
*flData++ = b;
*flData++ = a;
}
}
} else if (bitmap->getBitsPerPixel() == 24) {
for (int y=0; y<bitmap->getHeight(); ++y) {
for (int x=0; x<bitmap->getWidth(); ++x) {
if (m_gamma == -1) {
Float r = (*data++)/255.0f,
g = (*data++)/255.0f,
b = (*data++)/255.0f;
spec.fromSRGB(r, g, b);
spec.toLinearRGB(r, g, b);
*flData++ = r;
*flData++ = g;
*flData++ = b;
*flData++ = 1.0f;
} else {
Float r = std::pow((Float) (*data++)/255.0f, m_gamma),
g = std::pow((Float) (*data++)/255.0f, m_gamma),
b = std::pow((Float) (*data++)/255.0f, m_gamma);
*flData++ = r;
*flData++ = g;
*flData++ = b;
*flData++ = 1.0f;
}
float
r = tbl[*data++],
g = tbl[*data++],
b = tbl[*data++];
*flData++ = r;
*flData++ = g;
*flData++ = b;
*flData++ = 1.0f;
}
}
} else if (bitmap->getBitsPerPixel() == 16) {
for (int y=0; y<bitmap->getHeight(); ++y) {
for (int x=0; x<bitmap->getWidth(); ++x) {
if (m_gamma == -1) {
Float col = (*data++)/255.0f,
a = (*data++)/255.0f;
col = fromSRGBComponent(col);
*flData++ = col;
*flData++ = col;
*flData++ = col;
*flData++ = a;
} else {
Float col = std::pow((Float) (*data++)/255.0f, m_gamma),
a = (*data++)/255.0f;
*flData++ = col;
*flData++ = col;
*flData++ = col;
*flData++ = a;
}
float col = tbl[*data++],
a = *data++ / 255.0f;
*flData++ = col;
*flData++ = col;
*flData++ = col;
*flData++ = a;
}
}
} else if (bitmap->getBitsPerPixel() == 8) {
for (int y=0; y<bitmap->getHeight(); ++y) {
for (int x=0; x<bitmap->getWidth(); ++x) {
if (m_gamma == -1) {
Float col = (*data++)/255.0f;
col = fromSRGBComponent(col);
*flData++ = col;
*flData++ = col;
*flData++ = col;
*flData++ = 1.0f;
} else {
Float col = std::pow((Float) (*data++)/255.0f, m_gamma);
*flData++ = col;
*flData++ = col;
*flData++ = col;
*flData++ = 1.0f;
}
float col = tbl[*data++];
*flData++ = col;
*flData++ = col;
*flData++ = col;
*flData++ = 1.0f;
}
}
} else {
Log(EError, "%i bpp JPG/PNGs are currently not supported!", bitmap->getBitsPerPixel());
Log(EError, "%i bpp images are currently not supported!", bitmap->getBitsPerPixel());
}
m_mipmap = MIPMap::fromBitmap(corrected);
@ -218,7 +177,7 @@ public:
Spectrum getValue(const Intersection &its) const {
return m_mipmap->getValue(its);
}
Spectrum getAverage() const {
return m_average;
}