done with the smooth conductor, started working on the rough dielectric
parent
bd4301bd1e
commit
a13583db34
|
@ -2,6 +2,7 @@
|
||||||
# ; Optical constants for Cu
|
# ; Optical constants for Cu
|
||||||
# ;
|
# ;
|
||||||
# ; Lambda (A) n k
|
# ; Lambda (A) n k
|
||||||
|
# ;-----------------------------------------
|
||||||
302.400421 1.380000
|
302.400421 1.380000
|
||||||
306.133759 1.358438
|
306.133759 1.358438
|
||||||
309.960449 1.340000
|
309.960449 1.340000
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
# ;
|
# ;
|
||||||
# ; Lambda (A) n k
|
# ; Lambda (A) n k
|
||||||
# ;-----------------------------------------
|
# ;-----------------------------------------
|
||||||
298.757050 1.662125
|
|
||||||
302.400421 1.687000
|
302.400421 1.687000
|
||||||
306.133759 1.703313
|
306.133759 1.703313
|
||||||
309.960449 1.720000
|
309.960449 1.720000
|
||||||
|
|
|
@ -24,4 +24,7 @@
|
||||||
<rgb name="transmittance" value="0 .5 0"/>
|
<rgb name="transmittance" value="0 .5 0"/>
|
||||||
</bsdf>
|
</bsdf>
|
||||||
</bsdf>
|
</bsdf>
|
||||||
|
|
||||||
|
<!-- Test the conductor model -->
|
||||||
|
<bsdf type="conductor"/>
|
||||||
</scene>
|
</scene>
|
||||||
|
|
|
@ -127,6 +127,7 @@ Passing strings is straightforward:
|
||||||
<string name="stringProperty" value="This is a string"/>
|
<string name="stringProperty" value="This is a string"/>
|
||||||
\end{xml}
|
\end{xml}
|
||||||
\subsubsection{Color spectra}
|
\subsubsection{Color spectra}
|
||||||
|
\label{sec:format-spectra}
|
||||||
Depending on the compilation flags of Mitsuba (see \secref{compiling-flags} for
|
Depending on the compilation flags of Mitsuba (see \secref{compiling-flags} for
|
||||||
details), the renderer internally either represents colors using discretized color spectra
|
details), the renderer internally either represents colors using discretized color spectra
|
||||||
(when \texttt{SPECTRUM\_SAMPLES} is set to a value other than 3), or it
|
(when \texttt{SPECTRUM\_SAMPLES} is set to a value other than 3), or it
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 225 KiB |
Binary file not shown.
After Width: | Height: | Size: 230 KiB |
Binary file not shown.
After Width: | Height: | Size: 174 KiB |
|
@ -3,6 +3,7 @@
|
||||||
\newcommand{\figref}[1]{\mbox{Figure~\ref{fig:#1}}}
|
\newcommand{\figref}[1]{\mbox{Figure~\ref{fig:#1}}}
|
||||||
\newcommand{\secref}[1]{\mbox{Section~\ref{sec:#1}}}
|
\newcommand{\secref}[1]{\mbox{Section~\ref{sec:#1}}}
|
||||||
\newcommand{\lstref}[1]{\mbox{Listing~\ref{lst:#1}}}
|
\newcommand{\lstref}[1]{\mbox{Listing~\ref{lst:#1}}}
|
||||||
|
\newcommand{\tblref}[1]{\mbox{Table~\ref{tbl:#1}}}
|
||||||
\newcommand{\code}[1]{\texttt{#1}}
|
\newcommand{\code}[1]{\texttt{#1}}
|
||||||
|
|
||||||
% Macros that are used in the plugin documentation
|
% Macros that are used in the plugin documentation
|
||||||
|
|
|
@ -21,3 +21,10 @@
|
||||||
year = {2005},
|
year = {2005},
|
||||||
publisher = {AK Peters, Ltd.}
|
publisher = {AK Peters, Ltd.}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@book{Palik1998Handbook,
|
||||||
|
title = {Handbook of optical constants of solids},
|
||||||
|
author = {Palik, E.D. and Ghosh, G.},
|
||||||
|
year = {1998},
|
||||||
|
publisher = {Academic press}
|
||||||
|
}
|
||||||
|
|
|
@ -453,14 +453,14 @@ extern MTS_EXPORT_CORE Float fresnel(Float cosThetaI, Float etaExt,
|
||||||
* Calculates the unpolarized fresnel reflection coefficient on
|
* Calculates the unpolarized fresnel reflection coefficient on
|
||||||
* an interface to a conductor.
|
* an interface to a conductor.
|
||||||
*
|
*
|
||||||
* \param cosTheta
|
* \param cosThetaI
|
||||||
* Cosine of the angle between the normal and the incident ray
|
* Cosine of the angle between the normal and the incident ray
|
||||||
* \param eta
|
* \param eta
|
||||||
* Relative refractive index (per wavelength)
|
* Real refractive index (wavelength-dependent)
|
||||||
* \param k
|
* \param k
|
||||||
* Absorption coefficient (per wavelength)
|
* Imaginary refractive index (wavelength-dependent)
|
||||||
*/
|
*/
|
||||||
extern MTS_EXPORT_CORE Spectrum fresnelConductor(Float cosTheta,
|
extern MTS_EXPORT_CORE Spectrum fresnelConductor(Float cosThetaI,
|
||||||
const Spectrum &eta, const Spectrum &k);
|
const Spectrum &eta, const Spectrum &k);
|
||||||
|
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
|
@ -6,7 +6,7 @@ plugins += env.SharedLibrary('conductor', ['conductor.cpp'])
|
||||||
plugins += env.SharedLibrary('diffuse', ['diffuse.cpp'])
|
plugins += env.SharedLibrary('diffuse', ['diffuse.cpp'])
|
||||||
#plugins += env.SharedLibrary('plastic', ['plastic.cpp'])
|
#plugins += env.SharedLibrary('plastic', ['plastic.cpp'])
|
||||||
|
|
||||||
#plugins += env.SharedLibrary('roughdielectric', ['roughdielectric.cpp'])
|
plugins += env.SharedLibrary('roughdielectric', ['roughdielectric.cpp'])
|
||||||
#plugins += env.SharedLibrary('roughconductor', ['roughconductor.cpp'])
|
#plugins += env.SharedLibrary('roughconductor', ['roughconductor.cpp'])
|
||||||
#plugins += env.SharedLibrary('roughdiffuse', ['roughdiffuse.cpp'])
|
#plugins += env.SharedLibrary('roughdiffuse', ['roughdiffuse.cpp'])
|
||||||
#plugins += env.SharedLibrary('roughplastic', ['roughplastic.cpp'])
|
#plugins += env.SharedLibrary('roughplastic', ['roughplastic.cpp'])
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
MTS_NAMESPACE_BEGIN
|
MTS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
/*! \plugin{varnish}{Smooth varnish layer}
|
/*! \plugin{coating}{Smooth coating layer}
|
||||||
*
|
*
|
||||||
* \parameters{
|
* \parameters{
|
||||||
* \parameter{intIOR}{\Float}{Interior index of refraction \default{1.5046}}
|
* \parameter{intIOR}{\Float}{Interior index of refraction \default{1.5046}}
|
||||||
|
|
|
@ -18,13 +18,75 @@
|
||||||
|
|
||||||
#include <mitsuba/render/bsdf.h>
|
#include <mitsuba/render/bsdf.h>
|
||||||
#include <mitsuba/render/consttexture.h>
|
#include <mitsuba/render/consttexture.h>
|
||||||
#include "ior.h"
|
#include <mitsuba/core/fresolver.h>
|
||||||
|
|
||||||
MTS_NAMESPACE_BEGIN
|
MTS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
/*! \plugin{conductor}{Smooth conductor}
|
/*! \plugin{conductor}{Smooth conductor}
|
||||||
|
* \parameters{
|
||||||
|
* \parameter{preset}{\String}{Name of a material preset, see \tblref{conductor-iors}.\!\default{\texttt{Cu} / copper}}
|
||||||
|
* \parameter{eta}{\Spectrum}{Real part of the material's index of refraction \default{based on the value of \texttt{preset}}}
|
||||||
|
* \parameter{k}{\Spectrum}{Imaginary part of the material's index of refraction, also known as absorption coefficient.
|
||||||
|
* \default{based on the value of \texttt{preset}}}
|
||||||
|
* \lastparameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
|
||||||
|
* factor used to modulate the reflectance component\default{1.0}}
|
||||||
|
* }
|
||||||
|
* \renderings{
|
||||||
|
* \rendering{Measured copper material (the default)}{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,
|
||||||
|
* such as a metal. For a similar model that instead describes a rough surface
|
||||||
|
* microstructure, take a look at the seperately 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
|
||||||
|
* refraction information, Mitsuba ships with a set of measured data for a
|
||||||
|
* several materials, where visible-spectrum information was publicly available\footnote{
|
||||||
|
* These index of refraction values are identical to the data distributed with PBRT.
|
||||||
|
* They are originally from the Luxpop database (\url{www.luxpop.com}) and
|
||||||
|
* are based on data by Palik et al. \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
|
||||||
|
* not actually conductors. These materials can also 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
|
||||||
|
* refraction (named ``ordinary'' and ``extraordinary ray'').
|
||||||
*
|
*
|
||||||
* \begin{table}
|
* When using this plugin, you should compile Mitsuba with support for spectral
|
||||||
|
* renderings to get the most accurate results. While it also works in RGB mode,
|
||||||
|
* 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]
|
||||||
|
* <shape type="...">
|
||||||
|
* <bsdf type="conductor">
|
||||||
|
* <string name="preset" value="Au"/>
|
||||||
|
* </bsdf>
|
||||||
|
* <shape>
|
||||||
|
* \end{xml}
|
||||||
|
* \vspace{5mm}
|
||||||
|
* 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):
|
||||||
|
* \begin{xml}[caption=Rendering a smooth conductor with custom data]
|
||||||
|
* <shape type="...">
|
||||||
|
* <bsdf type="conductor">
|
||||||
|
* <spectrum name="eta" filename="conductorIOR.eta.spd"/>
|
||||||
|
* <spectrum name="k" filename="conductorIOR.k.spd"/>
|
||||||
|
* </bsdf>
|
||||||
|
* <shape>
|
||||||
|
* \end{xml}
|
||||||
|
* \vspace{1.5cm}
|
||||||
|
* \begin{table}[hb!]
|
||||||
* \centering
|
* \centering
|
||||||
* \scriptsize
|
* \scriptsize
|
||||||
* \begin{tabular}{>{\ttfamily}llp{1mm}>{\ttfamily}ll}
|
* \begin{tabular}{>{\ttfamily}llp{1mm}>{\ttfamily}ll}
|
||||||
|
@ -55,24 +117,33 @@ MTS_NAMESPACE_BEGIN
|
||||||
* \bottomrule
|
* \bottomrule
|
||||||
* \end{tabular}
|
* \end{tabular}
|
||||||
* \caption{
|
* \caption{
|
||||||
* \label{tbl:dielectric-iors}
|
* \label{tbl:conductor-iors}
|
||||||
* This table lists all supported material names that can be passed into the
|
* This table lists all supported material names that can be passed into the
|
||||||
* \pluginref{conductor} plugin. In most cases, there are two separate
|
* \pluginref{conductor} plugin. Note that some of them are not actually
|
||||||
* measurements of the same material made using different approaches.
|
* conductors---this is not a problem, they can be used regardless (though only
|
||||||
|
* the reflection component and no transmission will be simulated).
|
||||||
|
* In most cases, there are multiple entries for each material, which
|
||||||
|
* represent different measurements.
|
||||||
* }
|
* }
|
||||||
* \end{table}
|
* \end{table}
|
||||||
**
|
|
||||||
*/
|
*/
|
||||||
class SmoothConductor : public BSDF {
|
class SmoothConductor : public BSDF {
|
||||||
public:
|
public:
|
||||||
SmoothConductor(const Properties &props) : BSDF(props) {
|
SmoothConductor(const Properties &props) : BSDF(props) {
|
||||||
|
ref<FileResolver> fResolver = Thread::getThread()->getFileResolver();
|
||||||
|
|
||||||
m_specularReflectance = new ConstantSpectrumTexture(
|
m_specularReflectance = new ConstantSpectrumTexture(
|
||||||
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
|
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
|
||||||
|
|
||||||
std::string preset = props.getString("preset", "Cu");
|
std::string preset = props.getString("preset", "Cu");
|
||||||
|
Spectrum presetEta, presetK;
|
||||||
|
presetEta.fromContinuousSpectrum(InterpolatedSpectrum(
|
||||||
|
fResolver->resolve("data/ior/" + preset + ".eta.spd")));
|
||||||
|
presetK.fromContinuousSpectrum(InterpolatedSpectrum(
|
||||||
|
fResolver->resolve("data/ior/" + preset + ".k.spd")));
|
||||||
|
|
||||||
//m_eta = props.getSpectrum("eta", presetEta);
|
m_eta = props.getSpectrum("eta", presetEta);
|
||||||
// m_k = props.getSpectrum("k", presetK);
|
m_k = props.getSpectrum("k", presetK);
|
||||||
|
|
||||||
m_components.push_back(EDeltaReflection | EFrontSide);
|
m_components.push_back(EDeltaReflection | EFrontSide);
|
||||||
m_usesRayDifferentials = false;
|
m_usesRayDifferentials = false;
|
||||||
|
@ -106,20 +177,63 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
|
/// Reflection in local coordinates
|
||||||
return Spectrum(0.0f);
|
inline Vector reflect(const Vector &wi) const {
|
||||||
|
return Vector(-wi.x, -wi.y, wi.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||||
return Spectrum(0.0f);
|
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
||||||
}
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
|
|
||||||
Spectrum sample(BSDFQueryRecord &bRec, Float &pdf, const Point2 &sample) const {
|
if (!sampleReflection || measure != EDiscrete ||
|
||||||
return Spectrum(0.0f);
|
Frame::cosTheta(bRec.wi) <= 0 ||
|
||||||
|
Frame::cosTheta(bRec.wo) <= 0)
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
|
return m_specularReflectance->getValue(bRec.its) *
|
||||||
|
fresnelConductor(Frame::cosTheta(bRec.wi), m_eta, m_k);
|
||||||
}
|
}
|
||||||
|
|
||||||
Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||||
return 0.0f;
|
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
|
if (!sampleReflection || measure != EDiscrete ||
|
||||||
|
Frame::cosTheta(bRec.wi) <= 0 ||
|
||||||
|
Frame::cosTheta(bRec.wo) <= 0)
|
||||||
|
return 0.0f;
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
|
||||||
|
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
|
|
||||||
|
if (!sampleReflection || Frame::cosTheta(bRec.wi) <= 0)
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
|
bRec.sampledComponent = 0;
|
||||||
|
bRec.sampledType = EDeltaReflection;
|
||||||
|
bRec.wo = reflect(bRec.wi);
|
||||||
|
|
||||||
|
return m_specularReflectance->getValue(bRec.its) *
|
||||||
|
fresnelConductor(Frame::cosTheta(bRec.wi), m_eta, m_k);
|
||||||
|
}
|
||||||
|
|
||||||
|
Spectrum sample(BSDFQueryRecord &bRec, Float &pdf, const Point2 &sample) const {
|
||||||
|
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
|
|
||||||
|
if (!sampleReflection || Frame::cosTheta(bRec.wi) <= 0)
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
|
bRec.sampledComponent = 0;
|
||||||
|
bRec.sampledType = EDeltaReflection;
|
||||||
|
bRec.wo = reflect(bRec.wi);
|
||||||
|
pdf = 1;
|
||||||
|
|
||||||
|
return m_specularReflectance->getValue(bRec.its) *
|
||||||
|
fresnelConductor(Frame::cosTheta(bRec.wi), m_eta, m_k);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
|
|
|
@ -196,6 +196,54 @@ public:
|
||||||
return Vector(-eta*wi.x, -eta*wi.y, cosThetaT);
|
return Vector(-eta*wi.x, -eta*wi.y, cosThetaT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||||
|
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
|
bool sampleTransmission = (bRec.typeMask & EDeltaTransmission)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 1);
|
||||||
|
bool reflection = Frame::cosTheta(bRec.wo) * Frame::cosTheta(bRec.wi) > 0;
|
||||||
|
|
||||||
|
if ((reflection && !sampleReflection) ||
|
||||||
|
(!reflection && !sampleTransmission) || measure != EDiscrete)
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
|
Float fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
||||||
|
|
||||||
|
if (reflection) {
|
||||||
|
return m_specularReflectance->getValue(bRec.its) * fr;
|
||||||
|
} else {
|
||||||
|
Float etaI = m_extIOR, etaT = m_intIOR;
|
||||||
|
bool entering = Frame::cosTheta(bRec.wi) > 0.0f;
|
||||||
|
if (!entering)
|
||||||
|
std::swap(etaI, etaT);
|
||||||
|
|
||||||
|
Float factor = (bRec.quantity == ERadiance)
|
||||||
|
? (etaI*etaI) / (etaT*etaT) : 1.0f;
|
||||||
|
|
||||||
|
return m_specularTransmittance->getValue(bRec.its) * factor * (1 - fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||||
|
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
|
bool sampleTransmission = (bRec.typeMask & EDeltaTransmission)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 1);
|
||||||
|
bool reflection = Frame::cosTheta(bRec.wo)
|
||||||
|
* Frame::cosTheta(bRec.wi) > 0;
|
||||||
|
|
||||||
|
if ((reflection && !sampleReflection) ||
|
||||||
|
(!reflection && !sampleTransmission) || measure != EDiscrete)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
if (sampleTransmission && sampleReflection) {
|
||||||
|
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
||||||
|
return reflection ? Fr : (1 - Fr);
|
||||||
|
} else {
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
|
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
|
||||||
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
||||||
&& (bRec.component == -1 || bRec.component == 0);
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
|
@ -278,54 +326,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
|
||||||
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 0);
|
|
||||||
bool sampleTransmission = (bRec.typeMask & EDeltaTransmission)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 1);
|
|
||||||
bool reflection = Frame::cosTheta(bRec.wo) * Frame::cosTheta(bRec.wi) > 0;
|
|
||||||
|
|
||||||
if ((reflection && !sampleReflection) ||
|
|
||||||
(!reflection && !sampleTransmission) || measure != EDiscrete)
|
|
||||||
return Spectrum(0.0f);
|
|
||||||
|
|
||||||
Float fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
|
||||||
|
|
||||||
if (reflection) {
|
|
||||||
return m_specularReflectance->getValue(bRec.its) * fr;
|
|
||||||
} else {
|
|
||||||
Float etaI = m_extIOR, etaT = m_intIOR;
|
|
||||||
bool entering = Frame::cosTheta(bRec.wi) > 0.0f;
|
|
||||||
if (!entering)
|
|
||||||
std::swap(etaI, etaT);
|
|
||||||
|
|
||||||
Float factor = (bRec.quantity == ERadiance)
|
|
||||||
? (etaI*etaI) / (etaT*etaT) : 1.0f;
|
|
||||||
|
|
||||||
return m_specularTransmittance->getValue(bRec.its) * factor * (1 - fr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
|
||||||
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 0);
|
|
||||||
bool sampleTransmission = (bRec.typeMask & EDeltaTransmission)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 1);
|
|
||||||
bool reflection = Frame::cosTheta(bRec.wo)
|
|
||||||
* Frame::cosTheta(bRec.wi) > 0;
|
|
||||||
|
|
||||||
if ((reflection && !sampleReflection) ||
|
|
||||||
(!reflection && !sampleTransmission) || measure != EDiscrete)
|
|
||||||
return 0.0f;
|
|
||||||
|
|
||||||
if (sampleTransmission && sampleReflection) {
|
|
||||||
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
|
||||||
return reflection ? Fr : (1 - Fr);
|
|
||||||
} else {
|
|
||||||
return 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum sample(BSDFQueryRecord &bRec, Float &pdf, const Point2 &sample) const {
|
Spectrum sample(BSDFQueryRecord &bRec, Float &pdf, const Point2 &sample) const {
|
||||||
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
|
||||||
&& (bRec.component == -1 || bRec.component == 0);
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
|
|
|
@ -50,8 +50,7 @@ public:
|
||||||
* (ggx/phong/beckmann)
|
* (ggx/phong/beckmann)
|
||||||
*/
|
*/
|
||||||
MicrofacetDistribution(const std::string &name) {
|
MicrofacetDistribution(const std::string &name) {
|
||||||
std::string distr =
|
std::string distr = boost::to_lower_copy(name);
|
||||||
boost::to_lower_copy(props.getString("distribution", "beckmann"));
|
|
||||||
|
|
||||||
if (distr == "beckmann")
|
if (distr == "beckmann")
|
||||||
m_type = EBeckmann;
|
m_type = EBeckmann;
|
||||||
|
@ -171,8 +170,8 @@ public:
|
||||||
* \brief Smith's shadow-masking function G1 for each
|
* \brief Smith's shadow-masking function G1 for each
|
||||||
* of the supported microfacet distributions
|
* of the supported microfacet distributions
|
||||||
*
|
*
|
||||||
* \param m The microsurface normal
|
|
||||||
* \param v An arbitrary direction
|
* \param v An arbitrary direction
|
||||||
|
* \param m The microsurface normal
|
||||||
* \param alpha The surface roughness
|
* \param alpha The surface roughness
|
||||||
*/
|
*/
|
||||||
Float smithG1(const Vector &v, const Vector &m, Float alpha) const {
|
Float smithG1(const Vector &v, const Vector &m, Float alpha) const {
|
||||||
|
@ -218,9 +217,22 @@ public:
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Smith's shadow-masking function G1 for each
|
||||||
|
* of the supported microfacet distributions
|
||||||
|
*
|
||||||
|
* \param wi The incident direction
|
||||||
|
* \param wo The exitant direction
|
||||||
|
* \param m The microsurface normal
|
||||||
|
* \param alpha The surface roughness
|
||||||
|
*/
|
||||||
|
Float smithG(const Vector &wi, const Vector &wo, const Vector &m, Float alpha) const {
|
||||||
|
return smithG1(wi, m, alpha) * smithG1(wo, m, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
switch (m_distribution) {
|
switch (m_type) {
|
||||||
case EBeckmann: return "beckmann"; break;
|
case EBeckmann: return "beckmann"; break;
|
||||||
case EPhong: return "phong"; break;
|
case EPhong: return "phong"; break;
|
||||||
case EGGX: return "ggx"; break;
|
case EGGX: return "ggx"; break;
|
||||||
|
@ -230,7 +242,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
EType type;
|
EType m_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
|
@ -127,15 +127,6 @@ public:
|
||||||
m_specularTransmittance = new ConstantSpectrumTexture(
|
m_specularTransmittance = new ConstantSpectrumTexture(
|
||||||
props.getSpectrum("specularTransmittance", Spectrum(1.0f)));
|
props.getSpectrum("specularTransmittance", Spectrum(1.0f)));
|
||||||
|
|
||||||
Float alpha;
|
|
||||||
if (props.hasProperty("alphaB")) {
|
|
||||||
Log(EWarn, "Deprecation warning: the 'alphaB' parameter "
|
|
||||||
"has been renamed to 'alpha'");
|
|
||||||
|
|
||||||
alpha = props.getFloat("alphaB");
|
|
||||||
} else {
|
|
||||||
alpha = props.getFloat("alpha", 0.1f);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_intIOR = props.getFloat("intIOR", 1.5046f);
|
m_intIOR = props.getFloat("intIOR", 1.5046f);
|
||||||
m_extIOR = props.getFloat("extIOR", 1.0f);
|
m_extIOR = props.getFloat("extIOR", 1.0f);
|
||||||
|
@ -145,10 +136,11 @@ public:
|
||||||
"refraction must be positive and differ!");
|
"refraction must be positive and differ!");
|
||||||
|
|
||||||
m_distribution = MicrofacetDistribution(
|
m_distribution = MicrofacetDistribution(
|
||||||
m_props.getString("distribution", "beckmann")
|
props.getString("distribution", "beckmann")
|
||||||
);
|
);
|
||||||
|
|
||||||
m_alpha = new ConstantFloatTexture(alpha);
|
m_alpha = new ConstantFloatTexture(
|
||||||
|
props.getFloat("alpha", 0.1f));
|
||||||
|
|
||||||
m_components.push_back(
|
m_components.push_back(
|
||||||
EGlossyReflection | EFrontSide | EBackSide | ECanUseSampler);
|
EGlossyReflection | EFrontSide | EBackSide | ECanUseSampler);
|
||||||
|
@ -184,7 +176,10 @@ public:
|
||||||
return (value < 0) ? -1.0f : 1.0f;
|
return (value < 0) ? -1.0f : 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum eval(const BSDFQueryRecord &bRec) const {
|
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||||
|
if (measure != ESolidAngle)
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
/* Determine the type of interaction */
|
/* Determine the type of interaction */
|
||||||
bool reflect = Frame::cosTheta(bRec.wi)
|
bool reflect = Frame::cosTheta(bRec.wi)
|
||||||
* Frame::cosTheta(bRec.wo) > 0;
|
* Frame::cosTheta(bRec.wo) > 0;
|
||||||
|
@ -219,7 +214,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate the roughness */
|
/* Evaluate the roughness */
|
||||||
Float alpha = m_distribution.transform(
|
Float alpha = m_distribution.transformRoughness(
|
||||||
m_alpha->getValue(bRec.its).average());
|
m_alpha->getValue(bRec.its).average());
|
||||||
|
|
||||||
/* Microsurface normal distribution */
|
/* Microsurface normal distribution */
|
||||||
|
@ -231,7 +226,7 @@ public:
|
||||||
const Float F = fresnel(dot(bRec.wi, H), m_extIOR, m_intIOR);
|
const Float F = fresnel(dot(bRec.wi, H), m_extIOR, m_intIOR);
|
||||||
|
|
||||||
/* Smith's shadow-masking function */
|
/* Smith's shadow-masking function */
|
||||||
const Float G = smithG1(bRec.wi, H, alpha) * smithG1(bRec.wo, H, alpha);
|
const Float G = m_distribution.smithG(bRec.wi, bRec.wo, H, alpha);
|
||||||
|
|
||||||
if (reflect) {
|
if (reflect) {
|
||||||
/* Calculate the total amount of reflection */
|
/* Calculate the total amount of reflection */
|
||||||
|
@ -255,7 +250,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Float pdf(const BSDFQueryRecord &bRec) const {
|
Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||||
|
if (measure != ESolidAngle)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
/* Determine the type of interaction */
|
/* Determine the type of interaction */
|
||||||
bool sampleReflection = ((bRec.component == -1 || bRec.component == 0)
|
bool sampleReflection = ((bRec.component == -1 || bRec.component == 0)
|
||||||
&& (bRec.typeMask & EGlossyReflection)),
|
&& (bRec.typeMask & EGlossyReflection)),
|
||||||
|
@ -303,7 +301,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate the roughness */
|
/* Evaluate the roughness */
|
||||||
Float alpha = m_distribution.transform(
|
Float alpha = m_distribution.transformRoughness(
|
||||||
m_alpha->getValue(bRec.its).average());
|
m_alpha->getValue(bRec.its).average());
|
||||||
|
|
||||||
/* Suggestion by Bruce Walter: sample using a slightly different
|
/* Suggestion by Bruce Walter: sample using a slightly different
|
||||||
|
@ -386,7 +384,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate the roughness */
|
/* Evaluate the roughness */
|
||||||
Float alpha = m_distribution.transform(
|
Float alpha = m_distribution.transformRoughness(
|
||||||
m_alpha->getValue(bRec.its).average());
|
m_alpha->getValue(bRec.its).average());
|
||||||
|
|
||||||
/* Suggestion by Bruce Walter: sample using a slightly different
|
/* Suggestion by Bruce Walter: sample using a slightly different
|
||||||
|
@ -396,7 +394,7 @@ public:
|
||||||
std::abs(Frame::cosTheta(bRec.wi))));
|
std::abs(Frame::cosTheta(bRec.wi))));
|
||||||
|
|
||||||
/* Sample M, the microsurface normal */
|
/* Sample M, the microsurface normal */
|
||||||
const Normal m = sampleD(sample, sampleAlpha);
|
const Normal m = m_distribution.sampleD(sample, sampleAlpha);
|
||||||
|
|
||||||
if (sampleExactFresnelTerm) {
|
if (sampleExactFresnelTerm) {
|
||||||
sampleF = fresnel(dot(bRec.wi, m), m_extIOR, m_intIOR);
|
sampleF = fresnel(dot(bRec.wi, m), m_extIOR, m_intIOR);
|
||||||
|
@ -438,8 +436,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Float numerator = m_distribution.eval(m, alpha)
|
Float numerator = m_distribution.eval(m, alpha)
|
||||||
* m_distribution.smithG1(bRec.wi, m, alpha)
|
* m_distribution.smithG(bRec.wi, bRec.wo, m, alpha)
|
||||||
* m_distribution.smithG1(bRec.wo, m, alpha)
|
|
||||||
* dot(bRec.wi, m);
|
* dot(bRec.wi, m);
|
||||||
|
|
||||||
Float denominator = m_distribution.eval(m, sampleAlpha)
|
Float denominator = m_distribution.eval(m, sampleAlpha)
|
||||||
|
@ -508,7 +505,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate the roughness */
|
/* Evaluate the roughness */
|
||||||
Float alpha = m_distribution.transform(
|
Float alpha = m_distribution.transformRoughness(
|
||||||
m_alpha->getValue(bRec.its).average());
|
m_alpha->getValue(bRec.its).average());
|
||||||
|
|
||||||
/* Suggestion by Bruce Walter: sample using a slightly different
|
/* Suggestion by Bruce Walter: sample using a slightly different
|
||||||
|
@ -518,7 +515,7 @@ public:
|
||||||
std::abs(Frame::cosTheta(bRec.wi))));
|
std::abs(Frame::cosTheta(bRec.wi))));
|
||||||
|
|
||||||
/* Sample M, the microsurface normal */
|
/* Sample M, the microsurface normal */
|
||||||
const Normal m = sampleD(sample, sampleAlpha);
|
const Normal m = m_distribution.sampleD(sample, sampleAlpha);
|
||||||
|
|
||||||
if (sampleExactFresnelTerm) {
|
if (sampleExactFresnelTerm) {
|
||||||
Float sampleF = fresnel(dot(bRec.wi, m), m_extIOR, m_intIOR);
|
Float sampleF = fresnel(dot(bRec.wi, m), m_extIOR, m_intIOR);
|
||||||
|
|
|
@ -96,6 +96,8 @@ Float Spectrum::m_wavelengths[SPECTRUM_SAMPLES + 1];
|
||||||
void Spectrum::staticInitialization() {
|
void Spectrum::staticInitialization() {
|
||||||
#if SPECTRUM_SAMPLES != 3
|
#if SPECTRUM_SAMPLES != 3
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
oss << std::fixed;
|
||||||
|
oss.precision(2);
|
||||||
Float stepSize = SPECTRUM_RANGE / (Float) SPECTRUM_SAMPLES;
|
Float stepSize = SPECTRUM_RANGE / (Float) SPECTRUM_SAMPLES;
|
||||||
for (int i=0; i<SPECTRUM_SAMPLES + 1; i++) {
|
for (int i=0; i<SPECTRUM_SAMPLES + 1; i++) {
|
||||||
Float value = SPECTRUM_MIN_WAVELENGTH + stepSize * i;
|
Float value = SPECTRUM_MIN_WAVELENGTH + stepSize * i;
|
||||||
|
@ -406,12 +408,16 @@ void Spectrum::fromRGBE(const uint8_t rgbe[4], EConversionIntent intent) {
|
||||||
std::string Spectrum::toString() const {
|
std::string Spectrum::toString() const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "[";
|
oss << "[";
|
||||||
|
oss << std::fixed;
|
||||||
for (int i=0; i<SPECTRUM_SAMPLES; i++) {
|
for (int i=0; i<SPECTRUM_SAMPLES; i++) {
|
||||||
#if SPECTRUM_SAMPLES == 3
|
#if SPECTRUM_SAMPLES == 3
|
||||||
oss << s[i];
|
oss << s[i];
|
||||||
#else
|
#else
|
||||||
|
oss.precision(1);
|
||||||
oss << m_wavelengths[i] << "-"
|
oss << m_wavelengths[i] << "-"
|
||||||
<< m_wavelengths[i+1] << "nm => " << s[i];
|
<< m_wavelengths[i+1] << "nm => ";
|
||||||
|
oss.precision(3);
|
||||||
|
oss << s[i];
|
||||||
#endif
|
#endif
|
||||||
if (i < SPECTRUM_SAMPLES - 1)
|
if (i < SPECTRUM_SAMPLES - 1)
|
||||||
oss << ", ";
|
oss << ", ";
|
||||||
|
@ -607,9 +613,13 @@ Float InterpolatedSpectrum::eval(Float lambda) const {
|
||||||
|
|
||||||
std::string InterpolatedSpectrum::toString() const {
|
std::string InterpolatedSpectrum::toString() const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
oss << std::fixed;
|
||||||
oss << "InterpolatedSpectrum[" << endl;
|
oss << "InterpolatedSpectrum[" << endl;
|
||||||
for (size_t i=0; i<m_wavelengths.size(); ++i) {
|
for (size_t i=0; i<m_wavelengths.size(); ++i) {
|
||||||
oss << " " << m_wavelengths[i] << " nm => " << m_values[i];
|
oss.precision(1);
|
||||||
|
oss << " " << m_wavelengths[i] << " nm => ";
|
||||||
|
oss.precision(3);
|
||||||
|
oss << m_values[i];
|
||||||
if (i+1 < m_wavelengths.size())
|
if (i+1 < m_wavelengths.size())
|
||||||
oss << ",";
|
oss << ",";
|
||||||
oss << endl;
|
oss << endl;
|
||||||
|
|
|
@ -687,16 +687,16 @@ Float fresnelDielectric(Float cosThetaI, Float cosThetaT,
|
||||||
return (Rs * Rs + Rp * Rp) / 2.0f;
|
return (Rs * Rs + Rp * Rp) / 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum fresnelConductor(Float cosTheta, const Spectrum &eta, const Spectrum &k) {
|
Spectrum fresnelConductor(Float cosThetaI, const Spectrum &eta, const Spectrum &k) {
|
||||||
Spectrum tmp = (eta*eta + k*k) * (cosTheta * cosTheta);
|
Spectrum tmp = (eta*eta + k*k) * (cosThetaI * cosThetaI);
|
||||||
|
|
||||||
Spectrum rParl2 = (tmp - (eta * (2.0f * cosTheta)) + Spectrum(1.0f))
|
Spectrum rParl2 = (tmp - (eta * (2.0f * cosThetaI)) + Spectrum(1.0f))
|
||||||
/ (tmp + (eta * (2.0f * cosTheta)) + Spectrum(1.0f));
|
/ (tmp + (eta * (2.0f * cosThetaI)) + Spectrum(1.0f));
|
||||||
|
|
||||||
Spectrum tmpF = eta*eta + k*k;
|
Spectrum tmpF = eta*eta + k*k;
|
||||||
|
|
||||||
Spectrum rPerp2 = (tmpF - (eta * (2.0f * cosTheta)) + Spectrum(cosTheta*cosTheta)) /
|
Spectrum rPerp2 = (tmpF - (eta * (2.0f * cosThetaI)) + Spectrum(cosThetaI*cosThetaI)) /
|
||||||
(tmpF + (eta * (2.0f * cosTheta)) + Spectrum(cosTheta*cosTheta));
|
(tmpF + (eta * (2.0f * cosThetaI)) + Spectrum(cosThetaI*cosThetaI));
|
||||||
|
|
||||||
return (rParl2 + rPerp2) / 2.0f;
|
return (rParl2 + rPerp2) / 2.0f;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue