roughplastic cleanup, part 1

metadata
Wenzel Jakob 2011-07-11 22:46:05 +02:00
parent bf9dc03fd8
commit d50954b20e
2 changed files with 23 additions and 137 deletions

View File

@ -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;
};

View File

@ -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,21 +205,10 @@ 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 */
probSpecular = 1 - m_roughTransmittance->eval(Frame::cosTheta(bRec.wi));
/* Find the probability of sampling the specular component */
probSpecular = 1-m_roughTransmittance->eval(Frame::cosTheta(bRec.wi));
/* Reallocate samples */
probSpecular = (probSpecular*m_specularSamplingWeight) /
@ -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;