Phong now takes a separate color and reflectance argument

This change will soon be implemented with the remaining materials
metadata
Wenzel Jakob 2010-08-15 15:24:30 +02:00
parent c26b116f11
commit ab2e6b4ca7
13 changed files with 185 additions and 71 deletions

View File

@ -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'])

View File

@ -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<std::string, Element> m_elements;
std::string m_pluginName;
std::string m_pluginName, m_id;
};
MTS_NAMESPACE_END

View File

@ -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;

View File

@ -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;

View File

@ -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<std::string> 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; i<m_bsdfCount; ++i)
for (size_t i=0; i<m_bsdfs.size(); ++i)
m_bsdfs[i]->decRef();
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; i<m_bsdfCount; ++i)
result += m_bsdfs[i]->fDelta(bRec) * m_bsdfWeight[i];
} else {
/* Pick out an individual component */
for (int i=0; i<m_bsdfCount; ++i) {
int component = bRec.component - m_bsdfOffset[i];
if (component < 0 || component >= 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; i<m_bsdfCount; ++i)
result += m_bsdfs[i]->pdfDelta(bRec) * m_pdf[i];
} else {
/* Pick out an individual component */
for (int i=0; i<m_bsdfCount; ++i) {
int component = bRec.component - m_bsdfOffset[i];
if (component < 0 || component >= 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;

View File

@ -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<Texture *>(manager->getInstance(stream));
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
m_diffuseColor = static_cast<Texture *>(manager->getInstance(stream));
m_specularColor = static_cast<Texture *>(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<Texture *>(child);
m_usesRayDifferentials |= m_diffuseReflectance->usesRayDifferentials();
} else if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "specularReflectance") {
m_specularReflectance = static_cast<Texture *>(child);
m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials();
if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "diffuseColor") {
m_diffuseColor = static_cast<Texture *>(child);
m_usesRayDifferentials |= m_diffuseColor->usesRayDifferentials();
} else if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "specularColor") {
m_specularColor = static_cast<Texture *>(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<Texture> m_diffuseReflectance;
ref<Texture> m_specularReflectance;
ref<Texture> m_diffuseColor;
ref<Texture> 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<Shader *> &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<std::string> &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<int> &parameterIDs) 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<int> &parameterIDs, 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<const Texture> m_diffuseReflectance;
ref<const Texture> m_specularReflectance;
ref<Shader> m_diffuseReflectanceShader;
ref<Shader> m_specularReflectanceShader;
ref<const Texture> m_diffuseColor;
ref<const Texture> m_specularColor;
ref<Shader> m_diffuseColorShader;
ref<Shader> 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)

View File

@ -120,6 +120,12 @@ public:
void findRemovals(DOMNode *node, std::set<std::string> &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; i<attributes->getLength(); ++i) {
@ -146,7 +152,7 @@ bool cleanupPass(DOMNode *node, const std::set<std::string> &removals) {
XMLString::release(&nodeName);
return false;
}
if (node->getNodeType() == DOMNode::ELEMENT_NODE && node->hasAttributes()) {
DOMNamedNodeMap *attributes = node->getAttributes();
for (size_t i=0; i<attributes->getLength(); ++i) {
@ -600,11 +606,13 @@ void loadMaterial(ColladaConverter *cvt, std::ostream &os, domMaterial &mat, Str
os << "\t</bsdf>" << endl << endl;
} else {
os << "\t<bsdf id=\"" << mat.getId() << "\" type=\"phong\">" << endl;
loadMaterialParam(cvt, os, "diffuseReflectance", idToTexture, diffuse, false);
loadMaterialParam(cvt, os, "specularReflectance", idToTexture, specular, false);
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, "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</bsdf>" << endl << endl;
}

View File

@ -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<height; ++y) {
for (int x=0; x<width; ++x) {
Spectrum value = *pixels++;
for (int j=0; j<SPECTRUM_SAMPLES; ++j)
max[j] = std::max(max[j], value[j]);
}
}
return max;
}
ref<MIPMap> MIPMap::fromBitmap(Bitmap *bitmap) {
int width = bitmap->getWidth();
int height = bitmap->getHeight();

View File

@ -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<ConfigurableObject> object = NULL;

View File

@ -37,6 +37,10 @@ public:
Spectrum getAverage() const {
return m_reflectance * .5f;
}
Spectrum getMaximum() const {
return m_reflectance;
}
std::string toString() const {
return "Checkerboard[]";

View File

@ -21,6 +21,7 @@ public:
ref<Bitmap> 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> 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<MIPMap> m_mipmap;
std::string m_filename;
Spectrum m_average;
Spectrum m_average, m_maximum;
};
MTS_IMPLEMENT_CLASS_S(EXRTexture, false, Texture)

View File

@ -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[]";
}

View File

@ -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<MemoryStream> m_stream;
std::string m_filename;
Bitmap::EFileFormat m_format;
Spectrum m_average;
Spectrum m_average, m_maximum;
Float m_gamma;
};