documentation updates, fixed for many typos, fixed the bump map model

metadata
Wenzel Jakob 2011-07-15 18:37:48 +02:00
parent b5a6b7cbd8
commit 17eb2166f0
21 changed files with 414 additions and 44 deletions

View File

@ -20,6 +20,8 @@
\newcommand{\Vector}{\texttt{vector}}
\newcommand{\Point}{\texttt{point}}
\newcommand{\Texture}{\texttt{texture}}
\newcommand{\BSDF}{\texttt{bsdf}}
\newcommand{\Unnamed}{\emph{(Nested plugin)}}
\newcommand{\Or}{~~\small or \small}
\newcolumntype{P}[1]{>{\RaggedRight\hspace{0pt}}p{#1}}
\newcommand{\MtsVer}{\color{lstattrib}\texttt{"\MitsubaVersion"}}
@ -37,7 +39,7 @@
%\toprule
\\[-2.2ex]
\textbf{Parameter}&\textbf{Type}&\textbf{Description}\\
#1
#1\\[-4mm]
\end{tabular}}
\end{figure}
\setlength\fboxrule\fboxrulebackup

View File

@ -132,3 +132,15 @@
address = {Ithaca, NY, USA},
note = {\url{http://ecommons.library.cornell.edu/handle/1813/8331}}
}
@inproceedings{Blinn1978Simulation,
author = {Blinn, James F.},
title = {Simulation of wrinkled surfaces},
booktitle = {Proceedings of the 5th annual conference on Computer graphics and interactive techniques},
series = {SIGGRAPH '78},
year = {1978},
pages = {286--292},
publisher = {ACM},
address = {New York, NY, USA},
}

View File

@ -116,7 +116,8 @@ public:
*/
inline std::string toString() const {
if (m_ptr == NULL)
return "ref<null>[]";
return formatString("ref<%s>[null]",
T::m_theClass->getName().c_str());
else
return formatString("ref<%s>[ref=%i, ptr=%s]",
m_ptr->getClass()->getName().c_str(),

View File

@ -15,6 +15,7 @@ plugins += env.SharedLibrary('twosided', ['twosided.cpp'])
plugins += env.SharedLibrary('mask', ['mask.cpp'])
plugins += env.SharedLibrary('mixture', ['mixture.cpp'])
plugins += env.SharedLibrary('coating', ['coating.cpp'])
plugins += env.SharedLibrary('bump', ['bump.cpp'])
# Other materials
plugins += env.SharedLibrary('ward', ['ward.cpp'])

321
src/bsdfs/bump.cpp Normal file
View File

@ -0,0 +1,321 @@
/*
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/>.
*/
#include <mitsuba/render/scene.h>
#include <mitsuba/hw/basicshader.h>
MTS_NAMESPACE_BEGIN
/*! \plugin{bump}{Bump map}
*
* \parameters{
* \parameter{\Unnamed}{\Texture}{
* The luminance of this texture specifies the amount of
* displacement. The implementation ignores any constant
* offset---only changes in the luminance matter.
* }
* \parameter{\Unnamed}{\BSDF}{A BSDF model that should
* be affected by the bump map}
* }
*
* Bump mapping \cite{Blinn1978Simulation} is a simple technique for cheaply
* adding surface detail to a rendering. This is done by perturbing the
* shading coordinate frame based on a displacement height field provided
* as a texture. This method can lend objects a highly realistic and detailed
* appearance (e.g. wrinkled or covered by scratches and other imperfections)
* without requiring any changes to the input geometry.
*
* The implementation in Mitsuba uses the common approach of ignoring
* the normally negligible texture-space derivative of the base mesh
* surface normal. As side effect of this decision, it is invariant
* to constant offsets in the height field texture---only variations in
* its luminance cause changes to the shading frame.
*
* Note that the magnitude of the height field variations influences
* the strength of the displacement. If necessary, the \pluginref{scale}
* texture plugin can be used to magnify the scale of an existing bump map.
* \vspace{1cm}
* \begin{xml}[caption=A rough metal model with a scaled image-based bump map]
* <bsdf type="bump">
* <!-- The bump map is applied to a rough metal BRDF -->
* <bsdf type="roughconductor"/>
*
* <texture name="scale">
* <!-- The scale of the displacement gets multiplied by 10x -->
* <float name="scale" value="10"/>
*
* <texture name="bitmap">
* <string name="filename" value="bumpmap.png"/>
* </texture>
* </texture>
* </bsdf>
* \end{xml}
*/
class BumpMap : public BSDF {
public:
BumpMap(const Properties &props) : BSDF(props) { }
BumpMap(Stream *stream, InstanceManager *manager)
: BSDF(stream, manager) {
m_nested = static_cast<BSDF *>(manager->getInstance(stream));
m_displacement = static_cast<Texture *>(manager->getInstance(stream));
configure();
}
void configure() {
if (!m_nested)
Log(EError, "A child BSDF instance is required");
if (!m_displacement)
Log(EError, "A displacement texture must be specified");
m_components.clear();
for (int i=0; i<m_nested->getComponentCount(); ++i)
m_components.push_back(m_nested->getType(i) | ESpatiallyVarying | EAnisotropic);
m_usesRayDifferentials = true;
BSDF::configure();
}
void serialize(Stream *stream, InstanceManager *manager) const {
BSDF::serialize(stream, manager);
manager->serialize(stream, m_nested.get());
manager->serialize(stream, m_displacement.get());
}
void addChild(const std::string &name, ConfigurableObject *child) {
if (child->getClass()->derivesFrom(MTS_CLASS(BSDF))) {
if (m_nested != NULL)
Log(EError, "Only a single nested BSDF can be added!");
m_nested = static_cast<BSDF *>(child);
} else if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) {
if (m_displacement != NULL)
Log(EError, "Only a single displacement texture can be specified!");
m_displacement = static_cast<Texture *>(child);
} else {
BSDF::addChild(name, child);
}
}
void perturbIntersection(const Intersection &its, Intersection &target) const {
/* Determine the step size for the finite difference computation */
Float du = 0.5f * std::abs(its.dudx) + std::abs(its.dudy),
dv = 0.5f * std::abs(its.dvdx) + std::abs(its.dvdy);
if (du == 0) du = Epsilon;
if (dv == 0) dv = Epsilon;
/* Compute the U and V displacementment derivatives */
Float displacement, displacementU, displacementV;
target = its;
displacement = m_displacement->getValue(target).getLuminance();
target.p = its.p + its.dpdu * du;
target.uv = its.uv + Point2(du, 0);
displacementU = m_displacement->getValue(target).getLuminance();
target.p = its.p + its.dpdv * dv;
target.uv = its.uv + Point2(0, dv);
displacementV = m_displacement->getValue(target).getLuminance();
target.p = its.p;
target.uv = its.uv;
Float dDisplaceDu = (displacementU - displacement) / du;
Float dDisplaceDv = (displacementV - displacement) / dv;
/* Build a perturbed frame -- ignores the usually
negligible normal derivative term */
Vector dpdu = its.dpdu + its.shFrame.n * (
dDisplaceDu - dot(its.shFrame.n, its.dpdu));
Vector dpdv = its.dpdv + its.shFrame.n * (
dDisplaceDv - dot(its.shFrame.n, its.dpdv));
dpdu = normalize(dpdu);
dpdv = normalize(dpdv - dpdu * dot(dpdv, dpdu));
target.shFrame.s = dpdu;
target.shFrame.t = dpdv;
target.shFrame = Frame(Normal(cross(dpdv, dpdu)));
if (dot(target.shFrame.n, target.geoFrame.n) < 0)
target.shFrame.n *= -1;
}
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
const Intersection& its = bRec.its;
Intersection perturbed;
perturbIntersection(its, perturbed);
BSDFQueryRecord perturbedQuery(perturbed,
perturbed.toLocal(its.toWorld(bRec.wi)),
perturbed.toLocal(its.toWorld(bRec.wo)), bRec.quantity);
if (Frame::cosTheta(bRec.wo) * Frame::cosTheta(perturbedQuery.wo) <= 0)
return Spectrum(0.0f);
perturbedQuery.sampler = bRec.sampler;
perturbedQuery.typeMask = bRec.typeMask;
perturbedQuery.component = bRec.component;
return m_nested->eval(perturbedQuery, measure);
}
Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const {
const Intersection& its = bRec.its;
Intersection perturbed;
perturbIntersection(its, perturbed);
BSDFQueryRecord perturbedQuery(perturbed,
perturbed.toLocal(its.toWorld(bRec.wi)),
perturbed.toLocal(its.toWorld(bRec.wo)), bRec.quantity);
if (Frame::cosTheta(bRec.wo) * Frame::cosTheta(perturbedQuery.wo) <= 0)
return 0;
perturbedQuery.quantity = bRec.quantity;
perturbedQuery.sampler = bRec.sampler;
perturbedQuery.typeMask = bRec.typeMask;
perturbedQuery.component = bRec.component;
return m_nested->pdf(perturbedQuery, measure);
}
Spectrum sample(BSDFQueryRecord &bRec, Float &pdf, const Point2 &sample) const {
const Intersection& its = bRec.its;
Intersection perturbed;
perturbIntersection(its, perturbed);
BSDFQueryRecord perturbedQuery(perturbed, bRec.quantity);
perturbedQuery.wi = perturbed.toLocal(its.toWorld(bRec.wi));
perturbedQuery.sampler = bRec.sampler;
perturbedQuery.typeMask = bRec.typeMask;
perturbedQuery.component = bRec.component;
Spectrum result = m_nested->sample(perturbedQuery, pdf, sample);
if (!result.isZero()) {
bRec.sampledComponent = perturbedQuery.sampledComponent;
bRec.sampledType = perturbedQuery.sampledType;
bRec.wo = its.toLocal(perturbed.toWorld(perturbedQuery.wo));
if (Frame::cosTheta(bRec.wo) * Frame::cosTheta(perturbedQuery.wo) <= 0)
return Spectrum(0.0f);
}
return result;
}
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
const Intersection& its = bRec.its;
Intersection perturbed;
perturbIntersection(its, perturbed);
BSDFQueryRecord perturbedQuery(perturbed, bRec.quantity);
perturbedQuery.wi = perturbed.toLocal(its.toWorld(bRec.wi));
perturbedQuery.sampler = bRec.sampler;
perturbedQuery.typeMask = bRec.typeMask;
perturbedQuery.component = bRec.component;
Spectrum result = m_nested->sample(perturbedQuery, sample);
if (!result.isZero()) {
bRec.sampledComponent = perturbedQuery.sampledComponent;
bRec.sampledType = perturbedQuery.sampledType;
bRec.wo = its.toLocal(perturbed.toWorld(perturbedQuery.wo));
if (Frame::cosTheta(bRec.wo) * Frame::cosTheta(perturbedQuery.wo) <= 0)
return Spectrum(0.0f);
}
return result;
}
Shader *createShader(Renderer *renderer) const;
std::string toString() const {
std::ostringstream oss;
oss << "BumpMap[" << endl
<< " name = \"" << getName() << "\"," << endl
<< " displacement = " << indent(m_displacement->toString()) << endl
<< " nested = " << indent(m_nested->toString()) << endl
<< "]";
return oss.str();
}
MTS_DECLARE_CLASS()
protected:
ref<Texture> m_displacement;
ref<BSDF> m_nested;
};
// ================ Hardware shader implementation ================
/**
* This is a quite approximate version of the bump map model -- it likely
* won't match the reference exactly, but it should be good enough for
* preview purposes
*/
class BumpMapShader : public Shader {
public:
BumpMapShader(Renderer *renderer, const BSDF *nested, const Texture *displacement)
: Shader(renderer, EBSDFShader), m_nested(nested), m_displacement(displacement) {
m_nestedShader = renderer->registerShaderForResource(m_nested.get());
m_displacementShader = renderer->registerShaderForResource(m_displacement.get());
}
bool isComplete() const {
return m_nestedShader.get() != NULL;
}
void cleanup(Renderer *renderer) {
renderer->unregisterShaderForResource(m_nested.get());
renderer->unregisterShaderForResource(m_displacement.get());
}
void putDependencies(std::vector<Shader *> &deps) {
deps.push_back(m_nestedShader.get());
deps.push_back(m_displacementShader.get());
}
void generateCode(std::ostringstream &oss,
const std::string &evalName,
const std::vector<std::string> &depNames) const {
oss << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
<< " float du = abs(dFdx(uv.x)), dv = abs(dFdx(uv.y));" << endl
<< " if (du == 0.0) du = 0.001;" << endl
<< " if (dv == 0.0) dv = 0.001;" << endl
<< " float displacement = " << depNames[1] << "(uv)[0];" << endl
<< " float displacementU = " << depNames[1] << "(uv + vec2(du, 0.0))[0];" << endl
<< " float displacementV = " << depNames[1] << "(uv + vec2(0.0, dv))[0];" << endl
<< " float dfdu = (displacementU - displacement)/du;" << endl
<< " float dfdv = (displacementV - displacement)/dv;" << endl
<< " vec3 dpdu = normalize(vec3(1.0, 0.0, dfdu));" << endl
<< " vec3 dpdv = vec3(0.0, 1.0, dfdv);" << endl
<< " dpdv = normalize(dpdv - dot(dpdu, dpdv)*dpdu);" << endl
<< " vec3 n = cross(dpdu, dpdv);" << endl
<< " wi = vec3(dot(wi, dpdu), dot(wi, dpdv), dot(wi, n));" << endl
<< " wo = vec3(dot(wo, dpdu), dot(wo, dpdv), dot(wo, n));" << endl
<< " return " << depNames[0] << "(uv, wi, wo);" << endl
<< "}" << endl
<< endl
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
<< " return " << depNames[0] << "_diffuse(uv, wi, wo);" << endl
<< "}" << endl;
}
MTS_DECLARE_CLASS()
private:
ref<const BSDF> m_nested;
ref<const Texture> m_displacement;
ref<Shader> m_nestedShader;
ref<Shader> m_displacementShader;
};
Shader *BumpMap::createShader(Renderer *renderer) const {
return new BumpMapShader(renderer, m_nested.get(), m_displacement.get());
}
MTS_IMPLEMENT_CLASS(BumpMapShader, false, Shader)
MTS_IMPLEMENT_CLASS_S(BumpMap, false, BSDF)
MTS_EXPORT_PLUGIN(BumpMap, "Smooth dielectric coating");
MTS_NAMESPACE_END

View File

@ -30,8 +30,9 @@ MTS_NAMESPACE_BEGIN
* numerically or using a known material name. \default{\texttt{bk7} / 1.5046}}
* \parameter{extIOR}{\Float\Or\String}{Exterior index of refraction specified
* numerically or using a known material name. \default{\texttt{air} / 1.000277}}
* \parameter{thickness}{\Float}{Denotes the thickness of the absorbing layer (given in inverse units of \code{sigmaA})\default{1}}
* \parameter{thickness}{\Float}{Denotes the thickness of the layer (to model absorption --- should be specified in inverse units of \code{sigmaA})\default{1}}
* \parameter{sigmaA}{\Spectrum\Or\Texture}{The absorption coefficient of the coating layer. \default{0, i.e. there is no absorption}}
* \parameter{\Unnamed}{\BSDF}{A nested BSDF model that should be coated.}
* }
*
* \renderings{

View File

@ -37,7 +37,8 @@ MTS_NAMESPACE_BEGIN
* \default{1.0}}
* }
* \renderings{
* \rendering{Measured copper material (the default)}
* \rendering{Measured copper material (the default), rendered using 30
* spectral samples between 360 and 830$nm$}
* {bsdf_conductor_copper.jpg}
* \rendering{Measured gold material (\lstref{conductor-gold})}
* {bsdf_conductor_gold.jpg}
@ -45,14 +46,14 @@ MTS_NAMESPACE_BEGIN
*
* This plugin implements a perfectly smooth interface to a conducting material,
* such as a metal. For a similar model that instead describes a rough surface
* microstructure, take a look at the seperately available
* microstructure, take a look at the separately available
* \pluginref{roughconductor} plugin.
* In contrast to dielectric materials, conductors do not transmit
* any light. Their index of refraction is complex-valued and tends to undergo
* considerable changes throughout the visible color spectrum.
*
* To faciliate the tedious task of specifying spectrally-varying index of
* To facilitate the tedious task of specifying spectrally-varying index of
* refraction information, Mitsuba ships with a set of measured data for
* several materials, where visible-spectrum information was publicly
* available\footnote{
@ -69,7 +70,7 @@ MTS_NAMESPACE_BEGIN
* be used with this plugin, though note that the plugin will ignore any
* refraction component that the actual material might have had.
* The table also contains a few birefingent materials, which are split into
* separate measurements correponding to their two indices of
* separate measurements corresponding to their two indices of
* refraction (named ``ordinary'' and ``extraordinary ray'').
*
* When using this plugin, you should ideally compile Mitsuba with support for

View File

@ -65,7 +65,7 @@ MTS_NAMESPACE_BEGIN
* \end{xml}
*
* When using this model, it is crucial that the scene contains
* meaningful and mutally compatible indices of refraction changes---see
* meaningful and mutually compatible indices of refraction changes---see
* \figref{glass-explanation} for a description of what this entails.
*
* In many cases, we will want to additionally describe the \emph{medium} within a
@ -83,8 +83,8 @@ MTS_NAMESPACE_BEGIN
* </bsdf>
*
* <medium type="homogeneous" name="interior">
* <rgb name="sigmaS" value="0, 0, 0"/>
* <rgb name="sigmaA" value="4, 4, 2"/>
* <rgb name="sigmaS" value="0, 0, 0"/>
* <rgb name="sigmaA" value="4, 4, 2"/>
* </medium>
* <shape>
* \end{xml}

View File

@ -26,6 +26,8 @@ MTS_NAMESPACE_BEGIN
* \parameter{opacity}{\Spectrum\Or\Texture}{
* Specifies the per-channel opacity (where $1=$ completely transparent)\default{0.5}.
* }
* \parameter{\Unnamed}{\BSDF}{A base BSDF model that represents the
* non-transparent portion of the scattering}
* }
* \renderings{
* \rendering{Rendering without an opacity mask}
@ -37,7 +39,7 @@ MTS_NAMESPACE_BEGIN
* between perfectly transparent and completely opaque based on the \code{opacity}
* parameter.
*
* The transparency is implemented as a forward-facing Diract delta distribution.
* The transparency is implemented as a forward-facing Dirac delta distribution.
* \vspace{5mm}
*
* \begin{xml}[caption=Material configuration for a transparent leaf,

View File

@ -26,6 +26,8 @@ MTS_NAMESPACE_BEGIN
*
* \parameters{
* \parameter{weights}{\String}{A comma-separated list of BSDF weights}
* \parameter{\Unnamed}{\BSDF}{Multiple BSDF instances that should be
* mixed according to the specified weights}
* }
* \renderings{
* \rendering{An admittedly not particularly realistic linear combination of
@ -37,7 +39,7 @@ MTS_NAMESPACE_BEGIN
* model in Mitsuba (be it smooth, rough, reflecting, or transmitting) can
* be mixed with others in this manner to synthesize new models. There
* is no limit on how many models can be mixed, but their combination
* weights must be nonnegative and sum to less than one to ensure
* weights must be non-negative and sum to a value of one or less to ensure
* energy balance.
*
* \vspace{4mm}

View File

@ -46,7 +46,7 @@ MTS_NAMESPACE_BEGIN
* \end{enumerate}
* }
* \parameter{alpha}{\Float\Or\Texture}{
* Specifies the roughness of the unresolved surface microgeometry.
* Specifies the roughness of the unresolved surface micro-geometry.
* When the Beckmann distribution is used, this parameter is equal to the
* \emph{root mean square} (RMS) slope of the microfacets. This
* parameter is only valid when \texttt{distribution=beckmann/phong/ggx}.
@ -97,7 +97,7 @@ MTS_NAMESPACE_BEGIN
* for Refraction through Rough Surfaces'' by Walter et al.
* \cite{Walter07Microfacet}. It supports several different types of microfacet
* distributions and has a texturable roughness parameter.
* To faciliate the tedious task of specifying spectrally-varying index of
* To facilitate the tedious task of specifying spectrally-varying index of
* refraction information, this plugin can access a set of measured materials
* for which visible-spectrum information was publicly available
* (see \tblref{conductor-iors} for the full list).
@ -114,7 +114,7 @@ MTS_NAMESPACE_BEGIN
* and $\alpha=0.3-0.7$ is \emph{extremely} rough (e.g. an etched or ground
* finish). Values significantly above that are probably not too realistic.
* \vspace{-6mm}
* \subsubsection*{Techical details}\vspace{-2mm}
* \subsubsection*{Technical details}\vspace{-2mm}
* When rendering with the Ashikhmin-Shirley or Phong microfacet
* distributions, a conversion is used to turn the specified
* $\alpha$ roughness value into the exponents of these distributions.

View File

@ -52,7 +52,7 @@ MTS_NAMESPACE_BEGIN
* \end{enumerate}
* }
* \parameter{alpha}{\Float\Or\Texture}{
* Specifies the roughness of the unresolved surface microgeometry.
* Specifies the roughness of the unresolved surface micro-geometry.
* When the Beckmann distribution is used, this parameter is equal to the
* \emph{root mean square} (RMS) slope of the microfacets. This
* parameter is only valid when \texttt{distribution=beckmann/phong/ggx}.
@ -115,7 +115,7 @@ MTS_NAMESPACE_BEGIN
* finish).
*
* Please note that when using this plugin, it is crucial that the scene contains
* meaningful and mutally compatible index of refraction changes---see
* meaningful and mutually compatible index of refraction changes---see
* \figref{glass-explanation} for an example of what this entails. Also, note that
* the importance sampling implementation of this model is close, but
* not always a perfect a perfect match to the underlying scattering distribution,
@ -123,7 +123,7 @@ MTS_NAMESPACE_BEGIN
* microfacet distribution is used. Hence, such renderings may
* converge slowly.
*
* \subsubsection*{Techical details}
* \subsubsection*{Technical details}
* When rendering with the Ashikhmin-Shirley or Phong microfacet
* distributions, a conversion is used to turn the specified
* $\alpha$ roughness value into the exponents of these distributions.

View File

@ -29,7 +29,7 @@ MTS_NAMESPACE_BEGIN
* material. \default{0.5}
* }
* \parameter{alpha}{\Spectrum\Or\Texture}{
* Specifies the roughness of the unresolved surface microgeometry
* Specifies the roughness of the unresolved surface micro-geometry
* using the \emph{root mean square} (RMS) slope of the
* microfacets. \default{0.2}
* }
@ -64,9 +64,9 @@ MTS_NAMESPACE_BEGIN
* to Lambertian scattering, which does not take surface roughness into account.
*
* The implementation in Mitsuba uses a surface roughness parameter $\alpha$ that
* is slighly different from the slope-area variance in the original 1994 paper.
* is slightly different from the slope-area variance in the original 1994 paper.
* The reason for this change is to make the parameter $\alpha$ portable
* across different models (i.e. \pluginref{roughglass}, \pluginref{roughplastic},
* across different models (i.e. \pluginref{roughdielectric}, \pluginref{roughplastic},
* \pluginref{roughconductor}).
*
* To get an intuition about the effect of the

View File

@ -47,7 +47,7 @@ MTS_NAMESPACE_BEGIN
* \end{enumerate}
* }
* \parameter{alpha}{\Float}{
* Specifies the roughness of the unresolved surface microgeometry.
* Specifies the roughness of the unresolved surface micro-geometry.
* When the Beckmann distribution is used, this parameter is equal to the
* \emph{root mean square} (RMS) slope of the microfacets.
* \default{0.1}.

View File

@ -23,6 +23,11 @@
MTS_NAMESPACE_BEGIN
/*!\plugin{twosided}{Two-sided BRDF adapter}
* \parameters{
* \parameter{\Unnamed}{\BSDF}{A nested BRDF that should
* be turned into a two-sided scattering model.}
* }
*
* \renderings{
* \unframedrendering{From this angle, the Cornell box scene shows visible back-facing geometry}
* {bsdf_twosided_before}

View File

@ -85,7 +85,7 @@ Texture *BSDF::ensureEnergyConservation(Texture *texture,
<< "to the BSDF to prevent this from happening.";
Log(EWarn, "%s", oss.str().c_str());
Properties props("scale");
props.setFloat("value", scale);
props.setFloat("scale", scale);
Texture *scaleTexture = static_cast<Texture *> (PluginManager::getInstance()->
createObject(MTS_CLASS(Texture), props));
scaleTexture->addChild("", texture);
@ -150,7 +150,9 @@ static std::string typeMaskToString(unsigned int typeMask) {
if (isset(BSDF::EFrontSide)) { oss << "frontSide "; typeMask &= ~BSDF::EFrontSide; }
if (isset(BSDF::EBackSide)) { oss << "backSide "; typeMask &= ~BSDF::EBackSide; }
if (isset(BSDF::ECanUseSampler)) { oss << "canUseSampler "; typeMask &= ~BSDF::ECanUseSampler; }
if (isset(BSDF::ESpatiallyVarying)) { oss << "spatiallyVarying"; typeMask &= ~BSDF::ESpatiallyVarying; }
#undef isset
SAssert(typeMask == 0);
oss << "}";
return oss.str();
}

View File

@ -78,18 +78,22 @@ std::string Intersection::toString() const {
if (!isValid())
return "Intersection[invalid]";
std::ostringstream oss;
oss << "Intersection[" << std::endl
<< " p = " << p.toString() << "," << std::endl
<< " wi = " << wi.toString() << "," << std::endl
<< " t = " << t << "," << std::endl
<< " geoFrame = " << indent(geoFrame.toString()) << "," << std::endl
<< " shFrame = " << indent(shFrame.toString()) << "," << std::endl
<< " uv = " << uv.toString() << "," << std::endl
<< " hasUVPartials = " << hasUVPartials << "," << std::endl
<< " dpdu = " << dpdu.toString() << "," << std::endl
<< " dpdv = " << dpdv.toString() << "," << std::endl
<< " time = " << time << "," << std::endl
<< " shape = " << indent(((Object *)shape)->toString()) << std::endl
oss << "Intersection[" << endl
<< " p = " << p.toString() << "," << endl
<< " wi = " << wi.toString() << "," << endl
<< " t = " << t << "," << endl
<< " geoFrame = " << indent(geoFrame.toString()) << "," << endl
<< " shFrame = " << indent(shFrame.toString()) << "," << endl
<< " uv = " << uv.toString() << "," << endl
<< " hasUVPartials = " << hasUVPartials << "," << endl
<< " dpdu = " << dpdu.toString() << "," << endl
<< " dpdv = " << dpdv.toString() << "," << endl;
if (hasUVPartials) {
oss << " dud[x,y] = [" << dudx << ", " << dudy << "]," << endl
<< " dvd[x,y] = [" << dvdx << ", " << dvdy << "]," << endl;
}
oss << " time = " << time << "," << endl
<< " shape = " << indent(((Object *)shape)->toString()) << endl
<< "]";
return oss.str();
}

View File

@ -28,6 +28,7 @@
#include <mitsuba/render/renderjob.h>
#include <mitsuba/core/timer.h>
#include <mitsuba/core/mstream.h>
#include <mitsuba/core/fstream.h>
#include <mitsuba/hw/font.h>
GLWidget::GLWidget(QWidget *parent) :
@ -1060,6 +1061,14 @@ void GLWidget::paintGL() {
m_luminanceProgram->unbind();
buffer->unbind();
m_luminanceBuffer[0]->releaseTarget();
#if 0
/* For debugging .. */
ref<Bitmap> bitmap = new Bitmap(size.x, size.y, 128);
m_luminanceBuffer[0]->download(bitmap);
ref<FileStream> fs = new FileStream("test.exr", FileStream::ETruncReadWrite);
bitmap->save(Bitmap::EEXR, fs);
fs->close();
#endif
/* Iteratively downsample the image until left with a 1x1 pixel sum over
the whole image */

View File

@ -1314,13 +1314,15 @@ void MainWindow::onExportDialogClose(int reason) {
for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x) {
Spectrum spec;
spec.fromLinearRGB(source[(y*width+x)*4+0], source[(y*width+x)*4+1], source[(y*width+x)*4+2]);
spec.fromLinearRGB(source[(y*width+x)*4+0],
source[(y*width+x)*4+1], source[(y*width+x)*4+2]);
avgLogLuminance += std::log(0.001f+spec.getLuminance());
}
}
avgLogLuminance = std::exp(avgLogLuminance/(width*height));
reinhardKey = ctx->reinhardKey / avgLogLuminance;
}
for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x) {

View File

@ -99,15 +99,20 @@ public:
: m_bsdf(bsdf), m_sampler(sampler), m_wi(wi), m_component(component),
m_largestWeight(0), m_passSamplerToBSDF(passSamplerToBSDF) {
m_fakeSampler = new FakeSampler(m_sampler);
m_its.uv = Point2(0.0f);
m_its.dpdu = Vector(1, 0, 0);
m_its.dpdv = Vector(0, 1, 0);
m_its.dudx = m_its.dvdy = 0.01f;
m_its.dudy = m_its.dvdx = 0.00f;
m_its.shFrame = Frame(Normal(0, 0, 1));
}
boost::tuple<Vector, Float, EMeasure> generateSample() {
Point2 sample(m_sampler->next2D());
Intersection its;
BSDFQueryRecord bRec(its);
BSDFQueryRecord bRec(m_its);
bRec.component = m_component;
bRec.wi = m_wi;
#if defined(MTS_DEBUG_FP)
enableFPExceptions();
#endif
@ -187,8 +192,7 @@ public:
}
Float pdf(const Vector &wo, EMeasure measure) {
Intersection its;
BSDFQueryRecord bRec(its);
BSDFQueryRecord bRec(m_its);
bRec.component = m_component;
bRec.wi = m_wi;
bRec.wo = wo;
@ -212,6 +216,7 @@ public:
inline Float getLargestWeight() const { return m_largestWeight; }
private:
Intersection m_its;
ref<const BSDF> m_bsdf;
ref<Sampler> m_sampler;
ref<FakeSampler> m_fakeSampler;

View File

@ -31,10 +31,10 @@ MTS_NAMESPACE_BEGIN
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));
if (props.hasProperty("scale") && props.getType("scale") == Properties::EFloat)
m_scale = Spectrum(props.getFloat("scale", 1.0f));
else
m_scale = props.getSpectrum("value", Spectrum(1.0f));
m_scale = props.getSpectrum("scale", Spectrum(1.0f));
}
ScalingTexture(Stream *stream, InstanceManager *manager)