improved reliability of specular perturbations

metadata
Wenzel Jakob 2013-02-06 21:17:50 -05:00
parent d806c6194e
commit a279b7f638
6 changed files with 21 additions and 15 deletions

View File

@ -225,7 +225,7 @@ public:
&& (bRec.component == -1 || bRec.component < (int) m_components.size()-1);
if (measure == EDiscrete && sampleSpecular &&
absDot(reflect(bRec.wi), bRec.wo) > 1-DeltaEpsilon) {
std::abs(dot(reflect(bRec.wi), bRec.wo)-1) < DeltaEpsilon) {
return m_specularReflectance->eval(bRec.its) *
fresnelDielectricExt(std::abs(Frame::cosTheta(bRec.wi)), m_eta);
} else if (sampleNested) {
@ -274,7 +274,7 @@ public:
(1-R12) * (1-m_specularSamplingWeight));
if (measure == EDiscrete && sampleSpecular &&
absDot(reflect(bRec.wi), bRec.wo) > 1-DeltaEpsilon) {
std::abs(dot(reflect(bRec.wi), bRec.wo)-1) < DeltaEpsilon) {
return sampleNested ? probSpecular : 1.0f;
} else if (sampleNested) {
Float R21;

View File

@ -229,7 +229,7 @@ public:
if (!sampleReflection || measure != EDiscrete ||
Frame::cosTheta(bRec.wi) <= 0 ||
Frame::cosTheta(bRec.wo) <= 0 ||
absDot(reflect(bRec.wi), bRec.wo) < 1-DeltaEpsilon)
std::abs(dot(reflect(bRec.wi), bRec.wo)-1) > DeltaEpsilon)
return Spectrum(0.0f);
return m_specularReflectance->eval(bRec.its) *
@ -245,7 +245,7 @@ public:
if (!sampleReflection || measure != EDiscrete ||
Frame::cosTheta(bRec.wi) <= 0 ||
Frame::cosTheta(bRec.wo) <= 0 ||
absDot(reflect(bRec.wi), bRec.wo) < 1-DeltaEpsilon)
std::abs(dot(reflect(bRec.wi), bRec.wo)-1) > DeltaEpsilon)
return 0.0f;
return 1.0f;

View File

@ -235,12 +235,12 @@ public:
Float F = fresnelDielectricExt(Frame::cosTheta(bRec.wi), cosThetaT, m_eta);
if (Frame::cosTheta(bRec.wi) * Frame::cosTheta(bRec.wo) >= 0) {
if (!sampleReflection || absDot(reflect(bRec.wi), bRec.wo) < 1-DeltaEpsilon)
if (!sampleReflection || std::abs(dot(reflect(bRec.wi), bRec.wo)-1) > DeltaEpsilon)
return Spectrum(0.0f);
return m_specularReflectance->eval(bRec.its) * F;
} else {
if (!sampleTransmission || absDot(refract(bRec.wi, cosThetaT), bRec.wo) < 1-DeltaEpsilon)
if (!sampleTransmission || std::abs(dot(refract(bRec.wi, cosThetaT), bRec.wo)-1) > DeltaEpsilon)
return Spectrum(0.0f);
/* Radiance must be scaled to account for the solid angle compression
@ -262,12 +262,12 @@ public:
Float F = fresnelDielectricExt(Frame::cosTheta(bRec.wi), cosThetaT, m_eta);
if (Frame::cosTheta(bRec.wi) * Frame::cosTheta(bRec.wo) >= 0) {
if (!sampleReflection || absDot(reflect(bRec.wi), bRec.wo) < 1-DeltaEpsilon)
if (!sampleReflection || std::abs(dot(reflect(bRec.wi), bRec.wo)-1) > DeltaEpsilon)
return 0.0f;
return sampleTransmission ? F : 1.0f;
} else {
if (!sampleTransmission || absDot(refract(bRec.wi, cosThetaT), bRec.wo) < 1-DeltaEpsilon)
if (!sampleTransmission || std::abs(dot(refract(bRec.wi, cosThetaT), bRec.wo)-1) > DeltaEpsilon)
return 0.0f;
return sampleReflection ? 1-F : 1.0f;

View File

@ -255,7 +255,7 @@ public:
if (hasSpecular) {
/* Check if the provided direction pair matches an ideal
specular reflection; tolerate some roundoff errors */
if (absDot(reflect(bRec.wi), bRec.wo) > 1-DeltaEpsilon)
if (std::abs(dot(reflect(bRec.wi), bRec.wo)-1) < DeltaEpsilon)
return m_specularReflectance->eval(bRec.its) * Fi;
} else if (hasDiffuse) {
Float Fo = fresnelDielectricExt(Frame::cosTheta(bRec.wo), m_eta);
@ -294,7 +294,7 @@ public:
if (hasSpecular && measure == EDiscrete) {
/* Check if the provided direction pair matches an ideal
specular reflection; tolerate some roundoff errors */
if (absDot(reflect(bRec.wi), bRec.wo) > 1-DeltaEpsilon)
if (std::abs(dot(reflect(bRec.wi), bRec.wo)-1) < DeltaEpsilon)
return probSpecular;
} else if (hasDiffuse && measure == ESolidAngle) {
return Warp::squareToCosineHemispherePdf(bRec.wo) * (1-probSpecular);

View File

@ -163,12 +163,12 @@ public:
R += T*T * R / (1-R*R);
if (Frame::cosTheta(bRec.wi) * Frame::cosTheta(bRec.wo) >= 0) {
if (!sampleReflection || absDot(reflect(bRec.wi), bRec.wo) < 1-DeltaEpsilon)
if (!sampleReflection || std::abs(dot(reflect(bRec.wi), bRec.wo)-1) > DeltaEpsilon)
return Spectrum(0.0f);
return m_specularReflectance->eval(bRec.its) * R;
} else {
if (!sampleTransmission || absDot(transmit(bRec.wi), bRec.wo) < 1-DeltaEpsilon)
if (!sampleTransmission || std::abs(dot(transmit(bRec.wi), bRec.wo)-1) > DeltaEpsilon)
return Spectrum(0.0f);
return m_specularTransmittance->eval(bRec.its) * (1 - R);
@ -188,12 +188,12 @@ public:
R += T*T * R / (1-R*R);
if (Frame::cosTheta(bRec.wi) * Frame::cosTheta(bRec.wo) >= 0) {
if (!sampleReflection || absDot(reflect(bRec.wi), bRec.wo) < 1-DeltaEpsilon)
if (!sampleReflection || std::abs(dot(reflect(bRec.wi), bRec.wo)-1) > DeltaEpsilon)
return 0.0f;
return sampleTransmission ? R : 1.0f;
} else {
if (!sampleTransmission || absDot(transmit(bRec.wi), bRec.wo) < 1-DeltaEpsilon)
if (!sampleTransmission || std::abs(dot(transmit(bRec.wi), bRec.wo)-1) > DeltaEpsilon)
return 0.0f;
return sampleReflection ? 1-R : 1.0f;

View File

@ -710,7 +710,13 @@ bool PathVertex::propagatePerturbation(const Scene *scene, const PathVertex *pre
bRec.typeMask = BSDF::EAll;
Float prob = bsdf->pdf(bRec, EDiscrete);
weight[mode] = bsdf->eval(bRec, EDiscrete)/prob;
if (prob == 0) {
SLog(EWarn, "Unable to recreate specular vertex in perturbation (bsdf=%s)",
bsdf->toString().c_str());
return false;
}
weight[mode] = bsdf->eval(bRec, EDiscrete) / prob;
pdf[mode] = prob;
measure = EDiscrete;
componentType = componentType_;