documentation updates, added a smooth plastic material
parent
4b95e7ba64
commit
2b140885e8
|
@ -2,7 +2,10 @@
|
||||||
to be tested for consistency. This is done
|
to be tested for consistency. This is done
|
||||||
using the testcase 'test_chisquare' -->
|
using the testcase 'test_chisquare' -->
|
||||||
<scene>
|
<scene>
|
||||||
<!-- Test the diffuse model -->
|
<!-- Test the smooth plastic model -->
|
||||||
|
<bsdf type="plastic"/>
|
||||||
|
|
||||||
|
<!-- Test the smooth diffuse model -->
|
||||||
<bsdf type="diffuse"/>
|
<bsdf type="diffuse"/>
|
||||||
|
|
||||||
<!-- Test the diffuse transmission model -->
|
<!-- Test the diffuse transmission model -->
|
||||||
|
@ -21,10 +24,10 @@
|
||||||
</bsdf>
|
</bsdf>
|
||||||
</bsdf>
|
</bsdf>
|
||||||
|
|
||||||
<!-- Test the conductor model -->
|
<!-- Test the smooth conductor model -->
|
||||||
<bsdf type="conductor"/>
|
<bsdf type="conductor"/>
|
||||||
|
|
||||||
<!-- Test the dielectric model -->
|
<!-- Test the smooth dielectric model -->
|
||||||
<bsdf type="dielectric">
|
<bsdf type="dielectric">
|
||||||
<string name="intIOR" value="water"/>
|
<string name="intIOR" value="water"/>
|
||||||
<string name="extIOR" value="air"/>
|
<string name="extIOR" value="air"/>
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
Import('env', 'plugins')
|
Import('env', 'plugins')
|
||||||
|
|
||||||
# Basic materials (smooth & rough versions of each)
|
# Basic materials (smooth & rough versions of each)
|
||||||
|
plugins += env.SharedLibrary('diffuse', ['diffuse.cpp'])
|
||||||
plugins += env.SharedLibrary('dielectric', ['dielectric.cpp'])
|
plugins += env.SharedLibrary('dielectric', ['dielectric.cpp'])
|
||||||
plugins += env.SharedLibrary('conductor', ['conductor.cpp'])
|
plugins += env.SharedLibrary('conductor', ['conductor.cpp'])
|
||||||
plugins += env.SharedLibrary('diffuse', ['diffuse.cpp'])
|
plugins += env.SharedLibrary('plastic', ['plastic.cpp'])
|
||||||
#plugins += env.SharedLibrary('plastic', ['plastic.cpp'])
|
|
||||||
|
|
||||||
|
#plugins += env.SharedLibrary('roughdiffuse', ['roughdiffuse.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('roughplastic', ['roughplastic.cpp'])
|
#plugins += env.SharedLibrary('roughplastic', ['roughplastic.cpp'])
|
||||||
|
|
||||||
# Other
|
# Other
|
||||||
|
|
|
@ -26,13 +26,13 @@ MTS_NAMESPACE_BEGIN
|
||||||
/*!\plugin{conductor}{Smooth conductor}
|
/*!\plugin{conductor}{Smooth conductor}
|
||||||
* \order{5}
|
* \order{5}
|
||||||
* \parameters{
|
* \parameters{
|
||||||
* \parameter{preset}{\String}{Name of a material preset, see
|
* \parameter{material}{\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
|
* \parameter{eta}{\Spectrum}{Real part of the material's index
|
||||||
* of refraction \default{based on the value of \texttt{preset}}}
|
* of refraction \default{based on the value of \texttt{material}}}
|
||||||
* \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{material}}}
|
||||||
* \lastparameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{
|
* \lastparameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{
|
||||||
* Optional factor used to modulate the reflectance component
|
* Optional factor used to modulate the reflectance component
|
||||||
* \default{1.0}}
|
* \default{1.0}}
|
||||||
|
@ -54,7 +54,7 @@ MTS_NAMESPACE_BEGIN
|
||||||
* considerable changes throughout the visible color spectrum.
|
* considerable changes throughout the visible color spectrum.
|
||||||
*
|
*
|
||||||
* To faciliate the tedious task of specifying spectrally-varying index of
|
* To 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
|
||||||
* several materials, where visible-spectrum information was publicly
|
* several materials, where visible-spectrum information was publicly
|
||||||
* available\footnote{
|
* available\footnote{
|
||||||
* These index of refraction values are identical to the data distributed
|
* These index of refraction values are identical to the data distributed
|
||||||
|
@ -74,14 +74,17 @@ MTS_NAMESPACE_BEGIN
|
||||||
* refraction (named ``ordinary'' and ``extraordinary ray'').
|
* refraction (named ``ordinary'' and ``extraordinary ray'').
|
||||||
*
|
*
|
||||||
* When using this plugin, you should ideally compile Mitsuba with support for
|
* When using this plugin, you should ideally compile Mitsuba with support for
|
||||||
* spectral renderings to get the most accurate results. While it also works
|
* spectral rendering to get the most accurate results. While it also works
|
||||||
* in RGB mode, the computations will be much more approximate in this case.
|
* in RGB mode, the computations will be much more approximate in this case.
|
||||||
|
* Also note that this material is one-sided---that is, observed from the
|
||||||
|
* back side, it will be completely black. If this is undesirable,
|
||||||
|
* consider using the \pluginref{twosided} BRDF adapter plugin.\vspace{4mm}
|
||||||
*
|
*
|
||||||
* \begin{xml}[caption=Material configuration for a smooth conductor with
|
* \begin{xml}[caption=A material configuration for a smooth conductor with
|
||||||
* measured gold data, label=lst:conductor-gold]
|
* measured gold data, label=lst:conductor-gold]
|
||||||
* <shape type="...">
|
* <shape type="...">
|
||||||
* <bsdf type="conductor">
|
* <bsdf type="conductor">
|
||||||
* <string name="preset" value="Au"/>
|
* <string name="material" value="Au"/>
|
||||||
* </bsdf>
|
* </bsdf>
|
||||||
* <shape>
|
* <shape>
|
||||||
* \end{xml}
|
* \end{xml}
|
||||||
|
@ -149,15 +152,15 @@ public:
|
||||||
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 material = props.getString("material", "Cu");
|
||||||
Spectrum presetEta, presetK;
|
Spectrum materialEta, materialK;
|
||||||
presetEta.fromContinuousSpectrum(InterpolatedSpectrum(
|
materialEta.fromContinuousSpectrum(InterpolatedSpectrum(
|
||||||
fResolver->resolve("data/ior/" + preset + ".eta.spd")));
|
fResolver->resolve("data/ior/" + material + ".eta.spd")));
|
||||||
presetK.fromContinuousSpectrum(InterpolatedSpectrum(
|
materialK.fromContinuousSpectrum(InterpolatedSpectrum(
|
||||||
fResolver->resolve("data/ior/" + preset + ".k.spd")));
|
fResolver->resolve("data/ior/" + material + ".k.spd")));
|
||||||
|
|
||||||
m_eta = props.getSpectrum("eta", presetEta);
|
m_eta = props.getSpectrum("eta", materialEta);
|
||||||
m_k = props.getSpectrum("k", presetK);
|
m_k = props.getSpectrum("k", materialK);
|
||||||
|
|
||||||
m_components.push_back(EDeltaReflection | EFrontSide);
|
m_components.push_back(EDeltaReflection | EFrontSide);
|
||||||
m_usesRayDifferentials = false;
|
m_usesRayDifferentials = false;
|
||||||
|
@ -193,7 +196,8 @@ public:
|
||||||
|
|
||||||
void configure() {
|
void configure() {
|
||||||
BSDF::configure();
|
BSDF::configure();
|
||||||
/* Verify the input parameter and fix them if necessary */
|
|
||||||
|
/* Verify the input parameters and fix them if necessary */
|
||||||
m_specularReflectance = ensureEnergyConservation(
|
m_specularReflectance = ensureEnergyConservation(
|
||||||
m_specularReflectance, "specularReflectance", 1.0f);
|
m_specularReflectance, "specularReflectance", 1.0f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,19 +98,19 @@ MTS_NAMESPACE_BEGIN
|
||||||
* \rmfamily \textbf{Name} & \multicolumn{2}{l}{\textbf{Value}}\\
|
* \rmfamily \textbf{Name} & \multicolumn{2}{l}{\textbf{Value}}\\
|
||||||
* \cmidrule{1-3} \cmidrule{5-7}
|
* \cmidrule{1-3} \cmidrule{5-7}
|
||||||
* vacuum & 1 & 0 & &
|
* vacuum & 1 & 0 & &
|
||||||
* silicone oil & 1 & 52045\\
|
|
||||||
* helium & 1 & 00004 & &
|
|
||||||
* bromine & 1 & 661\\
|
* bromine & 1 & 661\\
|
||||||
|
* helium & 1 & 00004 & &
|
||||||
|
* water ice & 1 & 31\\
|
||||||
* hydrogen & 1 & 00013& &
|
* hydrogen & 1 & 00013& &
|
||||||
* water ice & 1 & 31\\[-.8mm]
|
* fused quartz & 1 & 458\\[-.8mm]
|
||||||
* \cmidrule{5-7}\\[-5.5mm]
|
* \cmidrule{5-7}\\[-5.5mm]
|
||||||
* air & 1 & 00028& &
|
* air & 1 & 00028& &
|
||||||
* fused quartz & 1 & 458\\
|
* pyrex & 1 & 470\\
|
||||||
* carbon dioxide & 1 & 00045& &
|
* carbon dioxide & 1 & 00045& &
|
||||||
* pyrex & 1 & 470\\[-.8mm]
|
* acrylic glass & 1 & 49\\[-.8mm]
|
||||||
* \cmidrule{1-3}\\[-5.5mm]
|
* \cmidrule{1-3}\\[-5.5mm]
|
||||||
* water & 1 & 3330& &
|
* water & 1 & 3330& &
|
||||||
* acrylic glass & 1 & 490\\
|
* polypropylene & 1 & 49\\
|
||||||
* acetone & 1 & 36 & &
|
* acetone & 1 & 36 & &
|
||||||
* bk7 & 1 & 5046\\
|
* bk7 & 1 & 5046\\
|
||||||
* ethanol & 1 & 361& &
|
* ethanol & 1 & 361& &
|
||||||
|
@ -121,6 +121,7 @@ MTS_NAMESPACE_BEGIN
|
||||||
* pet & 1 & 575\\
|
* pet & 1 & 575\\
|
||||||
* benzene & 1 & 501& &
|
* benzene & 1 & 501& &
|
||||||
* diamond & 2 & 419\\
|
* diamond & 2 & 419\\
|
||||||
|
* silicone oil & 1 & 52045\\
|
||||||
* \bottomrule
|
* \bottomrule
|
||||||
* \end{tabular}
|
* \end{tabular}
|
||||||
* \caption{
|
* \caption{
|
||||||
|
@ -192,7 +193,8 @@ public:
|
||||||
|
|
||||||
void configure() {
|
void configure() {
|
||||||
BSDF::configure();
|
BSDF::configure();
|
||||||
/* Verify the input parameter and fix them if necessary */
|
|
||||||
|
/* Verify the input parameters and fix them if necessary */
|
||||||
m_specularReflectance = ensureEnergyConservation(
|
m_specularReflectance = ensureEnergyConservation(
|
||||||
m_specularReflectance, "specularReflectance", 1.0f);
|
m_specularReflectance, "specularReflectance", 1.0f);
|
||||||
m_specularTransmittance = ensureEnergyConservation(
|
m_specularTransmittance = ensureEnergyConservation(
|
||||||
|
@ -344,9 +346,8 @@ public:
|
||||||
cosThetaT = -cosThetaT;
|
cosThetaT = -cosThetaT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the refracted/reflected vectors+coefficients */
|
|
||||||
if (sampleTransmission && sampleReflection) {
|
if (sampleTransmission && sampleReflection) {
|
||||||
/* Importance sample according to the reflectance/transmittance */
|
/* Importance sample wrt. the Fresnel reflectance */
|
||||||
if (sample.x <= Fr) {
|
if (sample.x <= Fr) {
|
||||||
bRec.sampledComponent = 0;
|
bRec.sampledComponent = 0;
|
||||||
bRec.sampledType = EDeltaReflection;
|
bRec.sampledType = EDeltaReflection;
|
||||||
|
@ -426,9 +427,7 @@ public:
|
||||||
cosThetaT = -cosThetaT;
|
cosThetaT = -cosThetaT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the refracted/reflected vectors+coefficients */
|
|
||||||
if (sampleTransmission && sampleReflection) {
|
if (sampleTransmission && sampleReflection) {
|
||||||
/* Importance sample according to the reflectance/transmittance */
|
|
||||||
if (sample.x <= Fr) {
|
if (sample.x <= Fr) {
|
||||||
bRec.sampledComponent = 0;
|
bRec.sampledComponent = 0;
|
||||||
bRec.sampledType = EDeltaReflection;
|
bRec.sampledType = EDeltaReflection;
|
||||||
|
|
|
@ -65,7 +65,8 @@ public:
|
||||||
|
|
||||||
void configure() {
|
void configure() {
|
||||||
BSDF::configure();
|
BSDF::configure();
|
||||||
/* Verify the input parameter and fix them if necessary */
|
|
||||||
|
/* Verify the input parameters and fix them if necessary */
|
||||||
m_transmittance = ensureEnergyConservation(m_transmittance, "transmittance", 1.0f);
|
m_transmittance = ensureEnergyConservation(m_transmittance, "transmittance", 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ public:
|
||||||
|
|
||||||
void configure() {
|
void configure() {
|
||||||
BSDF::configure();
|
BSDF::configure();
|
||||||
|
|
||||||
/* Verify the input parameter and fix them if necessary */
|
/* Verify the input parameter and fix them if necessary */
|
||||||
m_reflectance = ensureEnergyConservation(m_reflectance, "reflectance", 1.0f);
|
m_reflectance = ensureEnergyConservation(m_reflectance, "reflectance", 1.0f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,8 @@ static IOREntry iorData[] = {
|
||||||
{ "water ice", 1.31f },
|
{ "water ice", 1.31f },
|
||||||
{ "fused quartz", 1.458f },
|
{ "fused quartz", 1.458f },
|
||||||
{ "pyrex", 1.470f },
|
{ "pyrex", 1.470f },
|
||||||
{ "acrylic glass", 1.490f },
|
{ "acrylic glass", 1.49f },
|
||||||
|
{ "polypropylene", 1.49f },
|
||||||
{ "bk7", 1.5046f },
|
{ "bk7", 1.5046f },
|
||||||
{ "sodium chloride", 1.544f },
|
{ "sodium chloride", 1.544f },
|
||||||
{ "amber", 1.55f },
|
{ "amber", 1.55f },
|
||||||
|
|
|
@ -17,40 +17,48 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <mitsuba/render/bsdf.h>
|
#include <mitsuba/render/bsdf.h>
|
||||||
#include <mitsuba/render/consttexture.h>
|
#include <mitsuba/render/texture.h>
|
||||||
|
#include "ior.h"
|
||||||
|
|
||||||
MTS_NAMESPACE_BEGIN
|
MTS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
/*! \plugin{plastic}{Smooth plastic material}
|
/*!\plugin{plastic}{Smooth plastic material}
|
||||||
*
|
* \order{7}
|
||||||
* \parameters{
|
* \parameters{
|
||||||
* \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{polypropylene} / 1.49}}
|
||||||
* \parameter{diffuse\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
|
* \parameter{extIOR}{\Float\Or\String}{Exterior index of refraction specified
|
||||||
* factor used to modulate the diffuse reflectance component\default{1.0}}
|
* 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 specular reflectance component\default{1.0}}
|
* factor used to modulate the specular component\default{1.0}}
|
||||||
|
* \lastparameter{specular\showbreak Transmittance}{\Spectrum\Or\Texture}{Optional
|
||||||
|
* factor used to modulate the diffuse component\default{0.5}}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* \renderings{
|
||||||
|
* \medrendering{Air$\leftrightarrow$Water (IOR: 1.33) interface.
|
||||||
|
* See \lstref{dielectric-water}.}{bsdf_dielectric_water}
|
||||||
|
* \medrendering{Air$\leftrightarrow$Diamond (IOR: 2.419)}{bsdf_dielectric_diamond}
|
||||||
|
* \medrendering{Air$\leftrightarrow$Glass (IOR: 1.504) interface and absorption within.
|
||||||
|
* See \lstref{dielectric-glass}.}{bsdf_dielectric_glass}
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
class SmoothPlastic : public BSDF {
|
class SmoothPlastic : public BSDF {
|
||||||
public:
|
public:
|
||||||
SmoothPlastic(const Properties &props)
|
SmoothPlastic(const Properties &props) : BSDF(props) {
|
||||||
: BSDF(props) {
|
|
||||||
/* Specifies the internal index of refraction at the interface */
|
/* Specifies the internal index of refraction at the interface */
|
||||||
m_intIOR = props.getFloat("intIOR", 1.5046f);
|
m_intIOR = lookupIOR(props, "intIOR", "polypropylene");
|
||||||
/* Specifies the external index of refraction at the interface */
|
|
||||||
m_extIOR = props.getFloat("extIOR", 1);
|
/* Specifies the external index of refraction at the interface */
|
||||||
|
m_extIOR = lookupIOR(props, "extIOR", "air");
|
||||||
|
|
||||||
m_diffuseReflectance = new ConstantSpectrumTexture(
|
|
||||||
props.getSpectrum("diffuseReflectance", Spectrum(0.5f)));
|
|
||||||
m_specularReflectance = new ConstantSpectrumTexture(
|
m_specularReflectance = new ConstantSpectrumTexture(
|
||||||
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
|
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
|
||||||
|
m_diffuseReflectance = new ConstantSpectrumTexture(
|
||||||
|
props.getSpectrum("diffuseReflectance", Spectrum(0.5f)));
|
||||||
|
|
||||||
m_componentCount = 2;
|
m_components.push_back(EDeltaReflection | EFrontSide);
|
||||||
m_type = new unsigned int[m_componentCount];
|
m_components.push_back(EDiffuseReflection | EFrontSide);
|
||||||
m_type[0] = EDiffuseReflection | EFrontSide;
|
|
||||||
m_type[1] = EDeltaTransmission | EFrontSide;
|
|
||||||
m_combinedType = m_type[0] | m_type[1];
|
|
||||||
m_usesRayDifferentials = false;
|
m_usesRayDifferentials = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,241 +66,225 @@ public:
|
||||||
: BSDF(stream, manager) {
|
: BSDF(stream, manager) {
|
||||||
m_intIOR = stream->readFloat();
|
m_intIOR = stream->readFloat();
|
||||||
m_extIOR = stream->readFloat();
|
m_extIOR = stream->readFloat();
|
||||||
m_diffuseReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
|
||||||
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||||
|
m_diffuseReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||||
m_componentCount = 2;
|
m_components.push_back(EDeltaReflection | EFrontSide);
|
||||||
m_type = new unsigned int[m_componentCount];
|
m_components.push_back(EDiffuseReflection | EFrontSide);
|
||||||
m_type[0] = EDiffuseReflection | EFrontSide;
|
|
||||||
m_type[1] = EDeltaTransmission | EFrontSide;
|
|
||||||
m_combinedType = m_type[0] | m_type[1];
|
|
||||||
m_usesRayDifferentials =
|
m_usesRayDifferentials =
|
||||||
m_diffuseReflectance->usesRayDifferentials() ||
|
m_specularReflectance->usesRayDifferentials() ||
|
||||||
m_specularReflectance->usesRayDifferentials();
|
m_diffuseReflectance->usesRayDifferentials();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~SmoothPlastic() {
|
virtual ~SmoothPlastic() { }
|
||||||
delete[] m_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
BSDF::serialize(stream, manager);
|
BSDF::serialize(stream, manager);
|
||||||
|
|
||||||
stream->writeFloat(m_intIOR);
|
stream->writeFloat(m_intIOR);
|
||||||
stream->writeFloat(m_extIOR);
|
stream->writeFloat(m_extIOR);
|
||||||
manager->serialize(stream, m_diffuseReflectance.get());
|
|
||||||
manager->serialize(stream, m_specularReflectance.get());
|
manager->serialize(stream, m_specularReflectance.get());
|
||||||
|
manager->serialize(stream, m_diffuseReflectance.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void addChild(const std::string &name, ConfigurableObject *child) {
|
void addChild(const std::string &name, ConfigurableObject *child) {
|
||||||
if (child->getClass()->derivesFrom(MTS_CLASS(Texture)) && name == "diffuseReflectance") {
|
if (child->getClass()->derivesFrom(MTS_CLASS(Texture)) && name == "specularReflectance") {
|
||||||
m_diffuseReflectance = static_cast<Texture *>(child);
|
|
||||||
m_usesRayDifferentials |= m_diffuseReflectance->usesRayDifferentials();
|
|
||||||
} else if (child->getClass()->derivesFrom(MTS_CLASS(Texture)) && name == "specularReflectance") {
|
|
||||||
m_specularReflectance = static_cast<Texture *>(child);
|
m_specularReflectance = static_cast<Texture *>(child);
|
||||||
m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials();
|
m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials();
|
||||||
|
} else if (child->getClass()->derivesFrom(MTS_CLASS(Texture)) && name == "diffuseReflectance") {
|
||||||
|
m_diffuseReflectance = static_cast<Texture *>(child);
|
||||||
|
m_usesRayDifferentials |= m_diffuseReflectance->usesRayDifferentials();
|
||||||
} else {
|
} else {
|
||||||
BSDF::addChild(name, child);
|
BSDF::addChild(name, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void configure() {
|
||||||
|
BSDF::configure();
|
||||||
|
|
||||||
|
/* Verify the input parameters and fix them if necessary */
|
||||||
|
m_specularReflectance = ensureEnergyConservation(
|
||||||
|
m_specularReflectance, "specularReflectance", 1.0f);
|
||||||
|
m_diffuseReflectance = ensureEnergyConservation(
|
||||||
|
m_diffuseReflectance, "diffuseReflectance", 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reflection in local coordinates
|
||||||
inline Vector reflect(const Vector &wi) const {
|
inline Vector reflect(const Vector &wi) const {
|
||||||
return Vector(-wi.x, -wi.y, wi.z);
|
return Vector(-wi.x, -wi.y, wi.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum f(const BSDFQueryRecord &bRec) const {
|
Spectrum eval(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||||
|
bool sampleSpecular = (bRec.typeMask & EDeltaReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
bool sampleDiffuse = (bRec.typeMask & EDiffuseReflection)
|
bool sampleDiffuse = (bRec.typeMask & EDiffuseReflection)
|
||||||
&& (bRec.component == -1 || bRec.component == 0);
|
&& (bRec.component == -1 || bRec.component == 1);
|
||||||
|
|
||||||
if (Frame::cosTheta(bRec.wi) <= 0 ||
|
if (Frame::cosTheta(bRec.wo) <= 0 || Frame::cosTheta(bRec.wi) <= 0)
|
||||||
Frame::cosTheta(bRec.wo) <= 0 || !sampleDiffuse)
|
|
||||||
return Spectrum(0.0f);
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
return m_diffuseReflectance->getValue(bRec.its) * INV_PI *
|
|
||||||
(1 - fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR));
|
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum fDelta(const BSDFQueryRecord &bRec) const {
|
|
||||||
bool sampleSpecular = (bRec.typeMask & EDeltaReflection)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 1);
|
|
||||||
if (Frame::cosTheta(bRec.wi) <= 0 ||
|
|
||||||
Frame::cosTheta(bRec.wo) <= 0 || !sampleSpecular)
|
|
||||||
return Spectrum(0.0f);
|
|
||||||
|
|
||||||
return m_specularReflectance->getValue(bRec.its) *
|
|
||||||
fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
Float pdf(const BSDFQueryRecord &bRec) const {
|
|
||||||
bool sampleDiffuse = (bRec.typeMask & EDiffuseReflection)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 0);
|
|
||||||
|
|
||||||
if (Frame::cosTheta(bRec.wi) <= 0 ||
|
|
||||||
Frame::cosTheta(bRec.wo) <= 0 || !sampleDiffuse)
|
|
||||||
return 0.0f;
|
|
||||||
|
|
||||||
bool sampleSpecular = (bRec.typeMask & EDeltaReflection)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 1);
|
|
||||||
|
|
||||||
Float pdf = Frame::cosTheta(bRec.wo) * INV_PI;
|
|
||||||
if (sampleSpecular)
|
|
||||||
pdf *= 1 - fresnel(Frame::cosTheta(bRec.wi),
|
|
||||||
m_extIOR, m_intIOR);
|
|
||||||
|
|
||||||
return pdf;
|
|
||||||
}
|
|
||||||
|
|
||||||
Float pdfDelta(const BSDFQueryRecord &bRec) const {
|
|
||||||
bool sampleSpecular = (bRec.typeMask & EDeltaReflection)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 1);
|
|
||||||
|
|
||||||
if (Frame::cosTheta(bRec.wi) <= 0 ||
|
|
||||||
Frame::cosTheta(bRec.wo) <= 0 || !sampleSpecular)
|
|
||||||
return 0.0f;
|
|
||||||
|
|
||||||
bool sampleDiffuse = (bRec.typeMask & EDiffuseReflection)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 0);
|
|
||||||
|
|
||||||
Float pdf = std::abs(Frame::cosTheta(bRec.wo));
|
|
||||||
if (sampleDiffuse)
|
|
||||||
pdf *= fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
|
||||||
|
|
||||||
return pdf;
|
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum sample(BSDFQueryRecord &bRec, Float &pdf, const Point2 &_sample) const {
|
|
||||||
bool sampleDiffuse = (bRec.typeMask & EDiffuseReflection)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 0);
|
|
||||||
bool sampleSpecular = (bRec.typeMask & EDeltaReflection)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 1);
|
|
||||||
|
|
||||||
if ((!sampleDiffuse && !sampleSpecular) || Frame::cosTheta(bRec.wi) <= 0)
|
|
||||||
return Spectrum(0.0f);
|
|
||||||
|
|
||||||
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
||||||
Point2 sample(_sample);
|
|
||||||
|
|
||||||
if (sampleDiffuse && sampleSpecular) {
|
if (measure == EDiscrete && sampleSpecular) {
|
||||||
if (sample.x > Fr) {
|
/* Check if the provided direction pair matches an ideal
|
||||||
sample.x = (sample.x - Fr) / (1 - Fr);
|
specular reflection; tolerate some roundoff errors */
|
||||||
bRec.wo = squareToHemispherePSA(sample);
|
bool reflection = std::abs(1 - dot(reflect(bRec.wi), bRec.wo)) < Epsilon;
|
||||||
bRec.sampledComponent = 0;
|
if (reflection)
|
||||||
bRec.sampledType = EDiffuseReflection;
|
|
||||||
pdf = Frame::cosTheta(bRec.wo) * INV_PI * (1-Fr);
|
|
||||||
return m_diffuseReflectance->getValue(bRec.its) * INV_PI * (1-Fr);
|
|
||||||
} else {
|
|
||||||
bRec.sampledComponent = 1;
|
|
||||||
bRec.sampledType = EDeltaReflection;
|
|
||||||
bRec.wo = reflect(bRec.wi);
|
|
||||||
pdf = std::abs(Frame::cosTheta(bRec.wo)) * Fr;
|
|
||||||
return m_specularReflectance->getValue(bRec.its) * Fr;
|
return m_specularReflectance->getValue(bRec.its) * Fr;
|
||||||
}
|
} else if (measure == ESolidAngle && sampleDiffuse) {
|
||||||
} else if (sampleDiffuse) {
|
if (sampleDiffuse)
|
||||||
bRec.wo = squareToHemispherePSA(sample);
|
return m_diffuseReflectance->getValue(bRec.its)
|
||||||
bRec.sampledComponent = 0;
|
* (INV_PI * Frame::cosTheta(bRec.wo) * (1-Fr));
|
||||||
bRec.sampledType = EDiffuseReflection;
|
|
||||||
pdf = Frame::cosTheta(bRec.wo) * INV_PI;
|
|
||||||
return m_diffuseReflectance->getValue(bRec.its) * INV_PI * (1-Fr);
|
|
||||||
} else {
|
|
||||||
bRec.sampledComponent = 1;
|
|
||||||
bRec.sampledType = EDeltaReflection;
|
|
||||||
bRec.wo = reflect(bRec.wi);
|
|
||||||
pdf = std::abs(Frame::cosTheta(bRec.wo));
|
|
||||||
return m_specularReflectance->getValue(bRec.its) * Fr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Spectrum(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &_sample) const {
|
Float pdf(const BSDFQueryRecord &bRec, EMeasure measure) const {
|
||||||
|
bool sampleSpecular = (bRec.typeMask & EDeltaReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
bool sampleDiffuse = (bRec.typeMask & EDiffuseReflection)
|
bool sampleDiffuse = (bRec.typeMask & EDiffuseReflection)
|
||||||
&& (bRec.component == -1 || bRec.component == 0);
|
&& (bRec.component == -1 || bRec.component == 1);
|
||||||
bool sampleSpecular = (bRec.typeMask & EDeltaReflection)
|
|
||||||
&& (bRec.component == -1 || bRec.component == 1);
|
|
||||||
|
|
||||||
if ((!sampleDiffuse && !sampleSpecular) || Frame::cosTheta(bRec.wi) <= 0)
|
if (Frame::cosTheta(bRec.wo) <= 0 || Frame::cosTheta(bRec.wi) <= 0)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
if (measure == EDiscrete && sampleSpecular) {
|
||||||
|
/* Check if the provided direction pair matches an ideal
|
||||||
|
specular reflection; tolerate some roundoff errors */
|
||||||
|
bool reflection = std::abs(1 - dot(reflect(bRec.wi), bRec.wo)) < Epsilon;
|
||||||
|
if (reflection)
|
||||||
|
return sampleDiffuse ?
|
||||||
|
fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR) : 1.0f;
|
||||||
|
} else if (measure == ESolidAngle && sampleDiffuse) {
|
||||||
|
return Frame::cosTheta(bRec.wo) * INV_PI *
|
||||||
|
sampleSpecular ? (1 - fresnel(Frame::cosTheta(bRec.wi),
|
||||||
|
m_extIOR, m_intIOR)) : 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Spectrum sample(BSDFQueryRecord &bRec, const Point2 &sample) const {
|
||||||
|
bool sampleSpecular = (bRec.typeMask & EDeltaReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
|
bool sampleDiffuse = (bRec.typeMask & EDiffuseReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 1);
|
||||||
|
|
||||||
|
if ((!sampleDiffuse && !sampleSpecular) || Frame::cosTheta(bRec.wi) < 0)
|
||||||
return Spectrum(0.0f);
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
||||||
Point2 sample(_sample);
|
|
||||||
|
|
||||||
if (sampleDiffuse && sampleSpecular) {
|
if (sampleDiffuse && sampleSpecular) {
|
||||||
if (sample.x > Fr) {
|
/* Importance sample wrt. the Fresnel reflectance */
|
||||||
sample.x = (sample.x - Fr) / (1 - Fr);
|
if (sample.x <= Fr) {
|
||||||
bRec.wo = squareToHemispherePSA(sample);
|
|
||||||
bRec.sampledComponent = 0;
|
bRec.sampledComponent = 0;
|
||||||
bRec.sampledType = EDiffuseReflection;
|
|
||||||
return m_diffuseReflectance->getValue(bRec.its)
|
|
||||||
/ Frame::cosTheta(bRec.wo);
|
|
||||||
} else {
|
|
||||||
bRec.sampledComponent = 1;
|
|
||||||
bRec.sampledType = EDeltaReflection;
|
bRec.sampledType = EDeltaReflection;
|
||||||
bRec.wo = reflect(bRec.wi);
|
bRec.wo = reflect(bRec.wi);
|
||||||
return m_specularReflectance->getValue(bRec.its)
|
|
||||||
/ std::abs(Frame::cosTheta(bRec.wo));
|
return m_specularReflectance->getValue(bRec.its);
|
||||||
|
} else {
|
||||||
|
bRec.sampledComponent = 1;
|
||||||
|
bRec.sampledType = EDiffuseReflection;
|
||||||
|
bRec.wo = squareToHemispherePSA(Point2(
|
||||||
|
(sample.x - Fr) / (1 - Fr),
|
||||||
|
sample.y
|
||||||
|
));
|
||||||
|
|
||||||
|
return m_diffuseReflectance->getValue(bRec.its);
|
||||||
}
|
}
|
||||||
} else if (sampleDiffuse) {
|
} else if (sampleSpecular) {
|
||||||
bRec.wo = squareToHemispherePSA(sample);
|
|
||||||
bRec.sampledComponent = 0;
|
bRec.sampledComponent = 0;
|
||||||
bRec.sampledType = EDiffuseReflection;
|
|
||||||
return m_diffuseReflectance->getValue(bRec.its) * (1-Fr)
|
|
||||||
/ Frame::cosTheta(bRec.wo);
|
|
||||||
} else {
|
|
||||||
bRec.sampledComponent = 1;
|
|
||||||
bRec.sampledType = EDeltaReflection;
|
bRec.sampledType = EDeltaReflection;
|
||||||
bRec.wo = reflect(bRec.wi);
|
bRec.wo = reflect(bRec.wi);
|
||||||
return m_specularReflectance->getValue(bRec.its) * Fr
|
return m_specularReflectance->getValue(bRec.its) * Fr;
|
||||||
/ std::abs(Frame::cosTheta(bRec.wo));
|
} else {
|
||||||
|
bRec.sampledComponent = 1;
|
||||||
|
bRec.sampledType = EDiffuseReflection;
|
||||||
|
|
||||||
|
if (Fr == 1.0f) /* Total internal reflection */
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
|
bRec.wo = squareToSphere(sample);
|
||||||
|
|
||||||
|
return m_diffuseReflectance->getValue(bRec.its) * (1-Fr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spectrum sample(BSDFQueryRecord &bRec, Float &pdf, const Point2 &sample) const {
|
||||||
|
bool sampleSpecular = (bRec.typeMask & EDeltaReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 0);
|
||||||
|
bool sampleDiffuse = (bRec.typeMask & EDiffuseReflection)
|
||||||
|
&& (bRec.component == -1 || bRec.component == 1);
|
||||||
|
|
||||||
|
if ((!sampleDiffuse && !sampleSpecular) || Frame::cosTheta(bRec.wi) < 0)
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
|
Float Fr = fresnel(Frame::cosTheta(bRec.wi), m_extIOR, m_intIOR);
|
||||||
|
|
||||||
|
if (sampleDiffuse && sampleSpecular) {
|
||||||
|
/* Importance sample wrt. the Fresnel reflectance */
|
||||||
|
if (sample.x <= Fr) {
|
||||||
|
bRec.sampledComponent = 0;
|
||||||
|
bRec.sampledType = EDeltaReflection;
|
||||||
|
bRec.wo = reflect(bRec.wi);
|
||||||
|
|
||||||
|
pdf = Fr;
|
||||||
|
return m_specularReflectance->getValue(bRec.its) * Fr;
|
||||||
|
} else {
|
||||||
|
bRec.sampledComponent = 1;
|
||||||
|
bRec.sampledType = EDiffuseReflection;
|
||||||
|
bRec.wo = squareToHemispherePSA(Point2(
|
||||||
|
(sample.x - Fr) / (1 - Fr),
|
||||||
|
sample.y
|
||||||
|
));
|
||||||
|
|
||||||
|
pdf = (1-Fr) * Frame::cosTheta(bRec.wo) * INV_PI;
|
||||||
|
|
||||||
|
return m_diffuseReflectance->getValue(bRec.its)
|
||||||
|
* (INV_PI * Frame::cosTheta(bRec.wo) * (1-Fr));
|
||||||
|
}
|
||||||
|
} else if (sampleSpecular) {
|
||||||
|
bRec.sampledComponent = 0;
|
||||||
|
bRec.sampledType = EDeltaReflection;
|
||||||
|
bRec.wo = reflect(bRec.wi);
|
||||||
|
pdf = 1;
|
||||||
|
return m_specularReflectance->getValue(bRec.its) * Fr;
|
||||||
|
} else {
|
||||||
|
bRec.sampledComponent = 1;
|
||||||
|
bRec.sampledType = EDiffuseReflection;
|
||||||
|
|
||||||
|
if (Fr == 1.0f) /* Total internal reflection */
|
||||||
|
return Spectrum(0.0f);
|
||||||
|
|
||||||
|
bRec.wo = squareToSphere(sample);
|
||||||
|
|
||||||
|
pdf = Frame::cosTheta(bRec.wo) * INV_PI;
|
||||||
|
|
||||||
|
return m_diffuseReflectance->getValue(bRec.its)
|
||||||
|
* (INV_PI * Frame::cosTheta(bRec.wo) * (1-Fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "SmoothPlastic[" << endl
|
oss << "SmoothPlastic[" << endl
|
||||||
|
<< " name = \"" << getName() << "\"," << endl
|
||||||
<< " intIOR = " << m_intIOR << "," << endl
|
<< " intIOR = " << m_intIOR << "," << endl
|
||||||
<< " extIOR = " << m_extIOR << "," << endl
|
<< " extIOR = " << m_extIOR << "," << endl
|
||||||
<< " diffuseReflectance = " << indent(m_diffuseReflectance->toString()) << "," << endl
|
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << "," << endl
|
||||||
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << endl
|
<< " diffuseReflectance = " << indent(m_diffuseReflectance->toString()) << endl
|
||||||
<< "]";
|
<< "]";
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader *createShader(Renderer *renderer) const;
|
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
MTS_DECLARE_CLASS()
|
||||||
private:
|
private:
|
||||||
Float m_intIOR, m_extIOR;
|
Float m_intIOR, m_extIOR;
|
||||||
ref<Texture> m_specularReflectance;
|
|
||||||
ref<Texture> m_diffuseReflectance;
|
ref<Texture> m_diffuseReflectance;
|
||||||
|
ref<Texture> m_specularReflectance;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Fake glass shader -- it is really hopeless to visualize
|
|
||||||
this material in the VPL renderer, so let's try to do at least
|
|
||||||
something that suggests the presence of a transparent boundary */
|
|
||||||
class SmoothPlasticShader : public Shader {
|
|
||||||
public:
|
|
||||||
SmoothPlasticShader(Renderer *renderer) :
|
|
||||||
Shader(renderer, EBSDFShader) {
|
|
||||||
m_flags = ETransparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void generateCode(std::ostringstream &oss,
|
|
||||||
const std::string &evalName,
|
|
||||||
const std::vector<std::string> &depNames) const {
|
|
||||||
oss << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
|
||||||
<< " return vec3(0.08);" << endl
|
|
||||||
<< "}" << endl;
|
|
||||||
oss << "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
|
||||||
<< " return vec3(0.08);" << endl
|
|
||||||
<< "}" << endl;
|
|
||||||
}
|
|
||||||
MTS_DECLARE_CLASS()
|
|
||||||
};
|
|
||||||
|
|
||||||
Shader *SmoothPlastic::createShader(Renderer *renderer) const {
|
|
||||||
return new SmoothPlasticShader(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS(SmoothPlasticShader, false, Shader)
|
|
||||||
MTS_IMPLEMENT_CLASS_S(SmoothPlastic, false, BSDF)
|
MTS_IMPLEMENT_CLASS_S(SmoothPlastic, false, BSDF)
|
||||||
MTS_EXPORT_PLUGIN(SmoothPlastic, "Smooth plastic BSDF");
|
MTS_EXPORT_PLUGIN(SmoothPlastic, "Smooth plastic BSDF");
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
|
@ -67,24 +67,92 @@ MTS_NAMESPACE_BEGIN
|
||||||
* bitangent directions. These parameter are only valid when
|
* bitangent directions. These parameter are only valid when
|
||||||
* \texttt{distribution=as}. \default{0.1}.
|
* \texttt{distribution=as}. \default{0.1}.
|
||||||
* }
|
* }
|
||||||
* \parameter{preset}{\String}{Name of a material preset, see
|
* \parameter{material}{\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
|
* \parameter{eta}{\Spectrum}{Real part of the material's index
|
||||||
* of refraction \default{based on the value of \texttt{preset}}}
|
* of refraction \default{based on the value of \texttt{material}}}
|
||||||
* \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{material}}}
|
||||||
* \lastparameter{specular\showbreak Reflectance}{\Spectrum\Or\Texture}{Optional
|
* \lastparameter{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}}
|
||||||
* }
|
* }
|
||||||
|
* This plugin implements a realistic microfacet scattering model for rendering
|
||||||
|
* rough conducting materials, such as metals. Microfacet theory describes rough
|
||||||
|
* surfaces as an arrangement of unresolved and ideally specular facets, whose
|
||||||
|
* normal directions are given by a specially chosen \emph{microfacet distribution}.
|
||||||
|
* By accounting for shadowing and masking effects between these facets, it is
|
||||||
|
* possible to reproduce the important off-specular reflections peaks observed
|
||||||
|
* in real-world measurements of such materials.
|
||||||
|
|
||||||
* \renderings{
|
* \renderings{
|
||||||
* \rendering{Rough copper (Beckmann, $\alpha=0.1$)}
|
* \rendering{Rough copper (Beckmann, $\alpha=0.1$)}
|
||||||
* {bsdf_roughconductor_copper.jpg}
|
* {bsdf_roughconductor_copper.jpg}
|
||||||
* \rendering{Vertically brushed aluminium (Ashikhmin-Shirley,
|
* \rendering{Vertically brushed aluminium (Ashikhmin-Shirley,
|
||||||
* $\alpha_u=0.05,\
|
* $\alpha_u=0.05,\ \alpha_v=0.3$), see
|
||||||
* \alpha_v=0.3$)}{bsdf_roughconductor_anisotropic_aluminium.jpg}
|
* \lstref{roughconductor-aluminium}}
|
||||||
|
* {bsdf_roughconductor_anisotropic_aluminium.jpg}
|
||||||
|
* \vspace{-7mm}
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
|
* This plugin is essentially the ``roughened'' equivalent of the (smooth) plugin
|
||||||
|
* \pluginref{conductor}. For very low values of $\alpha$, the two will
|
||||||
|
* be very similar, though scenes using this plugin will take longer to render
|
||||||
|
* due to the additional computational burden of tracking surface roughness.
|
||||||
|
*
|
||||||
|
* The implementation is based on the paper ``Microfacet Models
|
||||||
|
* 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
|
||||||
|
* 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).
|
||||||
|
*
|
||||||
|
* When no parameters are given, the plugin activates the default settings,
|
||||||
|
* which describe copper with a light amount of roughness modeled using a
|
||||||
|
* Beckmann distribution.
|
||||||
|
*
|
||||||
|
* To get an intuition about the effect of the surface roughness
|
||||||
|
* parameter $\alpha$, consider the following approximate differentiation:
|
||||||
|
* a value of $\alpha=0.001-0.01$ corresponds to a material
|
||||||
|
* with slight imperfections on an
|
||||||
|
* otherwise smooth surface finish, $\alpha=0.1$ is relatively rough,
|
||||||
|
* and $\alpha=0.3-0.5$ is \emph{extremely} rough (e.g. an etched or ground
|
||||||
|
* finish).
|
||||||
|
* \vspace{-2mm}
|
||||||
|
* \subsubsection*{Techical 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.
|
||||||
|
* This is done in a way, such that the different
|
||||||
|
* distributions all produce a similar appearance for the same value of
|
||||||
|
* $\alpha$.
|
||||||
|
*
|
||||||
|
* The Ashikhmin-Shirley microfacet distribution allows the specification
|
||||||
|
* of two distinct roughness values along the tangent and bitangent
|
||||||
|
* directions. This can be used to provide a material with a ``brushed''
|
||||||
|
* appearance. The alignment of the anisotropy will follow the UV
|
||||||
|
* parameterization of the underlying mesh in this case. This means that
|
||||||
|
* such an anisotropic material cannot be applied to triangle meshes that
|
||||||
|
* are missing texture coordinates.
|
||||||
|
*
|
||||||
|
* When using this plugin, you should ideally compile Mitsuba with support for
|
||||||
|
* spectral rendering to get the most accurate results. While it also works
|
||||||
|
* in RGB mode, the computations will be much more approximate in this case.
|
||||||
|
* Also note that this material is one-sided---that is, observed from the
|
||||||
|
* back side, it will be completely black. If this is undesirable,
|
||||||
|
* consider using the \pluginref{twosided} BRDF adapter plugin.
|
||||||
|
*
|
||||||
|
* \begin{xml}[caption={A material definition for brushed aluminium}, label=lst:roughconductor-aluminium]
|
||||||
|
* <bsdf type="roughconductor">
|
||||||
|
* <string name="material" value="Cu"/>
|
||||||
|
* <string name="distribution" value="as"/>
|
||||||
|
* <float name="alphaU" value="0.05"/>
|
||||||
|
* <float name="alphaV" value="0.3"/>
|
||||||
|
* </bsdf>
|
||||||
|
* \end{xml}
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
class RoughConductor : public BSDF {
|
class RoughConductor : public BSDF {
|
||||||
public:
|
public:
|
||||||
|
@ -94,15 +162,15 @@ public:
|
||||||
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 material = props.getString("material", "Cu");
|
||||||
Spectrum presetEta, presetK;
|
Spectrum materialEta, materialK;
|
||||||
presetEta.fromContinuousSpectrum(InterpolatedSpectrum(
|
materialEta.fromContinuousSpectrum(InterpolatedSpectrum(
|
||||||
fResolver->resolve("data/ior/" + preset + ".eta.spd")));
|
fResolver->resolve("data/ior/" + material + ".eta.spd")));
|
||||||
presetK.fromContinuousSpectrum(InterpolatedSpectrum(
|
materialK.fromContinuousSpectrum(InterpolatedSpectrum(
|
||||||
fResolver->resolve("data/ior/" + preset + ".k.spd")));
|
fResolver->resolve("data/ior/" + material + ".k.spd")));
|
||||||
|
|
||||||
m_eta = props.getSpectrum("eta", presetEta);
|
m_eta = props.getSpectrum("eta", materialEta);
|
||||||
m_k = props.getSpectrum("k", presetK);
|
m_k = props.getSpectrum("k", materialK);
|
||||||
|
|
||||||
m_distribution = MicrofacetDistribution(
|
m_distribution = MicrofacetDistribution(
|
||||||
props.getString("distribution", "beckmann")
|
props.getString("distribution", "beckmann")
|
||||||
|
@ -156,7 +224,7 @@ public:
|
||||||
m_components.push_back(
|
m_components.push_back(
|
||||||
EGlossyReflection | EFrontSide | extraFlags);
|
EGlossyReflection | EFrontSide | extraFlags);
|
||||||
|
|
||||||
/* Verify the input parameter and fix them if necessary */
|
/* Verify the input parameters and fix them if necessary */
|
||||||
m_specularReflectance = ensureEnergyConservation(
|
m_specularReflectance = ensureEnergyConservation(
|
||||||
m_specularReflectance, "specularReflectance", 1.0f);
|
m_specularReflectance, "specularReflectance", 1.0f);
|
||||||
|
|
||||||
|
|
|
@ -241,7 +241,7 @@ public:
|
||||||
m_components.push_back(
|
m_components.push_back(
|
||||||
EGlossyTransmission | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
|
EGlossyTransmission | EFrontSide | EBackSide | ECanUseSampler | extraFlags);
|
||||||
|
|
||||||
/* Verify the input parameter and fix them if necessary */
|
/* Verify the input parameters and fix them if necessary */
|
||||||
m_specularReflectance = ensureEnergyConservation(
|
m_specularReflectance = ensureEnergyConservation(
|
||||||
m_specularReflectance, "specularReflectance", 1.0f);
|
m_specularReflectance, "specularReflectance", 1.0f);
|
||||||
m_specularTransmittance = ensureEnergyConservation(
|
m_specularTransmittance = ensureEnergyConservation(
|
||||||
|
|
|
@ -173,9 +173,11 @@ public:
|
||||||
mismatch = true;
|
mismatch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mismatch)
|
if (mismatch) {
|
||||||
Log(EWarn, "Potential inconsistency (3): f/pdf=%s (method 1), f/pdf=%s (methdod 2), sampled f/pdf=%s",
|
Log(EWarn, "Potential inconsistency (3): f/pdf=%s (method 1), f/pdf=%s (method 2), sampled f/pdf=%s",
|
||||||
sampled2.toString().c_str(), evaluated.toString().c_str(), sampled.toString().c_str());
|
sampled2.toString().c_str(), evaluated.toString().c_str(), sampled.toString().c_str());
|
||||||
|
Log(EWarn, " f=%s, f2=%s, pdf=%f, pdf2=%f", f.toString().c_str(), f.toString().c_str(), pdfVal, pdfVal2);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(MTS_DEBUG_FP)
|
#if defined(MTS_DEBUG_FP)
|
||||||
disableFPExceptions();
|
disableFPExceptions();
|
||||||
|
|
Loading…
Reference in New Issue