BMP loading support, material parameter naming more uniform

metadata
Wenzel Jakob 2010-09-03 15:26:18 +02:00
parent d4181b01fd
commit d4ae5660cf
4 changed files with 132 additions and 70 deletions

View File

@ -40,9 +40,30 @@ public:
props.getSpectrum("diffuseReflectance", Spectrum(0.0f)));
m_specularReflectance = new ConstantTexture(
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
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",
std::max((Float) 0.3, 1-2*m_diffuseReflectance->getAverage().average()));
avgSpecularReflectance / (avgDiffReflectance + avgSpecularReflectance));
m_diffuseSamplingWeight = 1.0f - m_specularSamplingWeight;
m_alphaB = props.getFloat("alphaB", .1f);
m_intIOR = props.getFloat("intIOR", 1.5f);
m_extIOR = props.getFloat("extIOR", 1.0f);
@ -62,6 +83,8 @@ public:
m_diffuseReflectance = static_cast<Texture *>(manager->getInstance(stream));
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
m_alphaB = stream->readFloat();
m_kd = stream->readFloat();
m_ks = stream->readFloat();
m_intIOR = stream->readFloat();
m_extIOR = stream->readFloat();
m_specularSamplingWeight = stream->readFloat();
@ -82,7 +105,7 @@ public:
}
Spectrum getDiffuseReflectance(const Intersection &its) const {
return m_diffuseReflectance->getValue(its);
return m_diffuseReflectance->getValue(its) * m_kd;
}
/**
@ -162,9 +185,9 @@ public:
Float F = fresnel(dot(bRec.wi, Hr), m_extIOR, m_intIOR);
if (hasGlossy)
result += fSpec(bRec, Hr) * F;
result += fSpec(bRec, Hr) * (F * m_ks);
if (hasDiffuse)
result += m_diffuseReflectance->getValue(bRec.its) * INV_PI * (1-F);
result += m_diffuseReflectance->getValue(bRec.its) * (INV_PI * (1-F) * m_kd);
return result;
}
@ -268,6 +291,8 @@ public:
manager->serialize(stream, m_diffuseReflectance.get());
manager->serialize(stream, m_specularReflectance.get());
stream->writeFloat(m_alphaB);
stream->writeFloat(m_kd);
stream->writeFloat(m_ks);
stream->writeFloat(m_intIOR);
stream->writeFloat(m_extIOR);
stream->writeFloat(m_specularSamplingWeight);
@ -295,6 +320,7 @@ private:
Float m_alphaB, m_intIOR, m_extIOR;
Float m_specularSamplingWeight;
Float m_diffuseSamplingWeight;
Float m_ks, m_kd;
};
// ================ Hardware shader implementation ================
@ -304,10 +330,12 @@ public:
MicrofacetShader(Renderer *renderer,
const Texture *diffuseReflectance,
const Texture *specularReflectance,
Float alphaB, Float etaInt, Float etaExt) : Shader(renderer, EBSDFShader),
Float alphaB, Float etaInt, Float etaExt,
Float ks, Float kd) : Shader(renderer, EBSDFShader),
m_diffuseReflectance(diffuseReflectance),
m_specularReflectance(specularReflectance),
m_alphaB(alphaB), m_etaInt(etaInt), m_etaExt(etaExt) {
m_alphaB(alphaB), m_etaInt(etaInt), m_etaExt(etaExt),
m_ks(ks), m_kd(kd) {
m_diffuseReflectanceShader = renderer->registerShaderForResource(m_diffuseReflectance.get());
m_specularReflectanceShader = renderer->registerShaderForResource(m_specularReflectance.get());
}
@ -333,6 +361,8 @@ public:
oss << "uniform float " << evalName << "_alphaB;" << endl
<< "uniform float " << evalName << "_etaInt;" << endl
<< "uniform float " << evalName << "_etaExt;" << endl
<< "uniform float " << evalName << "_ks;" << endl
<< "uniform float " << evalName << "_kd;" << endl
<< endl
<< "float " << evalName << "_beckmannD(vec3 m) {" << endl
<< " float ex = tanTheta(m) / " << evalName << "_alphaB;" << endl
@ -376,8 +406,8 @@ public:
<< " vec3 hr = normalize(wi + wo);" << endl
<< " float Fr = " << evalName << "_fresnel(wi, hr, " << evalName << "_etaExt, " << evalName << "_etaInt);"<< endl
<< " float Ft = 1-Fr;"<< endl
<< " return " << depNames[0] << "(uv) * (0.31831 * Ft)" << endl
<< " + " << depNames[1] << "(uv) * (" << evalName << "_fSpec(wi, wo, hr) * Fr);" << endl
<< " return " << depNames[0] << "(uv) * (0.31831 * Ft) * " << evalName << "_kd" << endl
<< " + " << depNames[1] << "(uv) * (" << evalName << "_fSpec(wi, wo, hr) * Fr) * " << evalName << "_ks" << endl
<< "}" << endl
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
<< " if (wi.z <= 0 || wo.z <= 0)" << endl
@ -390,12 +420,16 @@ public:
parameterIDs.push_back(program->getParameterID(evalName + "_alphaB", false));
parameterIDs.push_back(program->getParameterID(evalName + "_etaInt", false));
parameterIDs.push_back(program->getParameterID(evalName + "_etaExt", false));
parameterIDs.push_back(program->getParameterID(evalName + "_ks", false));
parameterIDs.push_back(program->getParameterID(evalName + "_kd", false));
}
void bind(GPUProgram *program, const std::vector<int> &parameterIDs, int &textureUnitOffset) const {
program->setParameter(parameterIDs[0], m_alphaB);
program->setParameter(parameterIDs[1], m_etaInt);
program->setParameter(parameterIDs[2], m_etaExt);
program->setParameter(parameterIDs[3], m_ks);
program->setParameter(parameterIDs[4], m_kd);
}
MTS_DECLARE_CLASS()
@ -404,12 +438,13 @@ private:
ref<const Texture> m_specularReflectance;
ref<Shader> m_diffuseReflectanceShader;
ref<Shader> m_specularReflectanceShader;
Float m_alphaB, m_etaInt, m_etaExt;
Float m_alphaB, m_etaInt, m_etaExt, m_ks, m_kd;
};
Shader *Microfacet::createShader(Renderer *renderer) const {
return new MicrofacetShader(renderer, m_diffuseReflectance.get(),
m_specularReflectance.get(), m_alphaB, m_intIOR, m_extIOR);
m_specularReflectance.get(), m_alphaB, m_intIOR, m_extIOR,
m_ks, m_kd);
}
MTS_IMPLEMENT_CLASS(MicrofacetShader, false, Shader)

View File

@ -31,27 +31,32 @@ class Phong : public BSDF {
public:
Phong(const Properties &props)
: BSDF(props) {
m_diffuseColor = new ConstantTexture(
props.getSpectrum("diffuseColor", Spectrum(1.0f)));
m_specularColor = new ConstantTexture(
props.getSpectrum("specularColor", Spectrum(1.0f)));
m_diffuseReflectance = new ConstantTexture(
props.getSpectrum("diffuseReflectance", Spectrum(0.5f)));
m_specularReflectance = new ConstantTexture(
props.getSpectrum("specularReflectance", Spectrum(0.2f)));
m_kd = props.getFloat("diffuseAmount", 1.0f);
m_ks = props.getFloat("specularAmount", 1.0f);
m_kd = props.getFloat("diffuseReflectance", 0.5f);
m_ks = props.getFloat("specularReflectance", 0.2f);
m_exponent = props.getFloat("exponent", 10.0f);
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, "Max. diffuse reflectance = %f * %f", m_kd, m_diffuseColor->getMaximum().max());
Log(EWarn, "Max. specular reflectance = %f * %f", m_ks, m_specularColor->getMaximum().max());
Float normalization = 1/(m_kd * m_diffuseColor->getMaximum().max() + m_ks * m_specularColor->getMaximum().max());
Log(EWarn, "Reducing the albedo to %.1f%% of the original value", normalization * 100);
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_diffuseColor->getAverage().average() * m_kd;
Float avgSpecularReflectance = m_specularColor->getAverage().average() * m_ks;
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;
@ -66,8 +71,8 @@ public:
Phong(Stream *stream, InstanceManager *manager)
: BSDF(stream, manager) {
m_diffuseColor = static_cast<Texture *>(manager->getInstance(stream));
m_specularColor = static_cast<Texture *>(manager->getInstance(stream));
m_diffuseReflectance = static_cast<Texture *>(manager->getInstance(stream));
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
m_exponent = stream->readFloat();
m_kd = stream->readFloat();
m_ks = stream->readFloat();
@ -80,8 +85,8 @@ public:
m_type[1] = EGlossyReflection;
m_combinedType = m_type[0] | m_type[1];
m_usesRayDifferentials =
m_diffuseColor->usesRayDifferentials() ||
m_specularColor->usesRayDifferentials();
m_diffuseReflectance->usesRayDifferentials() ||
m_specularReflectance->usesRayDifferentials();
}
virtual ~Phong() {
@ -89,7 +94,7 @@ public:
}
Spectrum getDiffuseReflectance(const Intersection &its) const {
return m_diffuseColor->getValue(its) * m_kd;
return m_diffuseReflectance->getValue(its) * m_kd;
}
Spectrum f(const BSDFQueryRecord &bRec) const {
@ -113,11 +118,11 @@ public:
else
specRef = (m_exponent + 2) * INV_TWOPI
* std::pow(alpha, m_exponent) * m_ks;
result += m_specularColor->getValue(bRec.its) * specRef;
result += m_specularReflectance->getValue(bRec.its) * specRef;
}
if (hasDiffuse)
result += m_diffuseColor->getValue(bRec.its) * (INV_PI * m_kd);
result += m_diffuseReflectance->getValue(bRec.its) * (INV_PI * m_kd);
return result;
}
@ -155,7 +160,7 @@ public:
inline Spectrum sampleSpecular(BSDFQueryRecord &bRec) const {
Vector R = Vector(-bRec.wi.x, -bRec.wi.y, bRec.wi.z);
/* Sample a cosine lobe centered around the normal */
/* Sample from a Phong lobe centered around (0, 0, 1) */
Float sinAlpha = std::sqrt(1-std::pow(bRec.sample.y, 2/(m_exponent + 1)));
Float cosAlpha = std::pow(bRec.sample.y, 1/(m_exponent + 1));
Float phi = (2.0f * M_PI) * bRec.sample.x;
@ -218,11 +223,11 @@ public:
void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "diffuseColor") {
m_diffuseColor = static_cast<Texture *>(child);
m_usesRayDifferentials |= m_diffuseColor->usesRayDifferentials();
m_diffuseReflectance = static_cast<Texture *>(child);
m_usesRayDifferentials |= m_diffuseReflectance->usesRayDifferentials();
} else if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "specularColor") {
m_specularColor = static_cast<Texture *>(child);
m_usesRayDifferentials |= m_specularColor->usesRayDifferentials();
m_specularReflectance = static_cast<Texture *>(child);
m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials();
} else {
BSDF::addChild(name, child);
}
@ -231,8 +236,8 @@ public:
void serialize(Stream *stream, InstanceManager *manager) const {
BSDF::serialize(stream, manager);
manager->serialize(stream, m_diffuseColor.get());
manager->serialize(stream, m_specularColor.get());
manager->serialize(stream, m_diffuseReflectance.get());
manager->serialize(stream, m_specularReflectance.get());
stream->writeFloat(m_exponent);
stream->writeFloat(m_kd);
stream->writeFloat(m_ks);
@ -245,8 +250,8 @@ public:
std::string toString() const {
std::ostringstream oss;
oss << "Phong[" << endl
<< " diffuseColor = " << indent(m_diffuseColor->toString()) << "," << endl
<< " specularColor = " << indent(m_specularColor->toString()) << "," << endl
<< " diffuseColor = " << indent(m_diffuseReflectance->toString()) << "," << endl
<< " specularColor = " << indent(m_specularReflectance->toString()) << "," << endl
<< " exponent = " << m_exponent << endl
<< "]";
return oss.str();
@ -255,8 +260,8 @@ public:
MTS_DECLARE_CLASS()
private:
ref<Texture> m_diffuseColor;
ref<Texture> m_specularColor;
ref<Texture> m_diffuseReflectance;
ref<Texture> m_specularReflectance;
Float m_exponent;
Float m_kd, m_ks;
Float m_specularSamplingWeight;
@ -272,27 +277,27 @@ public:
const Texture *specularColor,
Float ks, Float kd,
Float exponent) : Shader(renderer, EBSDFShader),
m_diffuseColor(diffuseColor),
m_specularColor(specularColor),
m_diffuseReflectance(diffuseColor),
m_specularReflectance(specularColor),
m_ks(ks), m_kd(kd),
m_exponent(exponent) {
m_diffuseColorShader = renderer->registerShaderForResource(m_diffuseColor.get());
m_specularColorShader = renderer->registerShaderForResource(m_specularColor.get());
m_diffuseReflectanceShader = renderer->registerShaderForResource(m_diffuseReflectance.get());
m_specularReflectanceShader = renderer->registerShaderForResource(m_specularReflectance.get());
}
bool isComplete() const {
return m_diffuseColorShader.get() != NULL &&
m_specularColorShader.get() != NULL;
return m_diffuseReflectanceShader.get() != NULL &&
m_specularReflectanceShader.get() != NULL;
}
void putDependencies(std::vector<Shader *> &deps) {
deps.push_back(m_diffuseColorShader.get());
deps.push_back(m_specularColorShader.get());
deps.push_back(m_diffuseReflectanceShader.get());
deps.push_back(m_specularReflectanceShader.get());
}
void cleanup(Renderer *renderer) {
renderer->unregisterShaderForResource(m_diffuseColor.get());
renderer->unregisterShaderForResource(m_specularColor.get());
renderer->unregisterShaderForResource(m_diffuseReflectance.get());
renderer->unregisterShaderForResource(m_specularReflectance.get());
}
void generateCode(std::ostringstream &oss,
@ -335,17 +340,17 @@ public:
MTS_DECLARE_CLASS()
private:
ref<const Texture> m_diffuseColor;
ref<const Texture> m_specularColor;
ref<Shader> m_diffuseColorShader;
ref<Shader> m_specularColorShader;
ref<const Texture> m_diffuseReflectance;
ref<const Texture> m_specularReflectance;
ref<Shader> m_diffuseReflectanceShader;
ref<Shader> m_specularReflectanceShader;
Float m_ks, m_kd;
Float m_exponent;
};
Shader *Phong::createShader(Renderer *renderer) const {
return new PhongShader(renderer, m_diffuseColor.get(),
m_specularColor.get(), m_ks, m_kd, m_exponent);
return new PhongShader(renderer, m_diffuseReflectance.get(),
m_specularReflectance.get(), m_ks, m_kd, m_exponent);
}
MTS_IMPLEMENT_CLASS(PhongShader, false, Shader)

View File

@ -613,13 +613,11 @@ void loadMaterial(GeometryConverter *cvt, std::ostream &os, domMaterial &mat, St
os << "\t</bsdf>" << endl << endl;
} else {
os << "\t<bsdf id=\"" << identifier << "\" type=\"phong\">" << 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

@ -268,7 +268,7 @@ void Bitmap::loadBMP(Stream *stream) {
{
uint32_t header_sz;
uint32_t width;
uint32_t height;
int32_t height;
uint16_t nplanes;
uint16_t bitspp;
uint32_t compress_type;
@ -301,17 +301,41 @@ void Bitmap::loadBMP(Stream *stream) {
if (DIBHeader.bitspp != 8 && DIBHeader.bitspp != 24)
Log(EError, "Only 8- and 24-bit BMP images are supported for now");
if (DIBHeader.compress_type != 0)
Log(EError, "Only uncompressed BMP images are supported for now");
m_width = DIBHeader.width;
m_height = DIBHeader.height;
m_height = std::abs(DIBHeader.height);
m_bpp = DIBHeader.bitspp;
m_size = m_width * m_height * (m_bpp / 8);
m_data = static_cast<unsigned char *>(allocAligned(m_size));
Log(ETrace, "Reading %ix%ix%i BMP file", m_width, m_height, m_bpp);
Log(ETrace, "Reading %ix%ix%i PNG file", m_width, m_height, m_bpp);
int nChannels = m_bpp / 8;
int lineWidth = m_width * nChannels;
int paddedLineWidth = lineWidth + lineWidth % 4;
if (DIBHeader.compress_type != 0)
Log(EError, "Only uncompressed BMP images are supported for now");
uint8_t *line = new uint8_t[paddedLineWidth];
for (int y=0; y<m_height; ++y) {
stream->read(line, paddedLineWidth);
int targetY = y;
if (DIBHeader.height > 0)
targetY = m_height - 1 - y; // inverted rows
memcpy(&m_data[targetY * m_width * nChannels], line, lineWidth);
if (nChannels == 3) {
for (int x=0; x<m_width; ++x)
std::swap(m_data[(targetY * m_width + x) * nChannels],
m_data[(targetY * m_width + x) * nChannels + 2]);
}
}
delete[] line;
}
void Bitmap::loadPNG(Stream *stream) {