improved interface for ensuring energy conservation

metadata
Wenzel Jakob 2011-07-07 17:49:21 +02:00
parent 8dbb6327f4
commit 736a8e6866
18 changed files with 345 additions and 164 deletions

View File

@ -2,8 +2,7 @@
to be tested for consistency. This is done
using the testcase 'test_chisquare' -->
<scene>
<!-- Test the rough glass model with the
<!-- Test the rough dielectric model with the anisotropic
Ashikhmin-Shirley microfacet distribution -->
<bsdf type="roughdielectric">
<string name="distribution" value="as"/>
@ -19,15 +18,6 @@
<string name="extIOR" value="air"/>
</bsdf>
<!-- Test the rough glass model with the
Beckmann microfacet distribution -->
<bsdf type="roughdielectric">
<string name="distribution" value="beckmann"/>
<float name="alpha" value=".3"/>
<float name="intIOR" value="1.5"/>
<float name="extIOR" value="1.0"/>
</bsdf>
<!-- Test the diffuse model -->
<bsdf type="diffuse"/>
@ -49,4 +39,41 @@
<!-- Test the conductor model -->
<bsdf type="conductor"/>
<!-- Test the rough glass model with the
Beckmann microfacet distribution -->
<bsdf type="roughdielectric">
<string name="distribution" value="beckmann"/>
<float name="alpha" value=".3"/>
<float name="intIOR" value="1.5"/>
<float name="extIOR" value="1.0"/>
</bsdf>
<!-- Test the rough glass model with the
Phong microfacet distribution -->
<bsdf type="roughdielectric">
<string name="distribution" value="phong"/>
<float name="alpha" value=".3"/>
<float name="intIOR" value="1.5"/>
<float name="extIOR" value="1.0"/>
</bsdf>
<!-- Test the rough glass model with the
GGX microfacet distribution -->
<bsdf type="roughdielectric">
<string name="distribution" value="ggx"/>
<float name="alpha" value=".3"/>
<float name="intIOR" value="1.5"/>
<float name="extIOR" value="1.0"/>
</bsdf>
<!-- Test the rough dielectric model with the anisotropic
Ashikhmin-Shirley microfacet distribution -->
<bsdf type="roughdielectric">
<string name="distribution" value="as"/>
<float name="alphaU" value=".1"/>
<float name="alphaV" value=".3"/>
<float name="intIOR" value="1.5"/>
<float name="extIOR" value="1.0"/>
</bsdf>
</scene>

View File

@ -422,12 +422,26 @@ protected:
/// Unserialize a BSDF instance
BSDF(Stream *stream, InstanceManager *manager);
/**
* \brief Convenience function to ensure energy conservation
*
* This function determines the component-wise maximum of the
* texture \c tex and checks if it is below \c max. If yes,
* it returns the texture unmodified. Otherwise, it wraps
* the texture into a \ref ScaleTexture instance (with a
* scaling factor chosen so that the desired maximum \c max
* is abided) and prints a warning.
*/
Texture *ensureEnergyConservation(Texture *tex,
const std::string &paramName, Float max) const;
/// Virtual destructor
virtual ~BSDF();
protected:
std::vector<unsigned int> m_components;
unsigned int m_combinedType;
bool m_usesRayDifferentials;
bool m_ensureEnergyConservation;
std::string m_name;
};

View File

