metadata
Wenzel Jakob 2011-07-07 18:50:43 +02:00
parent 736a8e6866
commit dacb6f96b6
3 changed files with 140 additions and 67 deletions

View File

@ -26,17 +26,20 @@ MTS_NAMESPACE_BEGIN
* \parameters{ * \parameters{
* \parameter{preset}{\String}{Name of a material preset, see * \parameter{preset}{\String}{Name of a material preset, see
* \tblref{conductor-iors}.\!\default{\texttt{Cu} / copper}} * \tblref{conductor-iors}.\!\default{\texttt{Cu} / copper}}
* \parameter{eta}{\Spectrum}{Real part of the material's index of refraction * \parameter{eta}{\Spectrum}{Real part of the material's index
* \default{based on the value of \texttt{preset}}} * of refraction \default{based on the value of \texttt{preset}}}
* \parameter{k}{\Spectrum}{Imaginary part of the material's index of * \parameter{k}{\Spectrum}{Imaginary part of the material's index of
* refraction, also known as absorption coefficient. * refraction, also known as absorption coefficient.
* \default{based on the value of \texttt{preset}}} * \default{based on the value of \texttt{preset}}}
* \lastparameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional * \lastparameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{
* factor used to modulate the reflectance component\default{1.0}} * Optional factor used to modulate the reflectance component
* \default{1.0}}
* } * }
* \renderings{ * \renderings{
* \rendering{Measured copper material (the default)}{bsdf_conductor_copper.jpg} * \rendering{Measured copper material (the default)}
* \rendering{Measured gold material (\lstref{conductor-gold})}{bsdf_conductor_gold.jpg} * {bsdf_conductor_copper.jpg}
* \rendering{Measured gold material (\lstref{conductor-gold})}
* {bsdf_conductor_gold.jpg}
* } * }
* This plugin implements a perfectly smooth interface to a conducting material, * This plugin implements a perfectly smooth interface to a conducting material,
@ -50,18 +53,20 @@ MTS_NAMESPACE_BEGIN
* *
* To faciliate the tedious task of specifying spectrally-varying index of * To faciliate the tedious task of specifying spectrally-varying index of
* refraction information, Mitsuba ships with a set of measured data for a * refraction information, Mitsuba ships with a set of measured data for a
* several materials, where visible-spectrum information was publicly available\footnote{ * several materials, where visible-spectrum information was publicly
* These index of refraction values are identical to the data distributed with PBRT. * available\footnote{
* They are originally from the Luxpop database (\url{www.luxpop.com}) and * These index of refraction values are identical to the data distributed
* are based on data by Palik et al. \cite{Palik1998Handbook} and measurements * with PBRT. They are originally from the Luxpop database
* of atomic scattering factors made by the Center For X-Ray Optics (CXRO) * (\url{www.luxpop.com}) and are based on data by Palik et al.
* at Berkeley and the Lawrence Livermore National Laboratory (LLNL). * \cite{Palik1998Handbook} and measurements of atomic scattering factors
* made by the Center For X-Ray Optics (CXRO) at Berkeley and the
* Lawrence Livermore National Laboratory (LLNL).
* }. * }.
* *
* Note that \tblref{conductor-iors} also includes several popular optical coatings, which are * Note that \tblref{conductor-iors} also includes several popular optical
* not actually conductors. These materials can also be used with this plugin, * coatings, which are not actually conductors. These materials can also
* though note that the plugin will ignore any refraction component that the actual * be used with this plugin, though note that the plugin will ignore any
* 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 correponding to their two indices of
* refraction (named ``ordinary'' and ``extraordinary ray''). * refraction (named ``ordinary'' and ``extraordinary ray'').
@ -70,7 +75,8 @@ MTS_NAMESPACE_BEGIN
* renderings to get the most accurate results. While it also works in RGB mode, * renderings to get the most accurate results. While it also works in RGB mode,
* the computations will be much more approximate in this case. * the computations will be much more approximate in this case.
* *
* \begin{xml}[caption=Material configuration for a smooth conductor with measured gold data, label=lst:conductor-gold] * \begin{xml}[caption=Material configuration for a smooth conductor with
* measured gold data, label=lst:conductor-gold]
* <shape type="..."> * <shape type="...">
* <bsdf type="conductor"> * <bsdf type="conductor">
* <string name="preset" value="Au"/> * <string name="preset" value="Au"/>
@ -79,7 +85,8 @@ MTS_NAMESPACE_BEGIN
* \end{xml} * \end{xml}
* \vspace{5mm} * \vspace{5mm}
* It is also possible to load spectrally varying index of refraction data from * It is also possible to load spectrally varying index of refraction data from
* two external files (see \secref{format-spectra} for details on the file format): * two external files (see \secref{format-spectra} for details on the file
* format):
* \begin{xml}[caption=Rendering a smooth conductor with custom data] * \begin{xml}[caption=Rendering a smooth conductor with custom data]
* <shape type="..."> * <shape type="...">
* <bsdf type="conductor"> * <bsdf type="conductor">
@ -121,12 +128,13 @@ MTS_NAMESPACE_BEGIN
* \end{tabular} * \end{tabular}
* \caption{ * \caption{
* \label{tbl:conductor-iors} * \label{tbl:conductor-iors}
* This table lists all supported material names that can be passed into the * This table lists all supported materials that can be passed into the
* \pluginref{conductor} plugin. Note that some of them are not actually * \pluginref{conductor} and \pluginref{roughconductor} plugins. Note that
* conductors---this is not a problem, they can be used regardless (though only * some of them are not actually conductors---this is not a problem,
* the reflection component and no transmission will be simulated). * they can be used regardless (though only the reflection component and
* In most cases, there are multiple entries for each material, which * no transmission will be simulated). In most cases, there are
* represent different measurements. * multiple entries for each material, which represent measurements by
* different authors.
* } * }
* \end{table} * \end{table}
*/ */
@ -196,9 +204,12 @@ public:
bool sampleReflection = (bRec.typeMask & EDeltaReflection) bool sampleReflection = (bRec.typeMask & EDeltaReflection)
&& (bRec.component == -1 || bRec.component == 0); && (bRec.component == -1 || bRec.component == 0);
/* Verify that the provided direction pair matches an ideal
specular reflection; tolerate some roundoff errors */
if (!sampleReflection || measure != EDiscrete || if (!sampleReflection || measure != EDiscrete ||
Frame::cosTheta(bRec.wi) <= 0 || Frame::cosTheta(bRec.wi) <= 0 ||
Frame::cosTheta(bRec.wo) <= 0) Frame::cosTheta(bRec.wo) <= 0 ||
std::abs(1 - dot(reflect(bRec.wi), bRec.wo)) > Epsilon)
return Spectrum(0.0f); return Spectrum(0.0f);
return m_specularReflectance->getValue(bRec.its) * return m_specularReflectance->getValue(bRec.its) *
@ -208,10 +219,15 @@ public:
Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const { Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const {
bool sampleReflection = (bRec.typeMask & EDeltaReflection) bool sampleReflection = (bRec.typeMask & EDeltaReflection)
&& (bRec.component == -1 || bRec.component == 0); && (bRec.component == -1 || bRec.component == 0);
/* Verify that the provided direction pair matches an ideal
specular reflection; tolerate some roundoff errors */
if (!sampleReflection || measure != EDiscrete || if (!sampleReflection || measure != EDiscrete ||
Frame::cosTheta(bRec.wi) <= 0 || Frame::cosTheta(bRec.wi) <= 0 ||
Frame::cosTheta(bRec.wo) <= 0) Frame::cosTheta(bRec.wo) <= 0 ||
std::abs(1 - dot(reflect(bRec.wi), bRec.wo)) > Epsilon)
return 0.0f; return 0.0f;
return 1.0f; return 1.0f;
} }

