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

View File

@ -132,3 +132,15 @@
address = {Ithaca, NY, USA}, address = {Ithaca, NY, USA},
note = {\url{http://ecommons.library.cornell.edu/handle/1813/8331}} 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 { inline std::string toString() const {
if (m_ptr == NULL) if (m_ptr == NULL)
return "ref<null>[]"; return formatString("ref<%s>[null]",
T::m_theClass->getName().c_str());
else else
return formatString("ref<%s>[ref=%i, ptr=%s]", return formatString("ref<%s>[ref=%i, ptr=%s]",
m_ptr->getClass()->getName().c_str(), 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('mask', ['mask.cpp'])
plugins += env.SharedLibrary('mixture', ['mixture.cpp']) plugins += env.SharedLibrary('mixture', ['mixture.cpp'])
plugins += env.SharedLibrary('coating', ['coating.cpp']) plugins += env.SharedLibrary('coating', ['coating.cpp'])
plugins += env.SharedLibrary('bump', ['bump.cpp'])
# Other materials # Other materials
plugins += env.SharedLibrary('ward', ['ward.cpp']) 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}} * numerically or using a known material name. \default{\texttt{bk7} / 1.5046}}
* \parameter{extIOR}{\Float\Or\String}{Exterior index of refraction specified * \parameter{extIOR}{\Float\Or\String}{Exterior index of refraction specified
* numerically or using a known material name. \default{\texttt{air} / 1.000277}} * 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{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{ * \renderings{

View File

@ -37,7 +37,8 @@ MTS_NAMESPACE_BEGIN
* \default{1.0}} * \default{1.0}}
* } * }
* \renderings{ * \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} * {bsdf_conductor_copper.jpg}
* \rendering{Measured gold material (\lstref{conductor-gold})} * \rendering{Measured gold material (\lstref{conductor-gold})}
* {bsdf_conductor_gold.jpg} * {bsdf_conductor_gold.jpg}
@ -45,14 +46,14 @@ MTS_NAMESPACE_BEGIN
* *
* This plugin implements a perfectly smooth interface to a conducting material, * 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 * 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. * \pluginref{roughconductor} plugin.
* In contrast to dielectric materials, conductors do not transmit * In contrast to dielectric materials, conductors do not transmit
* any light. Their index of refraction is complex-valued and tends to undergo * any light. Their index of refraction is complex-valued and tends to undergo
* considerable changes throughout the visible color spectrum. * 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 * refraction information, Mitsuba ships with a set of measured data for
* several materials, where visible-spectrum information was publicly * several materials, where visible-spectrum information was publicly
* available\footnote{ * available\footnote{
@ -69,7 +70,7 @@ MTS_NAMESPACE_BEGIN
* be used with this plugin, though note that the plugin will ignore any * be used with this plugin, though note that the plugin will ignore any
* refraction component that the actual material might have had. * refraction component that the actual material might have had.
* The table also contains a few birefingent materials, which are split into * 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''). * refraction (named ``ordinary'' and ``extraordinary ray'').
* *
* When using this plugin, you should ideally compile Mitsuba with support for * When using this plugin, you should ideally compile Mitsuba with support for

View File

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

View File

@ -26,6 +26,8 @@ MTS_NAMESPACE_BEGIN
* \parameter{opacity}{\Spectrum\Or\Texture}{ * \parameter{opacity}{\Spectrum\Or\Texture}{
* Specifies the per-channel opacity (where $1=$ completely transparent)\default{0.5}. * 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{ * \renderings{
* \rendering{Rendering without an opacity mask} * \rendering{Rendering without an opacity mask}
@ -37,7 +39,7 @@ MTS_NAMESPACE_BEGIN
* between perfectly transparent and completely opaque based on the \code{opacity} * between perfectly transparent and completely opaque based on the \code{opacity}
* parameter. * 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} * \vspace{5mm}
* *
* \begin{xml}[caption=Material configuration for a transparent leaf, * \begin{xml}[caption=Material configuration for a transparent leaf,

View File

@ -26,6 +26,8 @@ MTS_NAMESPACE_BEGIN
* *
* \parameters{ * \parameters{
* \parameter{weights}{\String}{A comma-separated list of BSDF weights} * \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{ * \renderings{
* \rendering{An admittedly not particularly realistic linear combination of * \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 * model in Mitsuba (be it smooth, rough, reflecting, or transmitting) can
* be mixed with others in this manner to synthesize new models. There * 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 * 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. * energy balance.
* *
* \vspace{4mm} * \vspace{4mm}

View File

@ -46,7 +46,7 @@ MTS_NAMESPACE_BEGIN
* \end{enumerate} * \end{enumerate}
* } * }
* \parameter{alpha}{\Float\Or\Texture}{ * \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 * When the Beckmann distribution is used, this parameter is equal to the
* \emph{root mean square} (RMS) slope of the microfacets. This * \emph{root mean square} (RMS) slope of the microfacets. This
* parameter is only valid when \texttt{distribution=beckmann/phong/ggx}. * 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. * for Refraction through Rough Surfaces'' by Walter et al.
* \cite{Walter07Microfacet}. It supports several different types of microfacet * \cite{Walter07Microfacet}. It supports several different types of microfacet
* distributions and has a texturable roughness parameter. * 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 * refraction information, this plugin can access a set of measured materials
* for which visible-spectrum information was publicly available * for which visible-spectrum information was publicly available
* (see \tblref{conductor-iors} for the full list). * (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 * 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. * finish). Values significantly above that are probably not too realistic.
* \vspace{-6mm} * \vspace{-6mm}
* \subsubsection*{Techical details}\vspace{-2mm} * \subsubsection*{Technical details}\vspace{-2mm}
* When rendering with the Ashikhmin-Shirley or Phong microfacet * When rendering with the Ashikhmin-Shirley or Phong microfacet
* distributions, a conversion is used to turn the specified * distributions, a conversion is used to turn the specified
* $\alpha$ roughness value into the exponents of these distributions. * $\alpha$ roughness value into the exponents of these distributions.

View File

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

View File

@ -29,7 +29,7 @@ MTS_NAMESPACE_BEGIN
* material. \default{0.5} * material. \default{0.5}
* } * }
* \parameter{alpha}{\Spectrum\Or\Texture}{ * \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 * using the \emph{root mean square} (RMS) slope of the
* microfacets. \default{0.2} * microfacets. \default{0.2}
* } * }
@ -64,9 +64,9 @@ MTS_NAMESPACE_BEGIN
* to Lambertian scattering, which does not take surface roughness into account. * to Lambertian scattering, which does not take surface roughness into account.
* *
* The implementation in Mitsuba uses a surface roughness parameter $\alpha$ that * 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 * 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}). * \pluginref{roughconductor}).
* *
* To get an intuition about the effect of the * To get an intuition about the effect of the

View File

@ -47,7 +47,7 @@ MTS_NAMESPACE_BEGIN
* \end{enumerate} * \end{enumerate}
* } * }
* \parameter{alpha}{\Float}{ * \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 * When the Beckmann distribution is used, this parameter is equal to the
* \emph{root mean square} (RMS) slope of the microfacets. * \emph{root mean square} (RMS) slope of the microfacets.
* \default{0.1}. * \default{0.1}.

View File

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

View File

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

View File

@ -78,18 +78,22 @@ std::string Intersection::toString() const {
if (!isValid()) if (!isValid())
return "Intersection[invalid]"; return "Intersection[invalid]";
std::ostringstream oss; std::ostringstream oss;
oss << "Intersection[" << std::endl oss << "Intersection[" << endl
<< " p = " << p.toString() << "," << std::endl << " p = " << p.toString() << "," << endl
<< " wi = " << wi.toString() << "," << std::endl << " wi = " << wi.toString() << "," << endl
<< " t = " << t << "," << std::endl << " t = " << t << "," << endl
<< " geoFrame = " << indent(geoFrame.toString()) << "," << std::endl << " geoFrame = " << indent(geoFrame.toString()) << "," << endl
<< " shFrame = " << indent(shFrame.toString()) << "," << std::endl << " shFrame = " << indent(shFrame.toString()) << "," << endl
<< " uv = " << uv.toString() << "," << std::endl << " uv = " << uv.toString() << "," << endl
<< " hasUVPartials = " << hasUVPartials << "," << std::endl << " hasUVPartials = " << hasUVPartials << "," << endl
<< " dpdu = " << dpdu.toString() << "," << std::endl << " dpdu = " << dpdu.toString() << "," << endl
<< " dpdv = " << dpdv.toString() << "," << std::endl << " dpdv = " << dpdv.toString() << "," << endl;
<< " time = " << time << "," << std::endl if (hasUVPartials) {
<< " shape = " << indent(((Object *)shape)->toString()) << std::endl 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(); return oss.str();
} }

View File

@ -28,6 +28,7 @@
#include <mitsuba/render/renderjob.h> #include <mitsuba/render/renderjob.h>
#include <mitsuba/core/timer.h> #include <mitsuba/core/timer.h>
#include <mitsuba/core/mstream.h> #include <mitsuba/core/mstream.h>
#include <mitsuba/core/fstream.h>
#include <mitsuba/hw/font.h> #include <mitsuba/hw/font.h>
GLWidget::GLWidget(QWidget *parent) : GLWidget::GLWidget(QWidget *parent) :
@ -1060,6 +1061,14 @@ void GLWidget::paintGL() {
m_luminanceProgram->unbind(); m_luminanceProgram->unbind();
buffer->unbind(); buffer->unbind();
m_luminanceBuffer[0]->releaseTarget(); 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 /* Iteratively downsample the image until left with a 1x1 pixel sum over
the whole image */ the whole image */

View File

@ -1314,13 +1314,15 @@ void MainWindow::onExportDialogClose(int reason) {
for (int y=0; y<height; ++y) { for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x) { for (int x=0; x<width; ++x) {
Spectrum spec; 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::log(0.001f+spec.getLuminance());
} }
} }
avgLogLuminance = std::exp(avgLogLuminance/(width*height)); avgLogLuminance = std::exp(avgLogLuminance/(width*height));
reinhardKey = ctx->reinhardKey / avgLogLuminance; reinhardKey = ctx->reinhardKey / avgLogLuminance;
} }
for (int y=0; y<height; ++y) { for (int y=0; y<height; ++y) {
for (int x=0; x<width; ++x) { 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_bsdf(bsdf), m_sampler(sampler), m_wi(wi), m_component(component),
m_largestWeight(0), m_passSamplerToBSDF(passSamplerToBSDF) { m_largestWeight(0), m_passSamplerToBSDF(passSamplerToBSDF) {
m_fakeSampler = new FakeSampler(m_sampler); 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() { boost::tuple<Vector, Float, EMeasure> generateSample() {
Point2 sample(m_sampler->next2D()); Point2 sample(m_sampler->next2D());
Intersection its; BSDFQueryRecord bRec(m_its);
BSDFQueryRecord bRec(its);
bRec.component = m_component; bRec.component = m_component;
bRec.wi = m_wi; bRec.wi = m_wi;
#if defined(MTS_DEBUG_FP) #if defined(MTS_DEBUG_FP)
enableFPExceptions(); enableFPExceptions();
#endif #endif
@ -187,8 +192,7 @@ public:
} }
Float pdf(const Vector &wo, EMeasure measure) { Float pdf(const Vector &wo, EMeasure measure) {
Intersection its; BSDFQueryRecord bRec(m_its);
BSDFQueryRecord bRec(its);
bRec.component = m_component; bRec.component = m_component;
bRec.wi = m_wi; bRec.wi = m_wi;
bRec.wo = wo; bRec.wo = wo;
@ -212,6 +216,7 @@ public:
inline Float getLargestWeight() const { return m_largestWeight; } inline Float getLargestWeight() const { return m_largestWeight; }
private: private:
Intersection m_its;
ref<const BSDF> m_bsdf; ref<const BSDF> m_bsdf;
ref<Sampler> m_sampler; ref<Sampler> m_sampler;
ref<FakeSampler> m_fakeSampler; ref<FakeSampler> m_fakeSampler;

View File

@ -31,10 +31,10 @@ MTS_NAMESPACE_BEGIN
class ScalingTexture : public Texture { class ScalingTexture : public Texture {
public: public:
ScalingTexture(const Properties &props) : Texture(props) { ScalingTexture(const Properties &props) : Texture(props) {
if (props.hasProperty("value") && props.getType("value") == Properties::EFloat) if (props.hasProperty("scale") && props.getType("scale") == Properties::EFloat)
m_scale = Spectrum(props.getFloat("value", 1.0f)); m_scale = Spectrum(props.getFloat("scale", 1.0f));
else else
m_scale = props.getSpectrum("value", Spectrum(1.0f)); m_scale = props.getSpectrum("scale", Spectrum(1.0f));
} }
ScalingTexture(Stream *stream, InstanceManager *manager) ScalingTexture(Stream *stream, InstanceManager *manager)