added a function for computing the diffuse fresnel reflectance (aka Fdr)

metadata
Wenzel Jakob 2011-09-07 00:35:02 -04:00
parent 1a8d3b096e
commit 213e550e2f
4 changed files with 88 additions and 23 deletions

View File

@ -463,6 +463,20 @@ extern MTS_EXPORT_CORE Point2 squareToStdNormal(const Point2 &sample);
extern MTS_EXPORT_CORE Float fresnelDielectric(Float cosThetaI, extern MTS_EXPORT_CORE Float fresnelDielectric(Float cosThetaI,
Float cosThetaT, Float etaI, Float etaT); Float cosThetaT, Float etaI, Float etaT);
/**
* \brief Calculates the unpolarized fresnel reflection coefficient on
* an interface to a conductor.
*
* \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
* Real refractive index (wavelength-dependent)
* \param k
* Imaginary refractive index (wavelength-dependent)
*/
extern MTS_EXPORT_CORE Spectrum fresnelConductor(Float cosThetaI,
const Spectrum &eta, const Spectrum &k);
/** /**
* \brief Calculates the unpolarized fresnel reflection coefficient for a * \brief Calculates the unpolarized fresnel reflection coefficient for a
* dielectric material. Handles incidence from either sides. * dielectric material. Handles incidence from either sides.
@ -479,7 +493,7 @@ extern MTS_EXPORT_CORE Float fresnel(Float cosThetaI, Float extIOR,
/** /**
* \brief Calculates the diffuse unpolarized fresnel reflectance of * \brief Calculates the diffuse unpolarized fresnel reflectance of
* a dielectric material. * a dielectric material (sometimes referred to as "Fdr").
* *
* This value quantifies what fraction of completely diffuse incident * This value quantifies what fraction of completely diffuse incident
* illumination will be reflected by a dielectric material on average. * illumination will be reflected by a dielectric material on average.
@ -495,21 +509,8 @@ extern MTS_EXPORT_CORE Float fresnel(Float cosThetaI, Float extIOR,
* a wider range of refraction coefficients, but at a cost * a wider range of refraction coefficients, but at a cost
* in terms of performance. * in terms of performance.
*/ */
extern MTS_EXPORT_CORE Float diffuseFresnelReflectance(Float eta, bool fast = false); extern MTS_EXPORT_CORE Float fresnelDiffuseReflectance(
Float eta, bool fast = false);
/**
* \brief Calculates the unpolarized fresnel reflection coefficient on
* an interface to a conductor.
*
* \param cosThetaI
* Cosine of the angle between the normal and the incident ray
* \param eta
* Real refractive index (wavelength-dependent)
* \param k
* Imaginary refractive index (wavelength-dependent)
*/
extern MTS_EXPORT_CORE Spectrum fresnelConductor(Float cosThetaI,
const Spectrum &eta, const Spectrum &k);
/*! @} */ /*! @} */

View File

