roughplastic cleanup, part 1
parent
bf9dc03fd8
commit
d50954b20e
|
@ -467,57 +467,6 @@ public:
|
||||||
return spline;
|
return spline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Compute a spline representation that gives the probability
|
|
||||||
* of choosing a reflection event when importance sampling wrt. the
|
|
||||||
* Fresnel coefficient between a sampled microsurface normal and the
|
|
||||||
* incident direction.
|
|
||||||
*
|
|
||||||
* This function is currently used by the plugin 'roughplastic'.
|
|
||||||
*
|
|
||||||
* 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, Float specularSamplingWeight, 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, specularSamplingWeight, _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;
|
||||||
|
@ -547,20 +496,6 @@ protected:
|
||||||
(Frame::cosTheta(wi) * Frame::cosTheta(m)));
|
(Frame::cosTheta(wi) * Frame::cosTheta(m)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Integrand helper function called by \ref computeTransmissionProbability
|
|
||||||
void integrand2(const Vector &wi, Float extIOR, Float intIOR, Float alpha,
|
|
||||||
Float specularSamplingWeight, 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);
|
|
||||||
Float probSpecular = fresnel(dot(wi, m), extIOR, intIOR);
|
|
||||||
probSpecular = (probSpecular*specularSamplingWeight) /
|
|
||||||
(probSpecular*specularSamplingWeight +
|
|
||||||
(1-probSpecular) * (1-specularSamplingWeight));
|
|
||||||
out[i] = 1-probSpecular;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EType m_type;
|
EType m_type;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
MTS_NAMESPACE_BEGIN
|
MTS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
#define SPLINE_PRECOMP_NODES 200
|
#define TRANSMITTANCE_PRECOMP_NODES 200
|
||||||
|
|
||||||
/*!\plugin{roughplastic}{Rough plastic material}
|
/*!\plugin{roughplastic}{Rough plastic material}
|
||||||
* \order{8}
|
* \order{8}
|
||||||
|
@ -107,7 +107,6 @@ public:
|
||||||
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_diffuseReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||||
m_roughTransmittance = static_cast<CubicSpline *>(manager->getInstance(stream));
|
m_roughTransmittance = static_cast<CubicSpline *>(manager->getInstance(stream));
|
||||||
m_diffuseProb = static_cast<CubicSpline *>(manager->getInstance(stream));
|
|
||||||
m_alpha = stream->readFloat();
|
m_alpha = stream->readFloat();
|
||||||
m_intIOR = stream->readFloat();
|
m_intIOR = stream->readFloat();
|
||||||
m_extIOR = stream->readFloat();
|
m_extIOR = stream->readFloat();
|
||||||
|
@ -121,8 +120,8 @@ public:
|
||||||
|
|
||||||
void configure() {
|
void configure() {
|
||||||
m_components.clear();
|
m_components.clear();
|
||||||
m_components.push_back(EGlossyReflection | ECanUseSampler | EFrontSide);
|
m_components.push_back(EGlossyReflection | EFrontSide);
|
||||||
m_components.push_back(EDiffuseReflection | ECanUseSampler | EFrontSide);
|
m_components.push_back(EDiffuseReflection | EFrontSide);
|
||||||
|
|
||||||
/* Verify the input parameters and fix them if necessary */
|
/* Verify the input parameters and fix them if necessary */
|
||||||
m_specularReflectance = ensureEnergyConservation(
|
m_specularReflectance = ensureEnergyConservation(
|
||||||
|
@ -138,14 +137,7 @@ public:
|
||||||
|
|
||||||
/* Precompute the rough transmittance through the interface */
|
/* Precompute the rough transmittance through the interface */
|
||||||
m_roughTransmittance = m_distribution.computeRoughTransmittance(
|
m_roughTransmittance = m_distribution.computeRoughTransmittance(
|
||||||
m_extIOR, m_intIOR, m_alpha, SPLINE_PRECOMP_NODES);
|
m_extIOR, m_intIOR, m_alpha, TRANSMITTANCE_PRECOMP_NODES);
|
||||||
|
|
||||||
/* Precompute a spline that specifies the probability of
|
|
||||||
sampling the diffuse component for different angles
|
|
||||||
of incidence. */
|
|
||||||
m_diffuseProb = m_distribution.computeTransmissionProbability(
|
|
||||||
m_extIOR, m_intIOR, m_alpha, m_specularSamplingWeight,
|
|
||||||
SPLINE_PRECOMP_NODES);
|
|
||||||
|
|
||||||
BSDF::configure();
|
BSDF::configure();
|
||||||
}
|
}
|
||||||
|
@ -213,29 +205,17 @@ public:
|
||||||
/* Calculate the reflection half-vector */
|
/* Calculate the reflection half-vector */
|
||||||
const Vector H = normalize(bRec.wo+bRec.wi);
|
const Vector H = normalize(bRec.wo+bRec.wi);
|
||||||
|
|
||||||
Float probSpecular, probDiffuse;
|
Float probDiffuse, probSpecular;
|
||||||
if (sampleSpecular && sampleDiffuse) {
|
if (sampleSpecular && sampleDiffuse) {
|
||||||
if (bRec.sampler && false) {
|
/* Find the probability of sampling the specular component */
|
||||||
/* Fancy sampling strategy */
|
probSpecular = 1-m_roughTransmittance->eval(Frame::cosTheta(bRec.wi));
|
||||||
probSpecular = fresnel(dot(bRec.wi, H), m_extIOR, m_intIOR);
|
|
||||||
|
|
||||||
/* Reallocate samples */
|
|
||||||
probSpecular = (probSpecular*m_specularSamplingWeight) /
|
|
||||||
(probSpecular*m_specularSamplingWeight +
|
|
||||||
(1-probSpecular) * (1-m_specularSamplingWeight));
|
|
||||||
|
|
||||||
probDiffuse = m_diffuseProb->eval(Frame::cosTheta(bRec.wi));
|
|
||||||
} else {
|
|
||||||
/* Basic sampling strategy that only needs 2 random numbers */
|
|
||||||
probSpecular = 1 - m_roughTransmittance->eval(Frame::cosTheta(bRec.wi));
|
|
||||||
|
|
||||||
/* Reallocate samples */
|
/* Reallocate samples */
|
||||||
probSpecular = (probSpecular*m_specularSamplingWeight) /
|
probSpecular = (probSpecular*m_specularSamplingWeight) /
|
||||||
(probSpecular*m_specularSamplingWeight +
|
(probSpecular*m_specularSamplingWeight +
|
||||||
(1-probSpecular) * (1-m_specularSamplingWeight));
|
(1-probSpecular) * (1-m_specularSamplingWeight));
|
||||||
|
|
||||||
probDiffuse = 1 - probSpecular;
|
probDiffuse = 1 - probSpecular;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
probDiffuse = probSpecular = 1.0f;
|
probDiffuse = probSpecular = 1.0f;
|
||||||
}
|
}
|
||||||
|
@ -272,52 +252,25 @@ public:
|
||||||
Point2 sample(_sample);
|
Point2 sample(_sample);
|
||||||
|
|
||||||
if (sampleSpecular && sampleDiffuse) {
|
if (sampleSpecular && sampleDiffuse) {
|
||||||
if (bRec.sampler && false) {
|
/* Find the probability of sampling the diffuse component */
|
||||||
/**
|
Float probSpecular = 1 - m_roughTransmittance->eval(Frame::cosTheta(bRec.wi));
|
||||||
* We have access to a sampler -- use a good sampling
|
|
||||||
* technique, which is somewhat wasteful in terms of
|
|
||||||
* random numbers
|
|
||||||
*/
|
|
||||||
m = m_distribution.sample(sample, m_alpha);
|
|
||||||
|
|
||||||
Float probSpecular = fresnel(dot(bRec.wi, m), m_extIOR, m_intIOR);
|
/* Reallocate samples */
|
||||||
|
probSpecular = (probSpecular*m_specularSamplingWeight) /
|
||||||
|
(probSpecular*m_specularSamplingWeight +
|
||||||
|
(1-probSpecular) * (1-m_specularSamplingWeight));
|
||||||
|
|
||||||
/* Reallocate samples */
|
if (sample.x <= probSpecular) {
|
||||||
probSpecular = (probSpecular*m_specularSamplingWeight) /
|
sample.x /= probSpecular;
|
||||||
(probSpecular*m_specularSamplingWeight +
|
|
||||||
(1-probSpecular) * (1-m_specularSamplingWeight));
|
|
||||||
|
|
||||||
if (bRec.sampler->next1D() > probSpecular) {
|
|
||||||
choseSpecular = false;
|
|
||||||
sample = bRec.sampler->next2D();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/**
|
sample.x = (sample.x - probSpecular) / (1 - probSpecular);
|
||||||
* Basic strategy -- use a clamped Fresnel coefficient
|
choseSpecular = false;
|
||||||
* wrt. the macro-surface normal to choose between
|
|
||||||
* diffuse and specular component.
|
|
||||||
*/
|
|
||||||
Float probSpecular = 1 - m_roughTransmittance->eval(Frame::cosTheta(bRec.wi));
|
|
||||||
|
|
||||||
/* Reallocate samples */
|
|
||||||
probSpecular = (probSpecular*m_specularSamplingWeight) /
|
|
||||||
(probSpecular*m_specularSamplingWeight +
|
|
||||||
(1-probSpecular) * (1-m_specularSamplingWeight));
|
|
||||||
|
|
||||||
if (sample.x < probSpecular) {
|
|
||||||
sample.x /= probSpecular;
|
|
||||||
m = m_distribution.sample(sample, m_alpha);
|
|
||||||
} else {
|
|
||||||
sample.x = (sample.x - probSpecular) / (1 - probSpecular);
|
|
||||||
choseSpecular = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (choseSpecular) {
|
|
||||||
m = m_distribution.sample(sample, m_alpha);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (choseSpecular) {
|
if (choseSpecular) {
|
||||||
/* Perfect specular reflection based on the microsurface normal */
|
/* Perfect specular reflection based on the microsurface normal */
|
||||||
|
m = m_distribution.sample(sample, m_alpha);
|
||||||
bRec.wo = reflect(bRec.wi, m);
|
bRec.wo = reflect(bRec.wi, m);
|
||||||
bRec.sampledComponent = 0;
|
bRec.sampledComponent = 0;
|
||||||
bRec.sampledType = EGlossyReflection;
|
bRec.sampledType = EGlossyReflection;
|
||||||
|
@ -369,7 +322,6 @@ public:
|
||||||
manager->serialize(stream, m_specularReflectance.get());
|
manager->serialize(stream, m_specularReflectance.get());
|
||||||
manager->serialize(stream, m_diffuseReflectance.get());
|
manager->serialize(stream, m_diffuseReflectance.get());
|
||||||
manager->serialize(stream, m_roughTransmittance.get());
|
manager->serialize(stream, m_roughTransmittance.get());
|
||||||
manager->serialize(stream, m_diffuseProb.get());
|
|
||||||
stream->writeFloat(m_alpha);
|
stream->writeFloat(m_alpha);
|
||||||
stream->writeFloat(m_intIOR);
|
stream->writeFloat(m_intIOR);
|
||||||
stream->writeFloat(m_extIOR);
|
stream->writeFloat(m_extIOR);
|
||||||
|
@ -397,7 +349,6 @@ public:
|
||||||
private:
|
private:
|
||||||
MicrofacetDistribution m_distribution;
|
MicrofacetDistribution m_distribution;
|
||||||
ref<CubicSpline> m_roughTransmittance;
|
ref<CubicSpline> m_roughTransmittance;
|
||||||
ref<CubicSpline> m_diffuseProb;
|
|
||||||
ref<Texture> m_diffuseReflectance;
|
ref<Texture> m_diffuseReflectance;
|
||||||
ref<Texture> m_specularReflectance;
|
ref<Texture> m_specularReflectance;
|
||||||
Float m_alpha, m_intIOR, m_extIOR;
|
Float m_alpha, m_intIOR, m_extIOR;
|
||||||
|
|
Loading…
Reference in New Issue