diff --git a/data/ior/Cu.eta.spd b/data/ior/Cu.eta.spd
index 6765da4b..75686a6a 100644
--- a/data/ior/Cu.eta.spd
+++ b/data/ior/Cu.eta.spd
@@ -2,6 +2,7 @@
# ; Optical constants for Cu
# ;
# ; Lambda (A) n k
+# ;-----------------------------------------
302.400421 1.380000
306.133759 1.358438
309.960449 1.340000
diff --git a/data/ior/Cu.k.spd b/data/ior/Cu.k.spd
index e087d4a0..5ecd7a36 100644
--- a/data/ior/Cu.k.spd
+++ b/data/ior/Cu.k.spd
@@ -3,7 +3,6 @@
# ;
# ; Lambda (A) n k
# ;-----------------------------------------
-298.757050 1.662125
302.400421 1.687000
306.133759 1.703313
309.960449 1.720000
diff --git a/data/tests/test_bsdf.xml b/data/tests/test_bsdf.xml
index f87239e2..13cc8203 100644
--- a/data/tests/test_bsdf.xml
+++ b/data/tests/test_bsdf.xml
@@ -24,4 +24,7 @@
+
+
+
diff --git a/doc/format.tex b/doc/format.tex
index 2fd444f8..09d1f5e8 100644
--- a/doc/format.tex
+++ b/doc/format.tex
@@ -127,6 +127,7 @@ Passing strings is straightforward:
\end{xml}
\subsubsection{Color spectra}
+\label{sec:format-spectra}
Depending on the compilation flags of Mitsuba (see \secref{compiling-flags} for
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
diff --git a/doc/images/bsdf_conductor_copper.jpg b/doc/images/bsdf_conductor_copper.jpg
new file mode 100644
index 00000000..c5a91ad0
Binary files /dev/null and b/doc/images/bsdf_conductor_copper.jpg differ
diff --git a/doc/images/bsdf_conductor_gold.jpg b/doc/images/bsdf_conductor_gold.jpg
new file mode 100644
index 00000000..928005f1
Binary files /dev/null and b/doc/images/bsdf_conductor_gold.jpg differ
diff --git a/doc/images/bsdf_difftrans.jpg b/doc/images/bsdf_difftrans.jpg
new file mode 100644
index 00000000..b028704e
Binary files /dev/null and b/doc/images/bsdf_difftrans.jpg differ
diff --git a/doc/macros.sty b/doc/macros.sty
index 5a569956..298bd7af 100644
--- a/doc/macros.sty
+++ b/doc/macros.sty
@@ -3,6 +3,7 @@
\newcommand{\figref}[1]{\mbox{Figure~\ref{fig:#1}}}
\newcommand{\secref}[1]{\mbox{Section~\ref{sec:#1}}}
\newcommand{\lstref}[1]{\mbox{Listing~\ref{lst:#1}}}
+\newcommand{\tblref}[1]{\mbox{Table~\ref{tbl:#1}}}
\newcommand{\code}[1]{\texttt{#1}}
% Macros that are used in the plugin documentation
diff --git a/doc/main.bib b/doc/main.bib
index 684f447d..55bf548b 100644
--- a/doc/main.bib
+++ b/doc/main.bib
@@ -21,3 +21,10 @@
year = {2005},
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}
+}
diff --git a/include/mitsuba/core/util.h b/include/mitsuba/core/util.h
index 3f181310..bd24e8db 100644
--- a/include/mitsuba/core/util.h
+++ b/include/mitsuba/core/util.h
@@ -453,14 +453,14 @@ extern MTS_EXPORT_CORE Float fresnel(Float cosThetaI, Float etaExt,
* Calculates the unpolarized fresnel reflection coefficient on
* an interface to a conductor.
*
- * \param cosTheta
+ * \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
- * Relative refractive index (per wavelength)
+ * Real refractive index (wavelength-dependent)
* \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);
/*! @} */
diff --git a/src/bsdfs/SConscript b/src/bsdfs/SConscript
index 3611a22f..28cf464d 100644
--- a/src/bsdfs/SConscript
+++ b/src/bsdfs/SConscript
@@ -6,7 +6,7 @@ plugins += env.SharedLibrary('conductor', ['conductor.cpp'])
plugins += env.SharedLibrary('diffuse', ['diffuse.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('roughdiffuse', ['roughdiffuse.cpp'])
#plugins += env.SharedLibrary('roughplastic', ['roughplastic.cpp'])
diff --git a/src/bsdfs/coating.cpp b/src/bsdfs/coating.cpp
index 97d40ce0..33d7ee14 100644
--- a/src/bsdfs/coating.cpp
+++ b/src/bsdfs/coating.cpp
@@ -21,7 +21,7 @@
MTS_NAMESPACE_BEGIN
-/*! \plugin{varnish}{Smooth varnish layer}
+/*! \plugin{coating}{Smooth coating layer}
*
* \parameters{
* \parameter{intIOR}{\Float}{Interior index of refraction \default{1.5046}}
diff --git a/src/bsdfs/conductor.cpp b/src/bsdfs/conductor.cpp
index c684976c..81b4c3a3 100644
--- a/src/bsdfs/conductor.cpp
+++ b/src/bsdfs/conductor.cpp
@@ -18,13 +18,75 @@
#include
#include
-#include "ior.h"
+#include
MTS_NAMESPACE_BEGIN
/*! \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]
+ *
+ *
+ *
+ *
+ *
+ * \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]
+ *
+ *
+ *
+ *
+ *
+ *
+ * \end{xml}
+ * \vspace{1.5cm}
+ * \begin{table}[hb!]
* \centering
* \scriptsize
* \begin{tabular}{>{\ttfamily}llp{1mm}>{\ttfamily}ll}
@@ -55,24 +117,33 @@ MTS_NAMESPACE_BEGIN
* \bottomrule
* \end{tabular}
* \caption{
- * \label{tbl:dielectric-iors}
+ * \label{tbl:conductor-iors}
* This table lists all supported material names that can be passed into the
- * \pluginref{conductor} plugin. In most cases, there are two separate
- * measurements of the same material made using different approaches.
+ * \pluginref{conductor} plugin. Note that some of them are not actually
+ * 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}
- **
*/
class SmoothConductor : public BSDF {
public:
SmoothConductor(const Properties &props) : BSDF(props) {
+ ref fResolver = Thread::getThread()->getFileResolver();
+
m_specularReflectance = new ConstantSpectrumTexture(
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
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_k = props.getSpectrum("k", presetK);
+ m_eta = props.getSpectrum("eta", presetEta);
+ m_k = props.getSpectrum("k", presetK);
m_components.push_back(EDeltaReflection | EFrontSide);
m_usesRayDifferentials = false;
@@ -106,20 +177,63 @@ public:
}
}
- Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
- return Spectrum(0.0f);
+ /// Reflection in local coordinates
+ inline Vector reflect(const Vector &wi) const {
+ return Vector(-wi.x, -wi.y, wi.z);
}
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 {
- return Spectrum(0.0f);
+ if (!sampleReflection || measure != EDiscrete ||
+ 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 {
- 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 {
diff --git a/src/bsdfs/dielectric.cpp b/src/bsdfs/dielectric.cpp
index 853bfcf5..3e4ad269 100644
--- a/src/bsdfs/dielectric.cpp
+++ b/src/bsdfs/dielectric.cpp
@@ -196,6 +196,54 @@ public:
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 {
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
&& (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 {
bool sampleReflection = (bRec.typeMask & EDeltaReflection)
&& (bRec.component == -1 || bRec.component == 0);
diff --git a/src/bsdfs/microfacet.h b/src/bsdfs/microfacet.h
index 267847be..314cb89d 100644
--- a/src/bsdfs/microfacet.h
+++ b/src/bsdfs/microfacet.h
@@ -50,8 +50,7 @@ public:
* (ggx/phong/beckmann)
*/
MicrofacetDistribution(const std::string &name) {
- std::string distr =
- boost::to_lower_copy(props.getString("distribution", "beckmann"));
+ std::string distr = boost::to_lower_copy(name);
if (distr == "beckmann")
m_type = EBeckmann;
@@ -171,8 +170,8 @@ public:
* \brief Smith's shadow-masking function G1 for each
* of the supported microfacet distributions
*
- * \param m The microsurface normal
* \param v An arbitrary direction
+ * \param m The microsurface normal
* \param alpha The surface roughness
*/
Float smithG1(const Vector &v, const Vector &m, Float alpha) const {
@@ -218,9 +217,22 @@ public:
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 {
- switch (m_distribution) {
+ switch (m_type) {
case EBeckmann: return "beckmann"; break;
case EPhong: return "phong"; break;
case EGGX: return "ggx"; break;
@@ -230,7 +242,7 @@ public:
}
}
private:
- EType type;
+ EType m_type;
};
MTS_NAMESPACE_END
diff --git a/src/bsdfs/roughdielectric.cpp b/src/bsdfs/roughdielectric.cpp
index 4bca5728..529a225b 100644
--- a/src/bsdfs/roughdielectric.cpp
+++ b/src/bsdfs/roughdielectric.cpp
@@ -127,15 +127,6 @@ public:
m_specularTransmittance = new ConstantSpectrumTexture(
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_extIOR = props.getFloat("extIOR", 1.0f);
@@ -145,10 +136,11 @@ public:
"refraction must be positive and differ!");
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(
EGlossyReflection | EFrontSide | EBackSide | ECanUseSampler);
@@ -184,7 +176,10 @@ public:
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 */
bool reflect = Frame::cosTheta(bRec.wi)
* Frame::cosTheta(bRec.wo) > 0;
@@ -219,7 +214,7 @@ public:
}
/* Evaluate the roughness */
- Float alpha = m_distribution.transform(
+ Float alpha = m_distribution.transformRoughness(
m_alpha->getValue(bRec.its).average());
/* Microsurface normal distribution */
@@ -231,7 +226,7 @@ public:
const Float F = fresnel(dot(bRec.wi, H), m_extIOR, m_intIOR);
/* 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) {
/* 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 */
bool sampleReflection = ((bRec.component == -1 || bRec.component == 0)
&& (bRec.typeMask & EGlossyReflection)),
@@ -303,7 +301,7 @@ public:
}
/* Evaluate the roughness */
- Float alpha = m_distribution.transform(
+ Float alpha = m_distribution.transformRoughness(
m_alpha->getValue(bRec.its).average());
/* Suggestion by Bruce Walter: sample using a slightly different
@@ -386,7 +384,7 @@ public:
}
/* Evaluate the roughness */
- Float alpha = m_distribution.transform(
+ Float alpha = m_distribution.transformRoughness(
m_alpha->getValue(bRec.its).average());
/* Suggestion by Bruce Walter: sample using a slightly different
@@ -396,7 +394,7 @@ public:
std::abs(Frame::cosTheta(bRec.wi))));
/* Sample M, the microsurface normal */
- const Normal m = sampleD(sample, sampleAlpha);
+ const Normal m = m_distribution.sampleD(sample, sampleAlpha);
if (sampleExactFresnelTerm) {
sampleF = fresnel(dot(bRec.wi, m), m_extIOR, m_intIOR);
@@ -438,8 +436,7 @@ public:
}
Float numerator = m_distribution.eval(m, alpha)
- * m_distribution.smithG1(bRec.wi, m, alpha)
- * m_distribution.smithG1(bRec.wo, m, alpha)
+ * m_distribution.smithG(bRec.wi, bRec.wo, m, alpha)
* dot(bRec.wi, m);
Float denominator = m_distribution.eval(m, sampleAlpha)
@@ -508,7 +505,7 @@ public:
}
/* Evaluate the roughness */
- Float alpha = m_distribution.transform(
+ Float alpha = m_distribution.transformRoughness(
m_alpha->getValue(bRec.its).average());
/* Suggestion by Bruce Walter: sample using a slightly different
@@ -518,7 +515,7 @@ public:
std::abs(Frame::cosTheta(bRec.wi))));
/* Sample M, the microsurface normal */
- const Normal m = sampleD(sample, sampleAlpha);
+ const Normal m = m_distribution.sampleD(sample, sampleAlpha);
if (sampleExactFresnelTerm) {
Float sampleF = fresnel(dot(bRec.wi, m), m_extIOR, m_intIOR);
diff --git a/src/libcore/spectrum.cpp b/src/libcore/spectrum.cpp
index bc5f112b..fdeb1e24 100644
--- a/src/libcore/spectrum.cpp
+++ b/src/libcore/spectrum.cpp
@@ -96,6 +96,8 @@ Float Spectrum::m_wavelengths[SPECTRUM_SAMPLES + 1];
void Spectrum::staticInitialization() {
#if SPECTRUM_SAMPLES != 3
std::ostringstream oss;
+ oss << std::fixed;
+ oss.precision(2);
Float stepSize = SPECTRUM_RANGE / (Float) SPECTRUM_SAMPLES;
for (int i=0; i " << s[i];
+ << m_wavelengths[i+1] << "nm => ";
+ oss.precision(3);
+ oss << s[i];
#endif
if (i < SPECTRUM_SAMPLES - 1)
oss << ", ";
@@ -607,9 +613,13 @@ Float InterpolatedSpectrum::eval(Float lambda) const {
std::string InterpolatedSpectrum::toString() const {
std::ostringstream oss;
+ oss << std::fixed;
oss << "InterpolatedSpectrum[" << endl;
for (size_t i=0; i " << m_values[i];
+ oss.precision(1);
+ oss << " " << m_wavelengths[i] << " nm => ";
+ oss.precision(3);
+ oss << m_values[i];
if (i+1 < m_wavelengths.size())
oss << ",";
oss << endl;
diff --git a/src/libcore/util.cpp b/src/libcore/util.cpp
index de483653..31a84e45 100644
--- a/src/libcore/util.cpp
+++ b/src/libcore/util.cpp
@@ -687,16 +687,16 @@ Float fresnelDielectric(Float cosThetaI, Float cosThetaT,
return (Rs * Rs + Rp * Rp) / 2.0f;
}
-Spectrum fresnelConductor(Float cosTheta, const Spectrum &eta, const Spectrum &k) {
- Spectrum tmp = (eta*eta + k*k) * (cosTheta * cosTheta);
+Spectrum fresnelConductor(Float cosThetaI, const Spectrum &eta, const Spectrum &k) {
+ Spectrum tmp = (eta*eta + k*k) * (cosThetaI * cosThetaI);
- Spectrum rParl2 = (tmp - (eta * (2.0f * cosTheta)) + Spectrum(1.0f))
- / (tmp + (eta * (2.0f * cosTheta)) + Spectrum(1.0f));
+ Spectrum rParl2 = (tmp - (eta * (2.0f * cosThetaI)) + Spectrum(1.0f))
+ / (tmp + (eta * (2.0f * cosThetaI)) + Spectrum(1.0f));
Spectrum tmpF = eta*eta + k*k;
- Spectrum rPerp2 = (tmpF - (eta * (2.0f * cosTheta)) + Spectrum(cosTheta*cosTheta)) /
- (tmpF + (eta * (2.0f * cosTheta)) + Spectrum(cosTheta*cosTheta));
+ Spectrum rPerp2 = (tmpF - (eta * (2.0f * cosThetaI)) + Spectrum(cosThetaI*cosThetaI)) /
+ (tmpF + (eta * (2.0f * cosThetaI)) + Spectrum(cosThetaI*cosThetaI));
return (rParl2 + rPerp2) / 2.0f;
}