@ -78,8 +78,6 @@ public:
if (eta > 1) { if (eta > 1) {
return -1.440f / (eta * eta) + 0.710f / eta + 0.668f + 0.0636f * eta; return -1.440f / (eta * eta) + 0.710f / eta + 0.668f + 0.0636f * eta;
} else if (eta < 1) { } else if (eta < 1) {
/* Average reflectance due to mismatched indices of refraction
* at the boundary - [Egan et al. 1973] */
return -0.4399f + 0.7099f / eta - 0.3319f / (eta * eta) return -0.4399f + 0.7099f / eta - 0.3319f / (eta * eta)
+ 0.0636f / (eta * eta * eta); + 0.0636f / (eta * eta * eta);
} else { } else {
@ -107,11 +105,10 @@ public:
m_usesRayDifferentials = m_sigmaS->usesRayDifferentials() m_usesRayDifferentials = m_sigmaS->usesRayDifferentials()
|| m_sigmaA->usesRayDifferentials(); || m_sigmaA->usesRayDifferentials();
/* relative index of refraction */ /* Numerically approximate the diffuse Fresnel reflectance */
const Float eta = m_intIOR / m_extIOR; const Float Fdr = fresnelDiffuse(m_extIOR / m_intIOR, false);
/* Approximate DipoleBRDF boundary condition term */ /* Compute the extrapolation distance */
const Float Fdr = evalFdr(eta);
m_A = (1 + Fdr) / (1 - Fdr); m_A = (1 + Fdr) / (1 - Fdr);
BSDF::configure(); BSDF::configure();

View File

@ -17,6 +17,8 @@
*/ */
#include <mitsuba/core/random.h> #include <mitsuba/core/random.h>
#include <mitsuba/core/quad.h>
#include <boost/bind.hpp>
#include <stdarg.h> #include <stdarg.h>
#include <iomanip> #include <iomanip>
#include <errno.h> #include <errno.h>
@ -584,7 +586,6 @@ void latinHypercube(Random *random, Float *dest, size_t nSamples, size_t nDim) {
} }
} }
Vector sphericalDirection(Float theta, Float phi) { Vector sphericalDirection(Float theta, Float phi) {
Float sinTheta, cosTheta, sinPhi, cosPhi; Float sinTheta, cosTheta, sinPhi, cosPhi;
@ -727,6 +728,9 @@ Float lanczosSinc(Float t, Float tau) {
by Paul S. Heckbert. */ by Paul S. Heckbert. */
Float fresnelDielectric(Float cosThetaI, Float cosThetaT, Float fresnelDielectric(Float cosThetaI, Float cosThetaT,
Float etaI, Float etaT) { Float etaI, Float etaT) {
if (etaI == etaT)
return 0.0f;
Float Rs = (etaI * cosThetaI - etaT * cosThetaT) Float Rs = (etaI * cosThetaI - etaT * cosThetaT)
/ (etaI * cosThetaI + etaT * cosThetaT); / (etaI * cosThetaI + etaT * cosThetaT);
Float Rp = (etaT * cosThetaI - etaI * cosThetaT) Float Rp = (etaT * cosThetaI - etaI * cosThetaT)
@ -772,6 +776,63 @@ Float fresnel(Float cosThetaI, Float extIOR, Float intIOR) {
cosThetaT, etaI, etaT); cosThetaT, etaI, etaT);
} }
static Float fresnelDiffuseIntegrand(Float eta, Float xi) {
if (eta > 1)
return fresnel(std::sqrt(xi), 1, eta);
else
return fresnel(std::sqrt(xi), 1/eta, 1);
}
Float fresnelDiffuseReflectance(Float eta, bool fast) {
if (fast) {
/* Fast mode: the following code approximates the
* diffuse Frensel reflectance for the eta<1 and
* eta>1 cases. An evalution of the accuracy led
* to the following scheme, which cherry-picks
* fits from two papers where they are best.
*/
if (eta < 1) {
/* Fit by Egan and Hilgeman (1973). Works
reasonably well for "normal" IOR values (<2).
Max rel. error in 1.0 - 1.5 : 0.1%
Max rel. error in 1.5 - 2 : 0.6%
Max rel. error in 2.0 - 5 : 9.5%
*/
return -1.4399f * (eta * eta)
+ 0.7099f * eta
+ 0.6681f
+ 0.0636f / eta;
} else {
/* Fit by d'Eon and Irving (2011)
*
* Maintains a good accuracy even for
* unrealistic IOR values.
*
* Max rel. error in 1.0 - 2.0 : 0.1%
* Max rel. error in 2.0 - 10.0 : 0.2%
*/
Float invEta = 1.0f / eta,
invEta2 = invEta*invEta,
invEta3 = invEta2*invEta,
invEta4 = invEta3*invEta,
invEta5 = invEta4*invEta;
return 0.919317f - 3.4793f * invEta
+ 6.75335f * invEta2
- 7.80989f * invEta3
+ 4.98554f * invEta4
- 1.36881f * invEta5;
}
} else {
GaussLobattoIntegrator quad(1024, 0, 1e-5f);
return quad.integrate(
boost::bind(&fresnelDiffuseIntegrand, eta, _1), 0, 1);
}
return 0.0f;
}
Float radicalInverse(int b, size_t i) { Float radicalInverse(int b, size_t i) {
Float invB = (Float) 1 / (Float) b; Float invB = (Float) 1 / (Float) b;
Float x = 0.0f, f = invB; Float x = 0.0f, f = invB;

View File

@ -1061,6 +1061,12 @@ void export_core() {
.staticmethod("glOrthographic") .staticmethod("glOrthographic")
.staticmethod("fromFrame"); .staticmethod("fromFrame");
/* Functions from utility.h */
bp::def("fresnel", &fresnel);
bp::def("fresnelDielectric", &fresnelDielectric);
bp::def("fresnelConductor", &fresnelConductor, BP_RETURN_VALUE);
bp::def("fresnelDiffuseReflectance", &fresnelDiffuseReflectance);
bp::detail::current_scope = oldScope; bp::detail::current_scope = oldScope;
} }