diff --git a/include/mitsuba/hw/basicshader.h b/include/mitsuba/hw/basicshader.h index e858e570..e8cff643 100644 --- a/include/mitsuba/hw/basicshader.h +++ b/include/mitsuba/hw/basicshader.h @@ -118,55 +118,6 @@ protected: Float m_value; }; -/** - * \brief Scaling passthrough texture - * - * Includes a \ref Shader implementation for hardware rendering - */ -class MTS_EXPORT_RENDER ScaleTexture : public Texture { -public: - inline ScaleTexture(const Texture *nested, const Float &scale) - : Texture(Properties()), m_nested(nested), m_scale(scale) { - } - - ScaleTexture(Stream *stream, InstanceManager *manager); - - - inline Spectrum getValue(const Intersection &its) const { - return m_nested->getValue(its) * m_scale; - } - - inline Spectrum getAverage() const { - return m_nested->getAverage() * m_scale; - } - - inline Spectrum getMaximum() const { - return m_nested->getMaximum() * m_scale; - } - - inline std::string toString() const { - std::ostringstream oss; - oss << "ScaleTexture[" << endl - << " nested = " << indent(m_nested->toString()) << "," << endl - << " scale = " << m_scale << endl - << "]"; - return oss.str(); - } - - inline bool usesRayDifferentials() const { - return m_nested->usesRayDifferentials(); - } - - Shader *createShader(Renderer *renderer) const; - - void serialize(Stream *stream, InstanceManager *manager) const; - - MTS_DECLARE_CLASS() -protected: - ref m_nested; - Float m_scale; -}; - MTS_NAMESPACE_END #endif /* __BASIC_SHADER_H */ diff --git a/src/bsdfs/roughdiffuse.cpp b/src/bsdfs/roughdiffuse.cpp index 5eb8c1f3..1a30e27e 100644 --- a/src/bsdfs/roughdiffuse.cpp +++ b/src/bsdfs/roughdiffuse.cpp @@ -43,22 +43,27 @@ MTS_NAMESPACE_BEGIN * such as plaster, sand, clay, or concrete. * The underlying theory was developed by Oren and Nayar * \cite{Oren1994Generalization}, who model the microscopic surface structure as - * an arrangement of unresolved planar facets with different slopes, where each facet + * unresolved planar facets arranged in V-shaped grooves, where each facet * is an ideal diffuse reflector. The model takes into account shadowing, * masking, as well as interreflections between the facets. * * Since the original publication in 1994, this approach has been shown to - * be a very good match for many real-world materials, in particular - * compared to Lambertian scattering, which does not take surface - * roughness into account. + * be a good match for many real-world materials, particularly compared + * to Lambertian scattering, which does not take surface roughness into account. * - * To get an intuition about the effect of the surface roughness + * The implementation in Mitsuba uses a surface roughness parameter $\alpha$ that + * is slighly different from the slope-area variance in the original paper. + * The reason for this change is to make the parameter $\alpha$ portable + * across different models (i.e. \pluginref{roughglass}, + * \pluginref{roughconductor}). + * + * To get an intuition about the effect of the * parameter $\alpha$, consider the following approximate differentiation: * a value of $\alpha=0.001-0.01$ corresponds to a material * with slight imperfections on an otherwise smooth surface (for such small * values, the model will behave almost identically to \pluginref{diffuse}), $\alpha=0.1$ * is relatively rough, and $\alpha=0.3-0.5$ is \emph{extremely} rough - * (e.g. an etched or ground finish). + * (e.g. an etched or ground surface). * * Note that this material is one-sided---that is, observed from the * back side, it will be completely black. If this is undesirable, diff --git a/src/libhw/basicshader.cpp b/src/libhw/basicshader.cpp index ec23f52b..71c93b05 100644 --- a/src/libhw/basicshader.cpp +++ b/src/libhw/basicshader.cpp @@ -41,18 +41,6 @@ void ConstantFloatTexture::serialize(Stream *stream, InstanceManager *manager) c stream->writeFloat(m_value); } -ScaleTexture::ScaleTexture(Stream *stream, InstanceManager *manager) - : Texture(stream, manager) { - m_nested = static_cast(manager->getInstance(stream)); - m_scale = stream->readFloat(); -} - -void ScaleTexture::serialize(Stream *stream, InstanceManager *manager) const { - Texture::serialize(stream, manager); - manager->serialize(stream, m_nested.get()); - stream->writeFloat(m_scale); -} - class ConstantSpectrumTextureShader : public Shader { public: ConstantSpectrumTextureShader(Renderer *renderer, const Spectrum &value) @@ -111,50 +99,6 @@ private: Float m_value; }; -class ScaleTextureShader : public Shader { -public: - ScaleTextureShader(Renderer *renderer, const Texture *nested, const Float &scale) - : Shader(renderer, ETextureShader), m_nested(nested), m_scale(scale) { - m_nestedShader = renderer->registerShaderForResource(m_nested.get()); - } - - bool isComplete() const { - return m_nestedShader.get() != NULL; - } - - void cleanup(Renderer *renderer) { - renderer->unregisterShaderForResource(m_nested.get()); - } - - void putDependencies(std::vector &deps) { - deps.push_back(m_nestedShader.get()); - } - - void generateCode(std::ostringstream &oss, - const std::string &evalName, - const std::vector &depNames) const { - oss << "uniform float " << evalName << "_scale;" << endl - << endl - << "vec3 " << evalName << "(vec2 uv) {" << endl - << " return " << depNames[0] << "(uv) * " << evalName << "_scale;" << endl - << "}" << endl; - } - - void resolve(const GPUProgram *program, const std::string &evalName, std::vector ¶meterIDs) const { - parameterIDs.push_back(program->getParameterID(evalName + "_scale")); - } - - void bind(GPUProgram *program, const std::vector ¶meterIDs, int &nestedUnitOffset) const { - program->setParameter(parameterIDs[0], m_scale); - } - - MTS_DECLARE_CLASS() -private: - ref m_nested; - ref m_nestedShader; - Float m_scale; -}; - Shader *ConstantSpectrumTexture::createShader(Renderer *renderer) const { return new ConstantSpectrumTextureShader(renderer, m_value); } @@ -163,15 +107,8 @@ Shader *ConstantFloatTexture::createShader(Renderer *renderer) const { return new ConstantFloatTextureShader(renderer, m_value); } -Shader *ScaleTexture::createShader(Renderer *renderer) const { - return new ScaleTextureShader(renderer, m_nested.get(), m_scale); -} - - MTS_IMPLEMENT_CLASS_S(ConstantSpectrumTexture, false, Texture) MTS_IMPLEMENT_CLASS(ConstantSpectrumTextureShader, false, Shader) MTS_IMPLEMENT_CLASS_S(ConstantFloatTexture, false, Texture) MTS_IMPLEMENT_CLASS(ConstantFloatTextureShader, false, Shader) -MTS_IMPLEMENT_CLASS_S(ScaleTexture, false, Texture) -MTS_IMPLEMENT_CLASS(ScaleTextureShader, false, Shader) MTS_NAMESPACE_END diff --git a/src/librender/bsdf.cpp b/src/librender/bsdf.cpp index 883491fe..77976e5e 100644 --- a/src/librender/bsdf.cpp +++ b/src/librender/bsdf.cpp @@ -84,8 +84,11 @@ Texture *BSDF::ensureEnergyConservation(Texture *texture, Log(EWarn, "%s", oss.str().c_str()); Properties props("scale"); props.setFloat("value", scale); - return static_cast (PluginManager::getInstance()-> + Texture *scaleTexture = static_cast (PluginManager::getInstance()-> createObject(MTS_CLASS(Texture), props)); + scaleTexture->addChild("", texture); + scaleTexture->configure(); + return scaleTexture; } return texture; } diff --git a/src/textures/SConscript b/src/textures/SConscript index 7ea1f828..9c013e65 100644 --- a/src/textures/SConscript +++ b/src/textures/SConscript @@ -1,6 +1,7 @@ Import('env', 'plugins') plugins += env.SharedLibrary('bitmap', ['bitmap.cpp']) +plugins += env.SharedLibrary('scale', ['scale.cpp']) plugins += env.SharedLibrary('gridtexture', ['gridtexture.cpp']) plugins += env.SharedLibrary('checkerboard', ['checkerboard.cpp']) plugins += env.SharedLibrary('vertexcolors', ['vertexcolors.cpp']) diff --git a/src/textures/scale.cpp b/src/textures/scale.cpp new file mode 100644 index 00000000..69522b69 --- /dev/null +++ b/src/textures/scale.cpp @@ -0,0 +1,151 @@ +/* + This file is part of Mitsuba, a physically based rendering system. + + Copyright (c) 2007-2011 by Wenzel Jakob and others. + + Mitsuba is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License Version 3 + as published by the Free Software Foundation. + + Mitsuba is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include + +MTS_NAMESPACE_BEGIN + +/** + * \brief Scaling passthrough texture + * + * Includes a \ref Shader implementation for hardware rendering + */ +class ScalingTexture : public Texture { +public: + ScalingTexture(const Properties &props) : Texture(props) { + if (props.hasProperty("value") && props.getType("value") == Properties::EFloat) + m_scale = Spectrum(props.getFloat("value", 1.0f)); + else + m_scale = props.getSpectrum("value", Spectrum(1.0f)); + } + + ScalingTexture(Stream *stream, InstanceManager *manager) + : Texture(stream, manager) { + m_nested = static_cast(manager->getInstance(stream)); + m_scale = Spectrum(stream); + } + + void configure() { + if (m_nested == NULL) + Log(EError, "The scale plugin needs a nested texture!"); + } + + void addChild(const std::string &name, ConfigurableObject *child) { + if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) { + m_nested = static_cast(child); + } else { + Texture::addChild(name, child); + } + } + + Spectrum getValue(const Intersection &its) const { + return m_nested->getValue(its) * m_scale; + } + + Spectrum getAverage() const { + return m_nested->getAverage() * m_scale; + } + + Spectrum getMaximum() const { + return m_nested->getMaximum() * m_scale; + } + + std::string toString() const { + std::ostringstream oss; + oss << "ScalingTexture[" << endl + << " nested = " << indent(m_nested->toString()) << "," << endl + << " scale = " << m_scale.toString() << endl + << "]"; + return oss.str(); + } + + bool usesRayDifferentials() const { + return m_nested->usesRayDifferentials(); + } + + Shader *createShader(Renderer *renderer) const; + + void serialize(Stream *stream, InstanceManager *manager) const { + Texture::serialize(stream, manager); + manager->serialize(stream, m_nested.get()); + m_scale.serialize(stream); + } + + MTS_DECLARE_CLASS() +protected: + ref m_nested; + Spectrum m_scale; +}; + +// ================ Hardware shader implementation ================ + +class ScalingTextureShader : public Shader { +public: + ScalingTextureShader(Renderer *renderer, const Texture *nested, const Spectrum &scale) + : Shader(renderer, ETextureShader), m_nested(nested), m_scale(scale) { + m_nestedShader = renderer->registerShaderForResource(m_nested.get()); + } + + bool isComplete() const { + return m_nestedShader.get() != NULL; + } + + void cleanup(Renderer *renderer) { + renderer->unregisterShaderForResource(m_nested.get()); + } + + void putDependencies(std::vector &deps) { + deps.push_back(m_nestedShader.get()); + } + + void generateCode(std::ostringstream &oss, + const std::string &evalName, + const std::vector &depNames) const { + oss << "uniform vec3 " << evalName << "_scale;" << endl + << endl + << "vec3 " << evalName << "(vec2 uv) {" << endl + << " return " << depNames[0] << "(uv) * " << evalName << "_scale;" << endl + << "}" << endl; + } + + void resolve(const GPUProgram *program, const std::string &evalName, std::vector ¶meterIDs) const { + parameterIDs.push_back(program->getParameterID(evalName + "_scale")); + } + + void bind(GPUProgram *program, const std::vector ¶meterIDs, int &nestedUnitOffset) const { + program->setParameter(parameterIDs[0], m_scale); + } + + MTS_DECLARE_CLASS() +private: + ref m_nested; + ref m_nestedShader; + Spectrum m_scale; +}; + +Shader *ScalingTexture::createShader(Renderer *renderer) const { + return new ScalingTextureShader(renderer, m_nested.get(), m_scale); +} + +MTS_IMPLEMENT_CLASS(ScalingTextureShader, false, Shader) +MTS_IMPLEMENT_CLASS_S(ScalingTexture, false, Texture2D) +MTS_EXPORT_PLUGIN(ScalingTexture, "Scaling texture"); +MTS_NAMESPACE_END