View File

@ -45,14 +45,14 @@ MTS_NAMESPACE_BEGIN
* *
* This plugin models an interface between two dielectric materials having mismatched * This plugin models an interface between two dielectric materials having mismatched
* indices of refraction (for instance, water and air). Exterior and interior IOR values * indices of refraction (for instance, water and air). Exterior and interior IOR values
* can each be independently specified, where ``exterior'' refers to the side that contains * can be independently specified, where ``exterior'' refers to the side that contains
* the surface normal. When no parameters are given, the plugin activates the defaults, which * the surface normal. When no parameters are given, the plugin activates the defaults, which
* describe a borosilicate glass BK7/air interface. * describe a borosilicate glass BK7/air interface.
* *
* In this model, the microscopic surface structure of the surface is assumed to be perfectly * In this model, the microscopic structure of the surface is assumed to be perfectly
* smooth, resulting in a degenerate\footnote{Meaning that for any given incoming ray of light, * smooth, resulting in a degenerate\footnote{Meaning that for any given incoming ray of light,
* the model always scatters into a discrete set of directions, as opposed to a continuum.} * the model always scatters into a discrete set of directions, as opposed to a continuum.}
* BSDF described by a Dirac delta function. For a similar model that instead describes a * BSDF described by a Dirac delta distribution. For a similar model that instead describes a
* rough surface microstructure, take a look at the \pluginref{roughdielectric} plugin. * rough surface microstructure, take a look at the \pluginref{roughdielectric} plugin.
* *
* \begin{xml}[caption=A simple air-to-water interface, label=lst:dielectric-water] * \begin{xml}[caption=A simple air-to-water interface, label=lst:dielectric-water]
@ -125,9 +125,13 @@ MTS_NAMESPACE_BEGIN
* \end{tabular} * \end{tabular}
* \caption{ * \caption{
* \label{tbl:dielectric-iors} * \label{tbl:dielectric-iors}
* This table lists all supported material names that can be passed * This table lists all supported material names along with
* into the \pluginref{dielectric} plugin, along with the associated * along with the associated index of refraction at
* index of refraction at standard conditions. * standard conditions. These can be used with the plugins
* \pluginref{dielectric},\
* \pluginref{roughdielectric},\
* \pluginref{plastic}, and
* \pluginref{roughplastic}.
* } * }
* \end{table} * \end{table}
*/ */
@ -200,26 +204,66 @@ public:
return Vector(-wi.x, -wi.y, wi.z); return Vector(-wi.x, -wi.y, wi.z);
} }
/// Refraction in local coordinates /// Refraction in local coordinates (reuses computed information)
inline Vector refract(const Vector &wi, Float eta, Float cosThetaT) const { inline Vector refract(const Vector &wi, Float eta, Float cosThetaT) const {
return Vector(-eta*wi.x, -eta*wi.y, cosThetaT); return Vector(-eta*wi.x, -eta*wi.y, cosThetaT);
} }
/// Refraction in local coordinates (full version)
inline Vector refract(const Vector &wi) const {
Float cosThetaI = Frame::cosTheta(wi),
etaI = m_extIOR,
etaT = m_intIOR;
bool entering = cosThetaI > 0.0f;
/* Determine the respective indices of refraction */
if (!entering)
std::swap(etaI, etaT);
/* Using Snell's law, calculate the squared sine of the
angle between the normal and the transmitted ray */
Float eta = etaI / etaT,
sinThetaTSqr = eta*eta * Frame::sinTheta2(wi);
Float cosThetaT = 0;
if (sinThetaTSqr >= 1.0f) {
/* Total internal reflection */
return Vector(0.0f);
} else {
cosThetaT = std::sqrt(1.0f - sinThetaTSqr);
if (entering)
cosThetaT = -cosThetaT;
}
return Vector(-eta*wi.x, -eta*wi.y, cosThetaT);
}
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const { Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
bool sampleReflection = (bRec.typeMask & EDeltaReflection) bool sampleReflection = (bRec.typeMask & EDeltaReflection)
&& (bRec.component == -1 || bRec.component == 0); && (bRec.component == -1 || bRec.component == 0);
bool sampleTransmission = (bRec.typeMask & EDeltaTransmission) bool sampleTransmission = (bRec.typeMask & EDeltaTransmission)
&& (bRec.component == -1 || bRec.component == 1); && (bRec.component == -1 || bRec.component == 1);
bool reflection = Frame::cosTheta(bRec.wo) * Frame::cosTheta(bRec.wi) > 0;
if ((reflection && !sampleReflection) || /* Check if the provided direction pair matches an ideal
(!reflection && !sampleTransmission) || measure != EDiscrete) specular reflection; tolerate some roundoff errors */
bool reflection = std::abs(1 - dot(reflect(bRec.wi), bRec.wo)) < Epsilon;
if (measure != EDiscrete || (reflection && !sampleReflection))
return Spectrum(0.0f); return Spectrum(0.0f);
Float fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR); if (!reflection) {
/* Check if the provided direction pair matches an ideal
specular refraction; tolerate some roundoff errors */
bool refraction = std::abs(1 - dot(refract(bRec.wi), bRec.wo)) < Epsilon;
if (!refraction || !sampleTransmission)
return Spectrum(0.0f);
}
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
if (reflection) { if (reflection) {
return m_specularReflectance->getValue(bRec.its) * fr; return m_specularReflectance->getValue(bRec.its) * Fr;
} else { } else {
Float etaI = m_extIOR, etaT = m_intIOR; Float etaI = m_extIOR, etaT = m_intIOR;
bool entering = Frame::cosTheta(bRec.wi) > 0.0f; bool entering = Frame::cosTheta(bRec.wi) > 0.0f;
@ -229,7 +273,7 @@ public:
Float factor = (bRec.quantity == ERadiance) Float factor = (bRec.quantity == ERadiance)
? (etaI*etaI) / (etaT*etaT) : 1.0f; ? (etaI*etaI) / (etaT*etaT) : 1.0f;
return m_specularTransmittance->getValue(bRec.its) * factor * (1 - fr); return m_specularTransmittance->getValue(bRec.its) * factor * (1 - Fr);
} }
} }
@ -238,13 +282,21 @@ public:
&& (bRec.component == -1 || bRec.component == 0); && (bRec.component == -1 || bRec.component == 0);
bool sampleTransmission = (bRec.typeMask & EDeltaTransmission) bool sampleTransmission = (bRec.typeMask & EDeltaTransmission)
&& (bRec.component == -1 || bRec.component == 1); && (bRec.component == -1 || bRec.component == 1);
bool reflection = Frame::cosTheta(bRec.wo)
* Frame::cosTheta(bRec.wi) > 0;
if ((reflection && !sampleReflection) || /* Check if the provided direction pair matches an ideal
(!reflection && !sampleTransmission) || measure != EDiscrete) specular reflection; tolerate some roundoff errors */
bool reflection = std::abs(1 - dot(reflect(bRec.wi), bRec.wo)) < Epsilon;
if (measure != EDiscrete || (reflection && !sampleReflection))
return 0.0f; return 0.0f;
if (!reflection) {
/* Check if the provided direction pair matches an ideal
specular refraction; tolerate some roundoff errors */
bool refraction = std::abs(1 - dot(refract(bRec.wi), bRec.wo)) < Epsilon;
if (!refraction || !sampleTransmission)
return 0.0f;
}
if (sampleTransmission && sampleReflection) { if (sampleTransmission && sampleReflection) {
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR); Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
return reflection ? Fr : (1 - Fr); return reflection ? Fr : (1 - Fr);

View File

@ -43,10 +43,9 @@ MTS_NAMESPACE_BEGIN
* behavior than the separately available \pluginref{phong} plugin. * behavior than the separately available \pluginref{phong} plugin.
* \item \code{ggx}: New distribution proposed by * \item \code{ggx}: New distribution proposed by
* Walter et al. meant to better handle the long * Walter et al. meant to better handle the long
* tails observed in transmission measurements through * tails observed in measurements of ground surfaces.
* ground glass. Renderings with this distribution may * Renderings with this distribution may converge slowly.
* converge slowly. * \item \code{as}: Anisotropic Phong-style microfacet distribution proposed by
* \item \code{as}: Anisotropic microfacet distribution proposed by
* Ashikhmin and Shirley \cite{Ashikhmin2005Anisotropic}.\vspace{-3mm} * Ashikhmin and Shirley \cite{Ashikhmin2005Anisotropic}.\vspace{-3mm}
* \end{enumerate} * \end{enumerate}
* } * }
@ -58,12 +57,14 @@ MTS_NAMESPACE_BEGIN
* \default{0.1}. * \default{0.1}.
* } * }
* \parameter{alphaU, alphaV}{\Float\Or\Texture}{ * \parameter{alphaU, alphaV}{\Float\Or\Texture}{
* Specifies the anisotropic rougness values along the tangent and bitangent directions. This * Specifies the anisotropic rougness values along the tangent and bitangent directions. These
* parameter is only valid when \texttt{distribution=as}. * parameter are only valid when \texttt{distribution=as}.
* \default{0.1}. * \default{0.1}.
* } * }
* \parameter{intIOR}{\Float}{Interior index of refraction \default{1.5046}} * \parameter{intIOR}{\Float\Or\String}{Interior index of refraction specified
* \parameter{extIOR}{\Float}{Exterior index of refraction \default{1.0}} * 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{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional * \parameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
* factor used to modulate the reflectance component\default{1.0}} * factor used to modulate the reflectance component\default{1.0}}
* \lastparameter{specular\showbreak Transmittance}{\Spectrum\Or\Texture}{Optional * \lastparameter{specular\showbreak Transmittance}{\Spectrum\Or\Texture}{Optional
@ -93,39 +94,43 @@ MTS_NAMESPACE_BEGIN
* plugin is based on the paper ``Microfacet Models for Refraction through * plugin is based on the paper ``Microfacet Models for Refraction through
* Rough Surfaces'' by Walter et al. \cite{Walter07Microfacet}. It supports * Rough Surfaces'' by Walter et al. \cite{Walter07Microfacet}. It supports
* several types of microfacet distributions and has a texturable roughness * several types of microfacet distributions and has a texturable roughness
* parameter. Exterior and interior IOR values can each be independently * parameter. Exterior and interior IOR values can be independently
* specified, where ``exterior'' refers to the side that contains the surface * specified, where ``exterior'' refers to the side that contains the surface
* normal. When no parameters are given, the plugin activates the default * normal. Similar to the \pluginref{dielectric} plugin, IOR values can either
* settings, which describe a borosilicate glass BK7/air interface with a * be specified numerically, or based on a list of known materials (see
* light amount of roughness modeled using a Beckmann distribution. * \tblref{dielectric-iors} for an overview). When no parameters are given,
* the plugin activates the default settings, which describe a borosilicate
* glass BK7/air interface with a light amount of roughness modeled using a
* Beckmann distribution.
* *
* When using the Ashikmin-Shirley or Phong models, a conversion method is * When using the Ashikmin-Shirley or Phong models, a conversion method is
* used to turn the specified $\alpha$ roughness value into the exponents * used to turn the specified $\alpha$ roughness value into the exponents
* of these distributions. This is done so that the different distributions * of these distributions. This is done in a way, such that the different
* all produce a similar appearance for the same value of $\alpha$. * distributions all produce a similar appearance for the same value of $\alpha$.
* *
* When using this plugin, it is crucial that the scene contains * When using this plugin, it is crucial that the scene contains
* meaningful and mutally compatible index of refraction changes---see * meaningful and mutally compatible index of refraction changes---see
* \figref{glass-explanation} for an example. Also, please note that * \figref{glass-explanation} for an example. Also, please note that
* the importance sampling implementation of this model is close, but * the importance sampling implementation of this model is close, but
* not perfect a perfect match to the underlying scattering distribution, * not always a perfect a perfect match to the underlying scattering distribution,
* particularly for high roughness values and when the \texttt{GGX} * particularly for high roughness values and when the \texttt{ggx}
* model is used. Hence, such renderings may converge slowly.\vspace{1cm} * microfacet distribution is used. Hence, such renderings may
* converge slowly.\vspace{1cm}
* *
* \begin{xml}[caption=Material definition for ground glass, label=lst:roughdielectric-roughglass] * \begin{xml}[caption=A material definition for ground glass, label=lst:roughdielectric-roughglass]
* <bsdf type="roughdielectric"> * <bsdf type="roughdielectric">
* <string name="distribution" value="ggx"/> * <string name="distribution" value="ggx"/>
* <float name="alpha" value="0.304"/> * <float name="alpha" value="0.304"/>
* <float name="intIOR" value="1.5046"/> * <string name="intIOR" value="bk7"/>
* <float name="extIOR" value="1.0"/> * <string name="extIOR" value="air"/>
* </bsdf> * </bsdf>
* \end{xml} * \end{xml}
* *
* \begin{xml}[caption=A texture can be attached to the roughness parameter, label=lst:roughdielectric-textured] * \begin{xml}[caption=A texture can be attached to the roughness parameter, label=lst:roughdielectric-textured]
* <bsdf type="roughdielectric"> * <bsdf type="roughdielectric">
* <string name="distribution" value="beckmann"/> * <string name="distribution" value="beckmann"/>
* <string name="intIOR" value="bk7"/> * <float name="intIOR" value="1.5046"/>
* <string name="extIOR" value="air"/> * <float name="extIOR" value="1.0"/>
* *
* <texture name="alpha" type="bitmap"> * <texture name="alpha" type="bitmap">
* <string name="filename" value="roughness.exr"/> * <string name="filename" value="roughness.exr"/>