roughplastic cleanup, part 1
parent
bf9dc03fd8
commit
d50954b20e
|
@ -467,57 +467,6 @@ public:
|
|||
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 {
|
||||
switch (m_type) {
|
||||
case EBeckmann: return "beckmann"; break;
|
||||
|
@ -547,20 +496,6 @@ protected:
|
|||
(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:
|
||||
EType m_type;
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
#define SPLINE_PRECOMP_NODES 200
|
||||
#define TRANSMITTANCE_PRECOMP_NODES 200
|
||||
|
||||
/*!\plugin{roughplastic}{Rough plastic material}
|
||||
* \order{8}
|
||||
|
@ -107,7 +107,6 @@ public:
|
|||
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_diffuseReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_roughTransmittance = static_cast<CubicSpline *>(manager->getInstance(stream));
|
||||
m_diffuseProb = static_cast<CubicSpline *>(manager->getInstance(stream));
|
||||
m_alpha = stream->readFloat();
|
||||
m_intIOR = stream->readFloat();
|
||||
m_extIOR = stream->readFloat();
|
||||
|
@ -121,8 +120,8 @@ public:
|
|||
|
||||
void configure() {
|
||||
m_components.clear();
|
||||
m_components.push_back(EGlossyReflection | ECanUseSampler | EFrontSide);
|
||||
m_components.push_back(EDiffuseReflection | ECanUseSampler | EFrontSide);
|
||||
m_components.push_back(EGlossyReflection | EFrontSide);
|
||||
m_components.push_back(EDiffuseReflection | EFrontSide);
|
||||
|
||||
/* Verify the input parameters and fix them if necessary */
|
||||
m_specularReflectance = ensureEnergyConservation(
|
||||
|
@ -138,14 +137,7 @@ public:
|
|||
|
||||
/* Precompute the rough transmittance through the interface */
|
||||
m_roughTransmittance = m_distribution.computeRoughTransmittance(
|
||||
m_extIOR, m_intIOR, m_alpha, SPLINE_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);
|
||||
m_extIOR, m_intIOR, m_alpha, TRANSMITTANCE_PRECOMP_NODES);
|
||||
|
||||
BSDF::configure();
|
||||
}
|
||||
|
@ -213,20 +205,9 @@ public:
|
|||
/* Calculate the reflection half-vector */
|
||||
const Vector H = normalize(bRec.wo+bRec.wi);
|
||||
|
||||
Float probSpecular, probDiffuse;
|
||||
Float probDiffuse, probSpecular;
|
||||
if (sampleSpecular && sampleDiffuse) {
|
||||
if (bRec.sampler && false) {
|
||||
/* Fancy sampling strategy */
|
||||
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 */
|
||||
/* Find the probability of sampling the specular component */
|
||||
probSpecular = 1-m_roughTransmittance->eval(Frame::cosTheta(bRec.wi));
|
||||
|
||||
/* Reallocate samples */
|
||||
|
@ -235,7 +216,6 @@ public:
|
|||
(1-probSpecular) * (1-m_specularSamplingWeight));
|
||||
|
||||
probDiffuse = 1 - probSpecular;
|
||||
}
|
||||
} else {
|
||||
probDiffuse = probSpecular = 1.0f;
|
||||
}
|
||||
|
@ -272,31 +252,7 @@ public:
|
|||
Point2 sample(_sample);
|
||||
|
||||
if (sampleSpecular && sampleDiffuse) {
|
||||
if (bRec.sampler && false) {
|
||||
/**
|
||||
* 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));
|
||||
|
||||
if (bRec.sampler->next1D() > probSpecular) {
|
||||
choseSpecular = false;
|
||||
sample = bRec.sampler->next2D();
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Basic strategy -- use a clamped Fresnel coefficient
|
||||
* wrt. the macro-surface normal to choose between
|
||||
* diffuse and specular component.
|
||||
*/
|
||||
/* Find the probability of sampling the diffuse component */
|
||||
Float probSpecular = 1 - m_roughTransmittance->eval(Frame::cosTheta(bRec.wi));
|
||||
|
||||
/* Reallocate samples */
|
||||
|
@ -304,20 +260,17 @@ public:
|
|||
(probSpecular*m_specularSamplingWeight +
|
||||
(1-probSpecular) * (1-m_specularSamplingWeight));
|
||||
|
||||
if (sample.x < probSpecular) {
|
||||
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) {
|
||||
/* Perfect specular reflection based on the microsurface normal */
|
||||
m = m_distribution.sample(sample, m_alpha);
|
||||
bRec.wo = reflect(bRec.wi, m);
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EGlossyReflection;
|
||||
|
@ -369,7 +322,6 @@ public:
|
|||
manager->serialize(stream, m_specularReflectance.get());
|
||||
manager->serialize(stream, m_diffuseReflectance.get());
|
||||
manager->serialize(stream, m_roughTransmittance.get());
|
||||
manager->serialize(stream, m_diffuseProb.get());
|
||||
stream->writeFloat(m_alpha);
|
||||
stream->writeFloat(m_intIOR);
|
||||
stream->writeFloat(m_extIOR);
|
||||
|
@ -397,7 +349,6 @@ public:
|
|||
private:
|
||||
MicrofacetDistribution m_distribution;
|
||||
ref<CubicSpline> m_roughTransmittance;
|
||||
ref<CubicSpline> m_diffuseProb;
|
||||
ref<Texture> m_diffuseReflectance;
|
||||
ref<Texture> m_specularReflectance;
|
||||
Float m_alpha, m_intIOR, m_extIOR;
|
||||
|
|
Loading…
Reference in New Issue