diff --git a/src/bsdfs/microfacet.cpp b/src/bsdfs/microfacet.cpp index 0109783f..04d4583e 100644 --- a/src/bsdfs/microfacet.cpp +++ b/src/bsdfs/microfacet.cpp @@ -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 ================ diff --git a/src/bsdfs/phong.cpp b/src/bsdfs/phong.cpp index 4b2118ae..e9b01163 100644 --- a/src/bsdfs/phong.cpp +++ b/src/bsdfs/phong.cpp @@ -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(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(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 ================ diff --git a/src/bsdfs/ward.cpp b/src/bsdfs/ward.cpp index 6ac2b788..6b642247 100644 --- a/src/bsdfs/ward.cpp +++ b/src/bsdfs/ward.cpp @@ -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(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(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); diff --git a/src/converter/collada.cpp b/src/converter/collada.cpp index e131a3d2..009e8774 100644 --- a/src/converter/collada.cpp +++ b/src/converter/collada.cpp @@ -658,11 +658,11 @@ void loadMaterial(GeometryConverter *cvt, std::ostream &os, domMaterial &mat, St os << "\t" << endl; os << "\t\t" << endl; os << "\t\t" << 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" << endl << endl; } diff --git a/src/librender/mipmap.cpp b/src/librender/mipmap.cpp index 11a1a7e5..f8fed6b2 100644 --- a/src/librender/mipmap.cpp +++ b/src/librender/mipmap.cpp @@ -129,8 +129,9 @@ Spectrum MIPMap::getMaximum() const { for (int y=0; y 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; ygetHeight(); ++y) { for (int x=0; xgetWidth(); ++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; ygetHeight(); ++y) { for (int x=0; xgetWidth(); ++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; ygetHeight(); ++y) { for (int x=0; xgetWidth(); ++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; ygetHeight(); ++y) { for (int x=0; xgetWidth(); ++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; }