@ -1,109 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#if !defined(__CONST_TEXTURE_H)
#define __CONST_TEXTURE_H
#include <mitsuba/core/properties.h>
#include <mitsuba/render/texture.h>
MTS_NAMESPACE_BEGIN
class MTS_EXPORT_RENDER ConstantSpectrumTexture : public Texture {
public:
inline ConstantSpectrumTexture(const Spectrum &value)
: Texture(Properties()), m_value(value) {
}
ConstantSpectrumTexture(Stream *stream, InstanceManager *manager);
inline Spectrum getValue(const Intersection &its) const {
return m_value;
}
inline Spectrum getAverage() const {
return m_value;
}
inline Spectrum getMaximum() const {
return m_value;
}
inline std::string toString() const {
std::ostringstream oss;
oss << "ConstantSpectrumTexture[value=" << m_value.toString() << "]";
return oss.str();
}
inline bool usesRayDifferentials() const {
return false;
}
Shader *createShader(Renderer *renderer) const;
void serialize(Stream *stream, InstanceManager *manager) const;
MTS_DECLARE_CLASS()
protected:
Spectrum m_value;
};
class MTS_EXPORT_RENDER ConstantFloatTexture : public Texture {
public:
inline ConstantFloatTexture(const Float &value)
: Texture(Properties()), m_value(value) {
}
ConstantFloatTexture(Stream *stream, InstanceManager *manager);
inline Spectrum getValue(const Intersection &its) const {
return Spectrum(m_value);
}
inline Spectrum getAverage() const {
return Spectrum(m_value);
}
inline Spectrum getMaximum() const {
return Spectrum(m_value);
}
inline std::string toString() const {
std::ostringstream oss;
oss << "ConstantFloatTexture[value=" << m_value << "]";
return oss.str();
}
inline bool usesRayDifferentials() const {
return false;
}
Shader *createShader(Renderer *renderer) const;
void serialize(Stream *stream, InstanceManager *manager) const;
MTS_DECLARE_CLASS()
protected:
Float m_value;
};
MTS_NAMESPACE_END
#endif /* __CONST_TEXTURE_H */

View File

@ -20,6 +20,7 @@
#define __TEXTURE_H
#include <mitsuba/core/cobject.h>
#include <mitsuba/core/properties.h>
#include <mitsuba/render/shader.h>
MTS_NAMESPACE_BEGIN
@ -85,6 +86,133 @@ protected:
Vector2 m_uvScale;
};
/* ============================================================ */
/* Some vary basic texture definitions */
/* ============================================================ */
class MTS_EXPORT_RENDER ConstantSpectrumTexture : public Texture {
public:
inline ConstantSpectrumTexture(const Spectrum &value)
: Texture(Properties()), m_value(value) {
}
ConstantSpectrumTexture(Stream *stream, InstanceManager *manager);
inline Spectrum getValue(const Intersection &its) const {
return m_value;
}
inline Spectrum getAverage() const {
return m_value;
}
inline Spectrum getMaximum() const {
return m_value;
}
inline std::string toString() const {
std::ostringstream oss;
oss << "ConstantSpectrumTexture[value=" << m_value.toString() << "]";
return oss.str();
}
inline bool usesRayDifferentials() const {
return false;
}
Shader *createShader(Renderer *renderer) const;
void serialize(Stream *stream, InstanceManager *manager) const;
MTS_DECLARE_CLASS()
protected:
Spectrum m_value;
};
class MTS_EXPORT_RENDER ConstantFloatTexture : public Texture {
public:
inline ConstantFloatTexture(const Float &value)
: Texture(Properties()), m_value(value) {
}
ConstantFloatTexture(Stream *stream, InstanceManager *manager);
inline Spectrum getValue(const Intersection &its) const {
return Spectrum(m_value);
}
inline Spectrum getAverage() const {
return Spectrum(m_value);
}
inline Spectrum getMaximum() const {
return Spectrum(m_value);
}
inline std::string toString() const {
std::ostringstream oss;
oss << "ConstantFloatTexture[value=" << m_value << "]";
return oss.str();
}
inline bool usesRayDifferentials() const {
return false;
}
Shader *createShader(Renderer *renderer) const;
void serialize(Stream *stream, InstanceManager *manager) const;
MTS_DECLARE_CLASS()
protected:
Float m_value;
};
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<const Texture> m_nested;
Float m_scale;
};
MTS_NAMESPACE_END
#endif /* __TEXTURE_H */

View File

@ -17,7 +17,7 @@
*/
#include <mitsuba/render/bsdf.h>
#include <mitsuba/render/consttexture.h>
#include <mitsuba/render/texture.h>
MTS_NAMESPACE_BEGIN

