added a function for computing the diffuse fresnel reflectance (aka Fdr)
parent
1a8d3b096e
commit
213e550e2f
|
@ -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);
|
|
||||||
|
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue