From 17eb2166f04fe7b93d005ccca8e37055ddc33c57 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Fri, 15 Jul 2011 18:37:48 +0200 Subject: [PATCH] documentation updates, fixed for many typos, fixed the bump map model --- doc/macros.sty | 4 +- doc/main.bib | 12 ++ include/mitsuba/core/ref.h | 3 +- src/bsdfs/SConscript | 1 + src/bsdfs/bump.cpp | 321 +++++++++++++++++++++++++++++++++ src/bsdfs/coating.cpp | 3 +- src/bsdfs/conductor.cpp | 9 +- src/bsdfs/dielectric.cpp | 6 +- src/bsdfs/mask.cpp | 4 +- src/bsdfs/mixture.cpp | 4 +- src/bsdfs/roughconductor.cpp | 6 +- src/bsdfs/roughdielectric.cpp | 6 +- src/bsdfs/roughdiffuse.cpp | 6 +- src/bsdfs/roughplastic.cpp | 2 +- src/bsdfs/twosided.cpp | 5 + src/librender/bsdf.cpp | 4 +- src/librender/intersection.cpp | 28 +-- src/qtgui/glwidget.cpp | 9 + src/qtgui/mainwindow.cpp | 4 +- src/tests/test_chisquare.cpp | 15 +- src/textures/scale.cpp | 6 +- 21 files changed, 414 insertions(+), 44 deletions(-) create mode 100644 src/bsdfs/bump.cpp diff --git a/doc/macros.sty b/doc/macros.sty index 4866c190..49ace58e 100644 --- a/doc/macros.sty +++ b/doc/macros.sty @@ -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 diff --git a/doc/main.bib b/doc/main.bib index 5d54d139..f027bd1f 100644 --- a/doc/main.bib +++ b/doc/main.bib @@ -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}, +} + diff --git a/include/mitsuba/core/ref.h b/include/mitsuba/core/ref.h index b6a56a80..777b507a 100644 --- a/include/mitsuba/core/ref.h +++ b/include/mitsuba/core/ref.h @@ -116,7 +116,8 @@ public: */ inline std::string toString() const { if (m_ptr == NULL) - return "ref[]"; + 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(), diff --git a/src/bsdfs/SConscript b/src/bsdfs/SConscript index 064f0e40..01bfb949 100644 --- a/src/bsdfs/SConscript +++ b/src/bsdfs/SConscript @@ -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']) diff --git a/src/bsdfs/bump.cpp b/src/bsdfs/bump.cpp new file mode 100644 index 00000000..f962c503 --- /dev/null +++ b/src/bsdfs/bump.cpp @@ -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 . +*/ + +#include +#include + +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] + * + * + * + * + * + * + * + * + * + * + * + * + * + * \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(manager->getInstance(stream)); + m_displacement = static_cast(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; igetComponentCount(); ++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(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(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 m_displacement; + ref 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 &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 &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 m_nested; + ref m_displacement; + ref m_nestedShader; + ref 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 diff --git a/src/bsdfs/coating.cpp b/src/bsdfs/coating.cpp index 25e39c27..1f7a4a1b 100644 --- a/src/bsdfs/coating.cpp +++ b/src/bsdfs/coating.cpp @@ -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{ diff --git a/src/bsdfs/conductor.cpp b/src/bsdfs/conductor.cpp index 7c4e30e6..3d2510e0 100644 --- a/src/bsdfs/conductor.cpp +++ b/src/bsdfs/conductor.cpp @@ -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 diff --git a/src/bsdfs/dielectric.cpp b/src/bsdfs/dielectric.cpp index ee9485dc..c1617231 100644 --- a/src/bsdfs/dielectric.cpp +++ b/src/bsdfs/dielectric.cpp @@ -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 * * * - * - * + * + * * * * \end{xml} diff --git a/src/bsdfs/mask.cpp b/src/bsdfs/mask.cpp index 8a7c3392..1588f1d7 100644 --- a/src/bsdfs/mask.cpp +++ b/src/bsdfs/mask.cpp @@ -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, diff --git a/src/bsdfs/mixture.cpp b/src/bsdfs/mixture.cpp index ce88404c..606983a7 100644 --- a/src/bsdfs/mixture.cpp +++ b/src/bsdfs/mixture.cpp @@ -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} diff --git a/src/bsdfs/roughconductor.cpp b/src/bsdfs/roughconductor.cpp index cf75d9fe..f257fa51 100644 --- a/src/bsdfs/roughconductor.cpp +++ b/src/bsdfs/roughconductor.cpp @@ -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. diff --git a/src/bsdfs/roughdielectric.cpp b/src/bsdfs/roughdielectric.cpp index 981ce8bc..2b8822bb 100644 --- a/src/bsdfs/roughdielectric.cpp +++ b/src/bsdfs/roughdielectric.cpp @@ -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. diff --git a/src/bsdfs/roughdiffuse.cpp b/src/bsdfs/roughdiffuse.cpp index f10de621..3186451c 100644 --- a/src/bsdfs/roughdiffuse.cpp +++ b/src/bsdfs/roughdiffuse.cpp @@ -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 diff --git a/src/bsdfs/roughplastic.cpp b/src/bsdfs/roughplastic.cpp index 23da5be8..f900c478 100644 --- a/src/bsdfs/roughplastic.cpp +++ b/src/bsdfs/roughplastic.cpp @@ -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}. diff --git a/src/bsdfs/twosided.cpp b/src/bsdfs/twosided.cpp index b4a0903a..f6f8b022 100644 --- a/src/bsdfs/twosided.cpp +++ b/src/bsdfs/twosided.cpp @@ -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} diff --git a/src/librender/bsdf.cpp b/src/librender/bsdf.cpp index e30d83b2..a97db56d 100644 --- a/src/librender/bsdf.cpp +++ b/src/librender/bsdf.cpp @@ -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 (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(); } diff --git a/src/librender/intersection.cpp b/src/librender/intersection.cpp index 5b7cd585..1d9fa895 100644 --- a/src/librender/intersection.cpp +++ b/src/librender/intersection.cpp @@ -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(); } diff --git a/src/qtgui/glwidget.cpp b/src/qtgui/glwidget.cpp index e6e7a7b8..aed3da99 100644 --- a/src/qtgui/glwidget.cpp +++ b/src/qtgui/glwidget.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include 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 = new Bitmap(size.x, size.y, 128); + m_luminanceBuffer[0]->download(bitmap); + ref 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 */ diff --git a/src/qtgui/mainwindow.cpp b/src/qtgui/mainwindow.cpp index e4a1a49b..86a8160d 100644 --- a/src/qtgui/mainwindow.cpp +++ b/src/qtgui/mainwindow.cpp @@ -1314,13 +1314,15 @@ void MainWindow::onExportDialogClose(int reason) { for (int y=0; yreinhardKey / avgLogLuminance; } + for (int y=0; y 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 m_bsdf; ref m_sampler; ref m_fakeSampler; diff --git a/src/textures/scale.cpp b/src/textures/scale.cpp index bcb9ecf0..885315fa 100644 --- a/src/textures/scale.cpp +++ b/src/textures/scale.cpp @@ -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)