From 65e8b9618558b97a81e470fd0892dfd41b749d42 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Wed, 8 Sep 2010 01:05:07 +0200 Subject: [PATCH] GLSL implementation of the Ward BRDF --- src/bsdfs/ward.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/bsdfs/ward.cpp b/src/bsdfs/ward.cpp index 6b642247..36f783fd 100644 --- a/src/bsdfs/ward.cpp +++ b/src/bsdfs/ward.cpp @@ -18,6 +18,7 @@ #include #include +#include MTS_NAMESPACE_BEGIN @@ -250,6 +251,8 @@ public: stream->writeFloat(m_diffuseSamplingWeight); } + Shader *createShader(Renderer *renderer) const; + std::string toString() const { std::ostringstream oss; oss << "Ward[" << endl @@ -275,6 +278,95 @@ private: bool m_verifyEnergyConservation; }; +// ================ Hardware shader implementation ================ + +class WardShader : public Shader { +public: + WardShader(Renderer *renderer, + const Texture *diffuseColor, + const Texture *specularColor, + Float ks, Float kd, + Float alphaX, Float alphaY) : Shader(renderer, EBSDFShader), + m_diffuseReflectance(diffuseColor), + m_specularReflectance(specularColor), + m_ks(ks), m_kd(kd), m_alphaX(alphaX), m_alphaY(alphaY) { + m_diffuseReflectanceShader = renderer->registerShaderForResource(m_diffuseReflectance.get()); + m_specularReflectanceShader = renderer->registerShaderForResource(m_specularReflectance.get()); + } + + bool isComplete() const { + return m_diffuseReflectanceShader.get() != NULL && + m_specularReflectanceShader.get() != NULL; + } + + void putDependencies(std::vector &deps) { + deps.push_back(m_diffuseReflectanceShader.get()); + deps.push_back(m_specularReflectanceShader.get()); + } + + void cleanup(Renderer *renderer) { + renderer->unregisterShaderForResource(m_diffuseReflectance.get()); + renderer->unregisterShaderForResource(m_specularReflectance.get()); + } + + void generateCode(std::ostringstream &oss, + const std::string &evalName, + const std::vector &depNames) const { + oss << "uniform float " << evalName << "_alphaX;" << endl + << "uniform float " << evalName << "_alphaY;" << 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 + << " return vec3(0.0);" << endl + << " vec3 H = normalize(wi + wo);" << endl + << " float factor1 = 1/(12.566 * " << evalName << "_alphaX * " + << " " << evalName << "_alphaY * sqrt(wi.z * wo.z));" << endl + << " float factor2 = H.x / " << evalName << "_alphaX;" << endl + << " float factor3 = H.y / " << evalName << "_alphaY;" << endl + << " float exponent = -(factor2*factor2 + factor3*factor3)/(H.z*H.z);" << endl + << " float specRef = factor1 * exp(exponent) * " << evalName << "_ks;" << endl + << " return " << depNames[0] << "(uv) * (0.31831 * " << evalName << "_kd)" << endl + << " + " << depNames[1] << "(uv) * specRef;" << endl + << "}" << endl + << "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl + << " if (wi.z < 0.0 || wo.z < 0.0)" << endl + << " return vec3(0.0);" << endl + << " return " << depNames[0] << "(uv) * (0.31831 * " << evalName << "_kd);" << endl + << "}" << endl; + } + + void resolve(const GPUProgram *program, const std::string &evalName, std::vector ¶meterIDs) const { + parameterIDs.push_back(program->getParameterID(evalName + "_alphaX")); + parameterIDs.push_back(program->getParameterID(evalName + "_alphaY")); + 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_alphaX); + program->setParameter(parameterIDs[1], m_alphaY); + program->setParameter(parameterIDs[2], m_ks); + program->setParameter(parameterIDs[3], m_kd); + } + + MTS_DECLARE_CLASS() +private: + ref m_diffuseReflectance; + ref m_specularReflectance; + ref m_diffuseReflectanceShader; + ref m_specularReflectanceShader; + Float m_ks, m_kd; + Float m_alphaX, m_alphaY; +}; + +Shader *Ward::createShader(Renderer *renderer) const { + return new WardShader(renderer, m_diffuseReflectance.get(), + m_specularReflectance.get(), m_ks, m_kd, m_alphaX, m_alphaY); +} + +MTS_IMPLEMENT_CLASS(WardShader, false, Shader) MTS_IMPLEMENT_CLASS_S(Ward, false, BSDF); MTS_EXPORT_PLUGIN(Ward, "Anisotropic Ward BRDF"); MTS_NAMESPACE_END