View File

@ -17,7 +17,7 @@
*/
#include <mitsuba/render/bsdf.h>
#include <mitsuba/render/consttexture.h>
#include <mitsuba/render/texture.h>
#include <mitsuba/core/fresolver.h>
MTS_NAMESPACE_BEGIN
@ -180,6 +180,13 @@ public:
}
}
void configure() {
BSDF::configure();
/* Verify the input parameter and fix them if necessary */
m_specularReflectance = ensureEnergyConservation(
m_specularReflectance, "specularReflectance", 1.0f);
}
/// Reflection in local coordinates
inline Vector reflect(const Vector &wi) const {
return Vector(-wi.x, -wi.y, wi.z);

View File

@ -17,7 +17,7 @@
*/
#include <mitsuba/render/bsdf.h>
#include <mitsuba/render/consttexture.h>
#include <mitsuba/render/texture.h>
#include "ior.h"
MTS_NAMESPACE_BEGIN
@ -186,6 +186,15 @@ public:
}
}
void configure() {
BSDF::configure();
/* Verify the input parameter and fix them if necessary */
m_specularReflectance = ensureEnergyConservation(
m_specularReflectance, "specularReflectance", 1.0f);
m_specularTransmittance = ensureEnergyConservation(
m_specularTransmittance, "specularTransmittance", 1.0f);
}
/// Reflection in local coordinates
inline Vector reflect(const Vector &wi) const {
return Vector(-wi.x, -wi.y, wi.z);

View File

@ -17,12 +17,11 @@
*/
#include <mitsuba/render/bsdf.h>
#include <mitsuba/render/consttexture.h>
#include <mitsuba/render/texture.h>
#include <mitsuba/hw/renderer.h>
MTS_NAMESPACE_BEGIN
/*! \plugin{difftrans}{Diffuse transmitter}
*
* \parameters{
@ -42,7 +41,6 @@ MTS_NAMESPACE_BEGIN
* plugin.} with a surface reflection model to describe translucent substances
* that have internal multiple scattering processes (e.g. plant leaves).
*/
class DiffuseTransmitter : public BSDF {
public:
DiffuseTransmitter(const Properties &props)
@ -65,6 +63,12 @@ public:
virtual ~DiffuseTransmitter() { }
void configure() {
BSDF::configure();
/* Verify the input parameter and fix them if necessary */
m_transmittance = ensureEnergyConservation(m_transmittance, "transmittance", 1.0f);
}
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
if (!(bRec.typeMask & EDiffuseTransmission) || measure != ESolidAngle
|| Frame::cosTheta(bRec.wi) * Frame::cosTheta(bRec.wo) >= 0)

View File

@ -17,8 +17,7 @@
*/
#include <mitsuba/render/bsdf.h>
#include <mitsuba/render/consttexture.h>
#include <mitsuba/core/properties.h>
#include <mitsuba/render/texture.h>
#include <mitsuba/hw/renderer.h>
MTS_NAMESPACE_BEGIN
@ -87,6 +86,16 @@ public:
virtual ~SmoothDiffuse() { }
void configure() {
BSDF::configure();
/* Verify the input parameter and fix them if necessary */
m_reflectance = ensureEnergyConservation(m_reflectance, "reflectance", 1.0f);
}
Spectrum getDiffuseReflectance(const Intersection &its) const {
return m_reflectance->getValue(its);
}
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
if (!(bRec.typeMask & EDiffuseReflection) || measure != ESolidAngle
|| Frame::cosTheta(bRec.wi) <= 0
@ -147,6 +156,7 @@ public:
std::string toString() const {
std::ostringstream oss;
oss << "SmoothDiffuse[" << endl
<< " name = \"" << getName() << "\"," << endl
<< " reflectance = " << indent(m_reflectance->toString()) << endl
<< "]";
return oss.str();

View File

@ -106,7 +106,7 @@ public:
case EPhong: {
/* Phong distribution function */
result = (alphaU + 1) * INV_TWOPI
result = (alphaU + 2) * INV_TWOPI
* std::pow(Frame::cosTheta(m), alphaU);
}
break;
@ -315,20 +315,8 @@ public:
* \param alpha The surface roughness
*/
Float G(const Vector &wi, const Vector &wo, const Vector &m, Float alphaU, Float alphaV) const {
if (EXPECT_TAKEN(m_type != EAshikhminShirley)) {
return smithG1(wi, m, alphaU) * smithG1(wo, m, alphaV);
} else {
/* Infinite groove shadowing/masking */
const Float nDotM = std::abs(Frame::cosTheta(m)),
nDotWo = std::abs(Frame::cosTheta(wo)),
nDotWi = std::abs(Frame::cosTheta(wi)),
woDotM = absDot(wo, m),
wiDotM = absDot(wi, m);
return std::max((Float) 0, std::min((Float) 1,
std::min(2 * nDotM * nDotWo / woDotM,
2 * nDotM * nDotWi / wiDotM)));
}
Float alpha = std::max(alphaU, alphaV);
return smithG1(wi, m, alpha) * smithG1(wo, m, alpha);
}
std::string toString() const {

View File

@ -41,7 +41,7 @@ public:
m_exponent = props.getFloat("exponent", 10.0f);
m_verifyEnergyConservation = props.getBoolean("verifyEnergyConservation", true);
m_ensureEnergyConservation = props.getBoolean("ensureEnergyConservation", true);
m_specularSamplingWeight = props.getFloat("specularSamplingWeight", -1);
m_componentCount = 2;
@ -78,14 +78,14 @@ public:
void configure() {
BSDF::configure();
if (m_verifyEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
if (m_ensureEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
+ m_ks * m_specularReflectance->getMaximum().max() > 1.0f)) {
Log(EWarn, "Material \"%s\": Energy conservation is potentially violated!", getName().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);
"Specify ensureEnergyConservation=false to prevent this.", normalization * 100);
m_kd *= normalization; m_ks *= normalization;
}
@ -275,7 +275,7 @@ private:
Float m_kd, m_ks;
Float m_specularSamplingWeight;
Float m_diffuseSamplingWeight;
bool m_verifyEnergyConservation;
bool m_ensureEnergyConservation;
};
// ================ Hardware shader implementation ================

View File

@ -18,8 +18,9 @@
#include <mitsuba/render/bsdf.h>
#include <mitsuba/render/sampler.h>
#include <mitsuba/render/consttexture.h>
#include <mitsuba/render/texture.h>
#include "microfacet.h"
#include "ior.h"
MTS_NAMESPACE_BEGIN
@ -123,8 +124,8 @@ MTS_NAMESPACE_BEGIN
* \begin{xml}[caption=A texture can be attached to the roughness parameter, label=lst:roughdielectric-textured]
* <bsdf type="roughdielectric">
* <string name="distribution" value="beckmann"/>
* <float name="intIOR" value="1.5046"/>
* <float name="extIOR" value="1.0"/>
* <string name="intIOR" value="bk7"/>
* <string name="extIOR" value="air"/>
*
* <texture name="alpha" type="bitmap">
* <string name="filename" value="roughness.exr"/>
@ -141,8 +142,11 @@ public:
m_specularTransmittance = new ConstantSpectrumTexture(
props.getSpectrum("specularTransmittance", Spectrum(1.0f)));
m_intIOR = props.getFloat("intIOR", 1.5046f);
m_extIOR = props.getFloat("extIOR", 1.0f);
/* Specifies the internal index of refraction at the interface */
m_intIOR = lookupIOR(props, "intIOR", "bk7");
/* Specifies the external index of refraction at the interface */
m_extIOR = lookupIOR(props, "extIOR", "air");
if (m_intIOR < 0 || m_extIOR < 0 || m_intIOR == m_extIOR)
Log(EError, "The interior and exterior indices of "
@ -208,6 +212,12 @@ public:
m_components.push_back(
EGlossyTransmission | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
/* Verify the input parameter and fix them if necessary */
m_specularReflectance = ensureEnergyConservation(
m_specularReflectance, "specularReflectance", 1.0f);
m_specularTransmittance = ensureEnergyConservation(
m_specularTransmittance, "specularTransmittance", 1.0f);
BSDF::configure();
}
@ -303,7 +313,8 @@ public:
} else {
/* Calculate the total amount of transmission */
Float sqrtDenom = etaI * dot(bRec.wi, H) + etaT * dot(bRec.wo, H);
Float value = ((1 - F) * D * G * etaT * etaT * dot(bRec.wi, H)*dot(bRec.wo, H)) /
Float value = ((1 - F) * D * G * etaT * etaT
* dot(bRec.wi, H) * dot(bRec.wo, H)) /
(Frame::cosTheta(bRec.wi) * sqrtDenom * sqrtDenom);
/* Missing term in the original paper: account for the solid angle
@ -380,6 +391,7 @@ public:
std::abs(Frame::cosTheta(bRec.wi))));
alphaU *= factor; alphaV *= factor;
#endif
/* Microsurface normal sampling density */
Float prob = m_distribution.pdf(H, alphaU, alphaV);
@ -512,7 +524,8 @@ public:
return Spectrum(0.0f);
result = m_specularTransmittance->getValue(bRec.its)
* ((bRec.quantity == ERadiance) ? ((etaI*etaI) / (etaT*etaT)) : (Float) 1);
* ((bRec.quantity == ERadiance) ?
((etaI*etaI) / (etaT*etaT)) : (Float) 1);
}
Float numerator = m_distribution.eval(m, alphaU, alphaV)
@ -603,7 +616,8 @@ public:
#endif
/* Sample M, the microsurface normal */
const Normal m = m_distribution.sample(sample, sampleAlphaU, sampleAlphaV);
const Normal m = m_distribution.sample(sample,
sampleAlphaU, sampleAlphaV);
if (sampleExactFresnelTerm) {
Float sampleF = fresnel(dot(bRec.wi, m), m_extIOR, m_intIOR);

View File

@ -17,7 +17,7 @@
*/
#include <mitsuba/render/bsdf.h>
#include <mitsuba/render/consttexture.h>
#include <mitsuba/render/texture.h>
#include <mitsuba/hw/gpuprogram.h>
MTS_NAMESPACE_BEGIN

View File

@ -72,7 +72,7 @@ public:
Log(EError, "Specified an invalid model type \"%s\", must be "
"\"ward\", \"ward-duer\", or \"balanced\"!", type.c_str());
m_verifyEnergyConservation = props.getBoolean("verifyEnergyConservation", true);
m_ensureEnergyConservation = props.getBoolean("ensureEnergyConservation", true);
m_specularSamplingWeight = props.getFloat("specularSamplingWeight", -1);
m_alphaX = props.getFloat("alphaX", .1f);
@ -116,14 +116,14 @@ public:
}
void configure() {
if (m_verifyEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
if (m_ensureEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
+ m_ks * m_specularReflectance->getMaximum().max() > 1.0f)) {
Log(EWarn, "Material \"%s\": Energy conservation is potentially violated!", getName().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);
"Specify ensureEnergyConservation=false to prevent this.", normalization * 100);
m_kd *= normalization; m_ks *= normalization;
}
@ -340,7 +340,7 @@ private:
Float m_kd, m_ks;
Float m_specularSamplingWeight;
Float m_diffuseSamplingWeight;
bool m_verifyEnergyConservation;
bool m_ensureEnergyConservation;
};
// ================ Hardware shader implementation ================

View File

@ -23,11 +23,17 @@ MTS_NAMESPACE_BEGIN
BSDF::BSDF(const Properties &props)
: ConfigurableObject(props), m_name(props.getID()) {
/* By default, verify whether energy conservation holds
for the user-specified parameter values. This step
is completely up to the particular BSDF implementations */
m_ensureEnergyConservation = props.getBoolean(
"ensureEnergyConservation", true);
}
BSDF::BSDF(Stream *stream, InstanceManager *manager)
: ConfigurableObject(stream, manager) {
m_name = stream->readString();
m_ensureEnergyConservation = stream->readBool();
}
BSDF::~BSDF() { }
@ -35,6 +41,7 @@ BSDF::~BSDF() { }
void BSDF::serialize(Stream *stream, InstanceManager *manager) const {
ConfigurableObject::serialize(stream, manager);
stream->writeString(m_name);
stream->writeBool(m_ensureEnergyConservation);
}
void BSDF::setParent(ConfigurableObject *parent) {
@ -58,6 +65,28 @@ Spectrum BSDF::getDiffuseReflectance(const Intersection &its) const {
return eval(bRec) * M_PI;
}
Texture *BSDF::ensureEnergyConservation(Texture *texture,
const std::string &paramName, Float max) const {
if (!m_ensureEnergyConservation)
return texture;
Float actualMax = texture->getMaximum().max();
if (actualMax > max) {
std::ostringstream oss;
Float scale = 0.99f * (max / actualMax);
oss << "The BSDF" << endl << toString() << endl
<< "violates energy conservation! The parameter \"" << paramName << "\" "
<< "has a component-wise maximum of "<< actualMax << " (which is > " << max << "!) "
<< "and will therefore be scaled by " << scale << " to prevent "
<< "issues. Specify the parameter ensureEnergyConservation=false "
<< "to the BSDF to prevent this from happening.";
Log(EWarn, "%s", oss.str().c_str());
return new ScaleTexture(texture, scale);
}
return texture;
}
static std::string typeMaskToString(unsigned int typeMask) {
std::ostringstream oss;
oss << "{ ";

View File

@ -16,7 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mitsuba/render/consttexture.h>
#include <mitsuba/render/texture.h>
#include <mitsuba/hw/gpuprogram.h>
MTS_NAMESPACE_BEGIN
@ -102,6 +102,18 @@ 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<Texture *>(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)
@ -160,6 +172,50 @@ 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<Shader *> &deps) {
deps.push_back(m_nestedShader.get());
}
void generateCode(std::ostringstream &oss,
const std::string &evalName,
const std::vector<std::string> &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<int> &parameterIDs) const {
parameterIDs.push_back(program->getParameterID(evalName + "_scale"));
}
void bind(GPUProgram *program, const std::vector<int> &parameterIDs, int &nestedUnitOffset) const {
program->setParameter(parameterIDs[0], m_scale);
}
MTS_DECLARE_CLASS()
private:
ref<const Texture> m_nested;
ref<Shader> m_nestedShader;
Float m_scale;
};
Shader *ConstantSpectrumTexture::createShader(Renderer *renderer) const {
return new ConstantSpectrumTextureShader(renderer, m_value);
}
@ -168,7 +224,9 @@ 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(Texture, true, ConfigurableObject)
MTS_IMPLEMENT_CLASS(Texture2D, true, Texture)
@ -176,4 +234,6 @@ 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

View File

@ -390,7 +390,7 @@ public:
// into doing correct texture filtering across the u=0 to u=1 seam.
<< " if (u < 0.1)" << endl
<< " return texture2D(" << evalName << "_texture, vec2(u+1.0, v)).rgb * " << evalName << "_intensityScale;" << endl
<< " else"
<< " else" << endl
<< " return texture2D(" << evalName << "_texture, vec2(u, v)).rgb * " << evalName << "_intensityScale;" << endl
<< "}" << endl;
}

View File

@ -17,7 +17,7 @@
*/
#include <mitsuba/render/scene.h>
#include <mitsuba/render/consttexture.h>
#include <mitsuba/render/texture.h>
#include <mitsuba/hw/gpuprogram.h>
MTS_NAMESPACE_BEGIN