added MicrofacetDistribution::computeTransmissionProbability
parent
1debcf3c0b
commit
0803cba093
|
@ -421,19 +421,21 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Precompute the aggregate Fresnel transmittance through
|
* \brief Compute a spline representation for the overall Fresnel
|
||||||
* a rough interface
|
* transmittance through a rough interface
|
||||||
*
|
*
|
||||||
* This function efficiently computes the integral of
|
* This function essentially computes the integral of
|
||||||
* \int_{S^2} D(m) * (1 - Fr(m<->wi)) dm
|
* 1 - \int_{S^2} f(w_i, w_o) * dw_o
|
||||||
* for incident directions 'wi' with a range of different inclinations
|
* for incident directions 'wi' with a range of different inclinations
|
||||||
* (where Fr denotes the fresnel reflectance). It returns a cubic spline
|
* (where f denotes a Cook-Torrance style reflectance model). It returns
|
||||||
* interpolation parameterized by the cosine of the angle between 'wi'
|
* a cubic spline interpolation parameterized by the cosine of the angle
|
||||||
* and the (macro-) surface normal.
|
* between 'wi' and the (macro-) surface normal.
|
||||||
|
*
|
||||||
|
* \remark This only works for isotropic microfacet distributions
|
||||||
*/
|
*/
|
||||||
CubicSpline *getRoughTransmittance(Float extIOR, Float intIOR, Float alpha, size_t resolution) const {
|
CubicSpline *computeRoughTransmittance(Float extIOR, Float intIOR, Float alpha, size_t resolution) const {
|
||||||
if (isAnisotropic())
|
if (isAnisotropic())
|
||||||
SLog(EError, "MicrofacetDistribution::getRoughTransmission(): only "
|
SLog(EError, "MicrofacetDistribution::computeRoughTransmission(): only "
|
||||||
"supports isotropic distributions!");
|
"supports isotropic distributions!");
|
||||||
|
|
||||||
NDIntegrator integrator(1, 2, 5000, 0, 1e-5f);
|
NDIntegrator integrator(1, 2, 5000, 0, 1e-5f);
|
||||||
|
@ -449,7 +451,7 @@ public:
|
||||||
integral = 0, error = 0;
|
integral = 0, error = 0;
|
||||||
|
|
||||||
integrator.integrateVectorized(
|
integrator.integrateVectorized(
|
||||||
boost::bind(&MicrofacetDistribution::integrand, this,
|
boost::bind(&MicrofacetDistribution::integrand1, this,
|
||||||
wi, extIOR, intIOR, alpha, _1, _2, _3),
|
wi, extIOR, intIOR, alpha, _1, _2, _3),
|
||||||
min, max, &integral, &error, &nEvals
|
min, max, &integral, &error, &nEvals
|
||||||
);
|
);
|
||||||
|
@ -465,6 +467,52 @@ public:
|
||||||
return spline;
|
return spline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compute a spline representation that gives the probability
|
||||||
|
* of sampling a transmission event e.g. in the plugin 'roughdielectric'.
|
||||||
|
*
|
||||||
|
* Like \ref computeRoughTransmittance, the spline is parameterized by the
|
||||||
|
* cosine of the angle between the indident direction and the (macro-)
|
||||||
|
* surface normal.
|
||||||
|
*
|
||||||
|
* \remark This function only works for isotropic microfacet distributions
|
||||||
|
*/
|
||||||
|
CubicSpline *computeTransmissionProbability(Float extIOR, Float intIOR, Float alpha, size_t resolution) const {
|
||||||
|
if (isAnisotropic())
|
||||||
|
SLog(EError, "MicrofacetDistribution::computeTransmissionProbability(): only "
|
||||||
|
"supports isotropic distributions!");
|
||||||
|
|
||||||
|
NDIntegrator integrator(1, 2, 5000, 0, 1e-5f);
|
||||||
|
CubicSpline *spline = new CubicSpline(resolution);
|
||||||
|
size_t nEvals, nEvalsTotal = 0;
|
||||||
|
ref<Timer> timer = new Timer();
|
||||||
|
|
||||||
|
Float stepSize = (1.0f-2*Epsilon)/(resolution-1);
|
||||||
|
for (size_t i=0; i<resolution; ++i) {
|
||||||
|
Float z = stepSize * i + Epsilon;
|
||||||
|
Vector wi(std::sqrt(std::max((Float) 0, 1-z*z)), 0, z);
|
||||||
|
Float min[2] = {0, 0}, max[2] = {1, 1},
|
||||||
|
integral = 0, error = 0;
|
||||||
|
|
||||||
|
integrator.integrateVectorized(
|
||||||
|
boost::bind(&MicrofacetDistribution::integrand2, this,
|
||||||
|
wi, extIOR, intIOR, alpha, _1, _2, _3),
|
||||||
|
min, max, &integral, &error, &nEvals
|
||||||
|
);
|
||||||
|
|
||||||
|
spline->append(z, integral);
|
||||||
|
|
||||||
|
nEvalsTotal += nEvals;
|
||||||
|
}
|
||||||
|
SLog(EInfo, "Created a " SIZE_T_FMT "-node cubic spline approximation to the "
|
||||||
|
"transmission probability (integration took %i ms and " SIZE_T_FMT
|
||||||
|
" function evaluations)", resolution, timer->getMilliseconds(),
|
||||||
|
nEvalsTotal);
|
||||||
|
|
||||||
|
spline->build();
|
||||||
|
return spline;
|
||||||
|
}
|
||||||
|
|
||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case EBeckmann: return "beckmann"; break;
|
case EBeckmann: return "beckmann"; break;
|
||||||
|
@ -477,13 +525,13 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
/// Integrand helper function called by \ref getRoughTransmission
|
/// Integrand helper function called by \ref computeRoughTransmission
|
||||||
void integrand(const Vector &wi, Float extIOR, Float intIOR, Float alpha,
|
void integrand1(const Vector &wi, Float extIOR, Float intIOR, Float alpha,
|
||||||
size_t nPts, const Float *in, Float *out) const {
|
size_t nPts, const Float *in, Float *out) const {
|
||||||
for (int i=0; i<(int) nPts; ++i) {
|
for (int i=0; i<(int) nPts; ++i) {
|
||||||
Normal m = sample(Point2(in[2*i], in[2*i+1]), alpha);
|
Normal m = sample(Point2(in[2*i], in[2*i+1]), alpha);
|
||||||
Vector wo = 2 * dot(wi, m) * Vector(m) - wi;
|
Vector wo = 2 * dot(wi, m) * Vector(m) - wi;
|
||||||
if (Frame::cosTheta(wi) <= 0 || Frame::cosTheta(wo) <= 0) {
|
if (Frame::cosTheta(wo) <= 0) {
|
||||||
out[i] = 0;
|
out[i] = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -495,6 +543,22 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Integrand helper function called by \ref computeTransmissionProbability
|
||||||
|
void integrand2(const Vector &wi, Float extIOR, Float intIOR, Float alpha,
|
||||||
|
size_t nPts, const Float *in, Float *out) const {
|
||||||
|
for (int i=0; i<(int) nPts; ++i) {
|
||||||
|
Normal m = sample(Point2(in[2*i], in[2*i+1]), alpha);
|
||||||
|
Vector wo = 2 * dot(wi, m) * Vector(m) - wi;
|
||||||
|
if (Frame::cosTheta(wo) <= 0) {
|
||||||
|
out[i] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate the specular reflection component */
|
||||||
|
out[i] = 1 - fresnel(dot(wi, m), extIOR, intIOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EType m_type;
|
EType m_type;
|
||||||
};
|
};
|
||||||
|
|
|
@ -130,7 +130,7 @@ public:
|
||||||
|
|
||||||
if (m_roughTransmittance == NULL) {
|
if (m_roughTransmittance == NULL) {
|
||||||
Float alpha = m_distribution.transformRoughness(m_alpha->getValue(Intersection()).average());
|
Float alpha = m_distribution.transformRoughness(m_alpha->getValue(Intersection()).average());
|
||||||
m_roughTransmittance = m_distribution.getRoughTransmittance(m_extIOR, m_intIOR, alpha, 200);
|
m_roughTransmittance = m_distribution.computeRoughTransmittance(m_extIOR, m_intIOR, alpha, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
BSDF::configure();
|
BSDF::configure();
|
||||||
|
|
Loading…
Reference in New Issue