diff --git a/SConstruct b/SConstruct index f7e2a737..0d0f2824 100644 --- a/SConstruct +++ b/SConstruct @@ -462,6 +462,7 @@ plugins = [] plugins += env.SharedLibrary('plugins/lambertian', ['src/bsdfs/lambertian.cpp']) plugins += env.SharedLibrary('plugins/dielectric', ['src/bsdfs/dielectric.cpp']) plugins += env.SharedLibrary('plugins/mirror', ['src/bsdfs/mirror.cpp']) +plugins += env.SharedLibrary('plugins/transparent', ['src/bsdfs/transparent.cpp']) plugins += env.SharedLibrary('plugins/ward', ['src/bsdfs/ward.cpp']) plugins += env.SharedLibrary('plugins/phong', ['src/bsdfs/phong.cpp']) plugins += env.SharedLibrary('plugins/microfacet', ['src/bsdfs/microfacet.cpp']) diff --git a/include/mitsuba/core/properties.h b/include/mitsuba/core/properties.h index 9e891983..ac446380 100644 --- a/include/mitsuba/core/properties.h +++ b/include/mitsuba/core/properties.h @@ -23,15 +23,20 @@ public: }; /// Construct an empty property container - Properties() { } + Properties() : m_id("unnamed") { } /// Construct an empty property container and set the plugin name - Properties(const std::string &pluginName) : m_pluginName(pluginName) { } + Properties(const std::string &pluginName) : m_pluginName(pluginName), m_id("unnamed") { } /// Set the associated plugin name inline void setPluginName(const std::string &name) { m_pluginName = name; } /// Get the associated plugin name inline const std::string &getPluginName() const { return m_pluginName; } + + /// Returns the associated ID (or the string "unnamed") + inline const std::string &getID() const { return m_id; } + /// Set the associated ID + inline void setID(const std::string &id) { m_id = id; } /// Set a boolean value void setBoolean(const std::string &name, bool value, bool warnDuplicates = true); @@ -129,7 +134,7 @@ private: }; std::map m_elements; - std::string m_pluginName; + std::string m_pluginName, m_id; }; MTS_NAMESPACE_END diff --git a/include/mitsuba/render/mipmap.h b/include/mitsuba/render/mipmap.h index 3144c55f..877141a2 100644 --- a/include/mitsuba/render/mipmap.h +++ b/include/mitsuba/render/mipmap.h @@ -49,6 +49,9 @@ public: /// Return a pointer to internal image representation at full resolution inline const Spectrum *getImageData() const { return m_pyramid[0]; } + /// Get the component-wise maximum at the zero level + Spectrum getMaximum() const; + /// Return a bitmap representation of the full-resolution image Bitmap *getBitmap() const; diff --git a/include/mitsuba/render/texture.h b/include/mitsuba/render/texture.h index 1c4415c6..6845727e 100644 --- a/include/mitsuba/render/texture.h +++ b/include/mitsuba/render/texture.h @@ -10,6 +10,7 @@ class MTS_EXPORT_RENDER Texture : public ConfigurableObject, public HWResource { public: virtual Spectrum getValue(const Intersection &its) const = 0; virtual Spectrum getAverage() const = 0; + virtual Spectrum getMaximum() const = 0; /* Component-wise maximum */ virtual bool usesRayDifferentials() const = 0; virtual void serialize(Stream *stream, InstanceManager *manager) const; @@ -36,6 +37,10 @@ public: inline Spectrum getAverage() const { return m_value; } + + inline Spectrum getMaximum() const { + return m_value; + } inline std::string toString() const { std::ostringstream oss; diff --git a/src/bsdfs/composite.cpp b/src/bsdfs/composite.cpp index 2db186bb..a3ebef44 100644 --- a/src/bsdfs/composite.cpp +++ b/src/bsdfs/composite.cpp @@ -11,8 +11,7 @@ MTS_NAMESPACE_BEGIN class Composite : public BSDF { public: Composite(const Properties &props) - : BSDF(props), m_bsdfWeight(NULL) { - + : BSDF(props), m_bsdfCount(0), m_bsdfWeight(NULL) { /* Parse the weight parameter */ std::vector weights = tokenize(props.getString("weights", ""), " ,;"); @@ -37,7 +36,7 @@ public: } Composite(Stream *stream, InstanceManager *manager) - : BSDF(stream, manager), m_bsdfWeight(NULL) { + : BSDF(stream, manager), m_bsdfCount(0), m_bsdfWeight(NULL) { m_bsdfCount = stream->readInt(); m_bsdfWeight = new Float[m_bsdfCount]; m_bsdfOffset = new int[m_bsdfCount]; @@ -51,7 +50,7 @@ public: } virtual ~Composite() { - for (int i=0; idecRef(); if (m_type) delete[] m_type; @@ -109,7 +108,7 @@ public: return result; } - inline Spectrum f(const BSDFQueryRecord &bRec) const { + Spectrum f(const BSDFQueryRecord &bRec) const { Spectrum result(0.0f); if (bRec.component == -1) { @@ -131,6 +130,28 @@ public: return result; } + Spectrum fDelta(const BSDFQueryRecord &bRec) const { + Spectrum result(0.0f); + + if (bRec.component == -1) { + for (int i=0; ifDelta(bRec) * m_bsdfWeight[i]; + } else { + /* Pick out an individual component */ + for (int i=0; i= m_bsdfs[i]->getComponentCount()) + continue; + + BSDFQueryRecord bRec2(bRec); + bRec2.component = component; + return m_bsdfs[i]->fDelta(bRec2) * m_bsdfWeight[i]; + } + } + + return result; + } + Float pdf(const BSDFQueryRecord &bRec) const { Float result = 0.0f; @@ -153,6 +174,28 @@ public: return result; } + Float pdfDelta(const BSDFQueryRecord &bRec) const { + Float result = 0.0f; + + if (bRec.component == -1) { + for (int i=0; ipdfDelta(bRec) * m_pdf[i]; + } else { + /* Pick out an individual component */ + for (int i=0; i= m_bsdfs[i]->getComponentCount()) + continue; + + BSDFQueryRecord bRec2(bRec); + bRec2.component = component; + return m_bsdfs[i]->pdfDelta(bRec2); + } + } + + return result; + } + Spectrum sample(BSDFQueryRecord &bRec, Float &pdf) const { if (bRec.component == -1) { Float componentPDF; diff --git a/src/bsdfs/phong.cpp b/src/bsdfs/phong.cpp index a7d27af1..2c2dbacc 100644 --- a/src/bsdfs/phong.cpp +++ b/src/bsdfs/phong.cpp @@ -13,19 +13,27 @@ class Phong : public BSDF { public: Phong(const Properties &props) : BSDF(props) { - m_diffuseReflectance = new ConstantTexture( - props.getSpectrum("diffuseReflectance", Spectrum(.5f))); - m_specularReflectance = new ConstantTexture( - props.getSpectrum("specularReflectance", Spectrum(.2f))); - m_kd = m_diffuseReflectance->getAverage().average(); - m_ks = m_specularReflectance->getAverage().average(); + m_diffuseColor = new ConstantTexture( + props.getSpectrum("diffuseColor", Spectrum(1.0f))); + m_specularColor = new ConstantTexture( + props.getSpectrum("specularColor", Spectrum(1.0f))); + + m_kd = props.getFloat("diffuseReflectance", 0.5f); + m_ks = props.getFloat("specularReflectance", 0.2f); + + Float avgDiffReflectance = m_diffuseColor->getAverage().average() * m_kd; + Float avgSpecularReflectance = m_specularColor->getAverage().average() * m_ks; + m_specularSamplingWeight = props.getFloat("specularSamplingWeight", - m_ks / (m_kd+m_ks)); + avgSpecularReflectance / (avgDiffReflectance + avgSpecularReflectance)); m_diffuseSamplingWeight = 1.0f - m_specularSamplingWeight; m_exponent = props.getFloat("exponent", 10.0f); - if (m_kd + m_ks > 1.0f) - Log(EWarn, "Energy conservation is violated!"); + if (m_kd * m_diffuseColor->getMaximum().max() + m_ks * m_specularColor->getMaximum().max() > 1.0f) { + Log(EWarn, "%s: Energy conservation is violated!", props.getID().c_str()); + Log(EWarn, "%s: Max. diffuse reflectance = %f * %f", m_kd, m_diffuseColor->getMaximum().max()); + Log(EWarn, "%s: Max. specular reflectance = %f * %f", m_ks, m_specularColor->getMaximum().max()); + } m_componentCount = 2; m_type = new unsigned int[m_componentCount]; @@ -37,8 +45,8 @@ public: Phong(Stream *stream, InstanceManager *manager) : BSDF(stream, manager) { - m_diffuseReflectance = static_cast(manager->getInstance(stream)); - m_specularReflectance = static_cast(manager->getInstance(stream)); + m_diffuseColor = static_cast(manager->getInstance(stream)); + m_specularColor = static_cast(manager->getInstance(stream)); m_exponent = stream->readFloat(); m_kd = stream->readFloat(); m_ks = stream->readFloat(); @@ -51,8 +59,8 @@ public: m_type[1] = EGlossyReflection; m_combinedType = m_type[0] | m_type[1]; m_usesRayDifferentials = - m_diffuseReflectance->usesRayDifferentials() || - m_specularReflectance->usesRayDifferentials(); + m_diffuseColor->usesRayDifferentials() || + m_specularColor->usesRayDifferentials(); } virtual ~Phong() { @@ -60,7 +68,7 @@ public: } Spectrum getDiffuseReflectance(const Intersection &its) const { - return m_diffuseReflectance->getValue(its); + return m_diffuseColor->getValue(its) * m_kd; } Spectrum f(const BSDFQueryRecord &bRec) const { @@ -83,12 +91,12 @@ public: specRef = 0.0f; else specRef = (m_exponent + 2) * INV_TWOPI - * std::pow(alpha, m_exponent); - result += m_specularReflectance->getValue(bRec.its) * specRef; + * std::pow(alpha, m_exponent) * m_ks; + result += m_specularColor->getValue(bRec.its) * specRef; } if (hasDiffuse) - result += m_diffuseReflectance->getValue(bRec.its) * INV_PI; + result += m_diffuseColor->getValue(bRec.its) * (INV_PI * m_kd); return result; } @@ -144,11 +152,7 @@ public: if (bRec.wo.z <= 0) return Spectrum(0.0f); - if (m_diffuseSamplingWeight == 0) { - return m_specularReflectance->getValue(bRec.its) * (m_exponent+2)/(m_exponent+1); - } else { - return f(bRec) / pdf(bRec); - } + return f(bRec) / pdf(bRec); } inline Float pdfDiffuse(const BSDFQueryRecord &bRec) const { @@ -192,12 +196,12 @@ public: } void addChild(const std::string &name, ConfigurableObject *child) { - 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 == "specularReflectance") { - m_specularReflectance = static_cast(child); - m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials(); + if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "diffuseColor") { + m_diffuseColor = static_cast(child); + m_usesRayDifferentials |= m_diffuseColor->usesRayDifferentials(); + } else if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "specularColor") { + m_specularColor = static_cast(child); + m_usesRayDifferentials |= m_specularColor->usesRayDifferentials(); } else { BSDF::addChild(name, child); } @@ -206,8 +210,8 @@ public: void serialize(Stream *stream, InstanceManager *manager) const { BSDF::serialize(stream, manager); - manager->serialize(stream, m_diffuseReflectance.get()); - manager->serialize(stream, m_specularReflectance.get()); + manager->serialize(stream, m_diffuseColor.get()); + manager->serialize(stream, m_specularColor.get()); stream->writeFloat(m_exponent); stream->writeFloat(m_kd); stream->writeFloat(m_ks); @@ -220,8 +224,8 @@ public: std::string toString() const { std::ostringstream oss; oss << "Phong[" - << " diffuseReflectance = " << indent(m_diffuseReflectance->toString()) << "," << endl - << " specularReflectance = " << indent(m_specularReflectance->toString()) << "," << endl + << " diffuseColor = " << indent(m_diffuseColor->toString()) << "," << endl + << " specularColor = " << indent(m_specularColor->toString()) << "," << endl << " exponent = " << m_exponent << endl << "]"; return oss.str(); @@ -230,8 +234,8 @@ public: MTS_DECLARE_CLASS() private: - ref m_diffuseReflectance; - ref m_specularReflectance; + ref m_diffuseColor; + ref m_specularColor; Float m_exponent; Float m_kd, m_ks; Float m_specularSamplingWeight; @@ -243,35 +247,39 @@ private: class PhongShader : public Shader { public: PhongShader(Renderer *renderer, - const Texture *diffuseReflectance, - const Texture *specularReflectance, + const Texture *diffuseColor, + const Texture *specularColor, + Float ks, Float kd, Float exponent) : Shader(renderer, EBSDFShader), - m_diffuseReflectance(diffuseReflectance), - m_specularReflectance(specularReflectance), + m_diffuseColor(diffuseColor), + m_specularColor(specularColor), + m_ks(ks), m_kd(kd), m_exponent(exponent) { - m_diffuseReflectanceShader = renderer->registerShaderForResource(m_diffuseReflectance.get()); - m_specularReflectanceShader = renderer->registerShaderForResource(m_specularReflectance.get()); + m_diffuseColorShader = renderer->registerShaderForResource(m_diffuseColor.get()); + m_specularColorShader = renderer->registerShaderForResource(m_specularColor.get()); } bool isComplete() const { - return m_diffuseReflectanceShader.get() != NULL && - m_specularReflectanceShader.get() != NULL; + return m_diffuseColorShader.get() != NULL && + m_specularColorShader.get() != NULL; } void putDependencies(std::vector &deps) { - deps.push_back(m_diffuseReflectanceShader.get()); - deps.push_back(m_specularReflectanceShader.get()); + deps.push_back(m_diffuseColorShader.get()); + deps.push_back(m_specularColorShader.get()); } void cleanup(Renderer *renderer) { - renderer->unregisterShaderForResource(m_diffuseReflectance.get()); - renderer->unregisterShaderForResource(m_specularReflectance.get()); + renderer->unregisterShaderForResource(m_diffuseColor.get()); + renderer->unregisterShaderForResource(m_specularColor.get()); } void generateCode(std::ostringstream &oss, const std::string &evalName, const std::vector &depNames) const { oss << "uniform float " << evalName << "_exponent;" << endl + << "uniform float " << evalName << "_ks;" << endl + << "uniform float " << evalName << "_kd;" << endl << endl << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl << " if (wi.z < 0.0 || wo.z < 0.0)" << endl @@ -281,32 +289,37 @@ public: << " if (alpha < 0.0)" << endl << " return vec3(0.0);" << endl << " float specRef = pow(alpha, " << evalName << "_exponent) * " << endl - << " (" << evalName << "_exponent + 2) * 0.15915;" << endl - << " return " << depNames[0] << "(uv) * 0.31831" << endl + << " (" << evalName << "_exponent + 2) * 0.15915 * " << evalName << "_ks;" << endl + << " return " << depNames[0] << "(uv) * (0.31831 * " << evalName << "_kd)" << endl << " + " << depNames[1] << "(uv) * specRef;" << endl << "}" << endl; } void resolve(const GPUProgram *program, const std::string &evalName, std::vector ¶meterIDs) const { parameterIDs.push_back(program->getParameterID(evalName + "_exponent")); + parameterIDs.push_back(program->getParameterID(evalName + "_ks")); + parameterIDs.push_back(program->getParameterID(evalName + "_kd")); } void bind(GPUProgram *program, const std::vector ¶meterIDs, int &textureUnitOffset) const { program->setParameter(parameterIDs[0], m_exponent); + program->setParameter(parameterIDs[1], m_ks); + program->setParameter(parameterIDs[2], m_kd); } MTS_DECLARE_CLASS() private: - ref m_diffuseReflectance; - ref m_specularReflectance; - ref m_diffuseReflectanceShader; - ref m_specularReflectanceShader; + ref m_diffuseColor; + ref m_specularColor; + ref m_diffuseColorShader; + ref m_specularColorShader; + Float m_ks, m_kd; Float m_exponent; }; Shader *Phong::createShader(Renderer *renderer) const { - return new PhongShader(renderer, m_diffuseReflectance.get(), - m_specularReflectance.get(), m_exponent); + return new PhongShader(renderer, m_diffuseColor.get(), + m_specularColor.get(), m_ks, m_kd, m_exponent); } MTS_IMPLEMENT_CLASS(PhongShader, false, Shader) diff --git a/src/collada/converter.cpp b/src/collada/converter.cpp index 9d15df51..25c8396f 100644 --- a/src/collada/converter.cpp +++ b/src/collada/converter.cpp @@ -120,6 +120,12 @@ public: void findRemovals(DOMNode *node, std::set &removals) { if (node) { + char *nodeName = XMLString::transcode(node->getNodeName()); + if (strcmp(nodeName, "ref") == 0) { + XMLString::release(&nodeName); + return; + } + XMLString::release(&nodeName); if (node->getNodeType() == DOMNode::ELEMENT_NODE && node->hasAttributes()) { DOMNamedNodeMap *attributes = node->getAttributes(); for (size_t i=0; igetLength(); ++i) { @@ -146,7 +152,7 @@ bool cleanupPass(DOMNode *node, const std::set &removals) { XMLString::release(&nodeName); return false; } - + if (node->getNodeType() == DOMNode::ELEMENT_NODE && node->hasAttributes()) { DOMNamedNodeMap *attributes = node->getAttributes(); for (size_t i=0; igetLength(); ++i) { @@ -600,11 +606,13 @@ void loadMaterial(ColladaConverter *cvt, std::ostream &os, domMaterial &mat, Str os << "\t" << endl << endl; } else { os << "\t" << endl; - loadMaterialParam(cvt, os, "diffuseReflectance", idToTexture, diffuse, false); - loadMaterialParam(cvt, os, "specularReflectance", idToTexture, specular, false); + 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, "exponent", idToTexture, shininess, false); - loadMaterialParam(cvt, os, "diffuseReflectance", idToTexture, diffuse, true); - loadMaterialParam(cvt, os, "specularReflectance", idToTexture, specular, true); + loadMaterialParam(cvt, os, "diffuseColor", idToTexture, diffuse, true); + loadMaterialParam(cvt, os, "specularColor", 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 18c64b94..a08d29f6 100644 --- a/src/librender/mipmap.cpp +++ b/src/librender/mipmap.cpp @@ -102,7 +102,22 @@ MIPMap::~MIPMap() { delete[] m_levelWidth; delete[] m_pyramid; } - + +Spectrum MIPMap::getMaximum() const { + Spectrum max(0.0f); + int height = m_levelHeight[0]; + int width = m_levelWidth[0]; + Spectrum *pixels = m_pyramid[0]; + for (int y=0; y MIPMap::fromBitmap(Bitmap *bitmap) { int width = bitmap->getWidth(); int height = bitmap->getHeight(); diff --git a/src/mitsuba/shandler.cpp b/src/mitsuba/shandler.cpp index 44c78b7b..26060dd2 100644 --- a/src/mitsuba/shandler.cpp +++ b/src/mitsuba/shandler.cpp @@ -79,6 +79,8 @@ void SceneHandler::endElement(const XMLCh* const xmlName) { ParseContext &context = m_context.top(); std::string type = context.attributes["type"]; context.properties.setPluginName(type); + if (context.attributes.find("id") != context.attributes.end()) + context.properties.setID(context.attributes["id"]); ref object = NULL; diff --git a/src/textures/checkerboard.cpp b/src/textures/checkerboard.cpp index 586e29ca..37ff63ec 100644 --- a/src/textures/checkerboard.cpp +++ b/src/textures/checkerboard.cpp @@ -37,6 +37,10 @@ public: Spectrum getAverage() const { return m_reflectance * .5f; } + + Spectrum getMaximum() const { + return m_reflectance; + } std::string toString() const { return "Checkerboard[]"; diff --git a/src/textures/exrtexture.cpp b/src/textures/exrtexture.cpp index fd864f11..2747fd7d 100644 --- a/src/textures/exrtexture.cpp +++ b/src/textures/exrtexture.cpp @@ -21,6 +21,7 @@ public: ref bitmap = new Bitmap(Bitmap::EEXR, fs); m_mipmap = MIPMap::fromBitmap(bitmap); m_average = m_mipmap->triangle(m_mipmap->getLevels()-1, 0, 0); + m_maximum = m_mipmap->getMaximum(); } EXRTexture(Stream *stream, InstanceManager *manager) @@ -34,6 +35,7 @@ public: ref bitmap = new Bitmap(Bitmap::EEXR, mStream); m_mipmap = MIPMap::fromBitmap(bitmap); m_average = m_mipmap->triangle(m_mipmap->getLevels()-1, 0, 0); + m_maximum = m_mipmap->getMaximum(); } void serialize(Stream *stream, InstanceManager *manager) const { @@ -48,6 +50,10 @@ public: return m_mipmap->getValue(its); } + Spectrum getMaximum() const { + return m_maximum; + } + Spectrum getAverage() const { return m_average; } @@ -66,7 +72,7 @@ public: protected: ref m_mipmap; std::string m_filename; - Spectrum m_average; + Spectrum m_average, m_maximum; }; MTS_IMPLEMENT_CLASS_S(EXRTexture, false, Texture) diff --git a/src/textures/gridtexture.cpp b/src/textures/gridtexture.cpp index 8ad80222..3ac205f2 100644 --- a/src/textures/gridtexture.cpp +++ b/src/textures/gridtexture.cpp @@ -41,10 +41,14 @@ public: return false; } - Spectrum getAverage() const { + Spectrum getMaximum() const { return m_reflectance; } + Spectrum getAverage() const { + return m_reflectance; // that's not quite right + } + std::string toString() const { return "GridTexture[]"; } diff --git a/src/textures/ldrtexture.cpp b/src/textures/ldrtexture.cpp index 7ff5006e..d261f89f 100644 --- a/src/textures/ldrtexture.cpp +++ b/src/textures/ldrtexture.cpp @@ -175,6 +175,7 @@ public: m_mipmap = MIPMap::fromBitmap(corrected); m_average = m_mipmap->triangle(m_mipmap->getLevels()-1, 0, 0); + m_maximum = m_mipmap->getMaximum(); } void serialize(Stream *stream, InstanceManager *manager) const { @@ -201,6 +202,10 @@ public: return m_average; } + Spectrum getMaximum() const { + return m_maximum; + } + bool usesRayDifferentials() const { return true; } @@ -219,7 +224,7 @@ protected: ref m_stream; std::string m_filename; Bitmap::EFileFormat m_format; - Spectrum m_average; + Spectrum m_average, m_maximum; Float m_gamma; };