rewrote photon mapper lobe selection logic yet once more -- I hope I got it right this time..

metadata
Wenzel Jakob 2013-01-31 20:53:57 -05:00
parent 47ef9e2249
commit 473f75ff6f
1 changed files with 106 additions and 105 deletions

View File

@ -435,9 +435,17 @@ public:
return LiSurf * transmittance + LiMedium; return LiSurf * transmittance + LiMedium;
unsigned int bsdfType = bsdf->getType() & BSDF::EAll; unsigned int bsdfType = bsdf->getType() & BSDF::EAll;
bool isDiffuse = (bsdfType == BSDF::EDiffuseReflection);
if (isDiffuse || cacheQuery) { /* Irradiance cachq query -> trat as diffuse */
bool isDiffuse = (bsdfType == BSDF::EDiffuseReflection) || cacheQuery;
bool hasSpecular = bsdfType & BSDF::EDelta;
/* Exhaustively recurse into all specular lobes? */
bool exhaustiveSpecular = rRec.depth < m_maxSpecularDepth && !cacheQuery;
if (isDiffuse) {
/* 1. Diffuse indirect */
int maxDepth = m_maxDepth == -1 ? INT_MAX : (m_maxDepth-rRec.depth); int maxDepth = m_maxDepth == -1 ? INT_MAX : (m_maxDepth-rRec.depth);
if (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance && m_globalPhotonMap.get()) if (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance && m_globalPhotonMap.get())
LiSurf += m_globalPhotonMap->estimateIrradiance(its.p, LiSurf += m_globalPhotonMap->estimateIrradiance(its.p,
@ -449,8 +457,9 @@ public:
m_causticLookupSize) * bsdf->getDiffuseReflectance(its) * INV_PI; m_causticLookupSize) * bsdf->getDiffuseReflectance(its) * INV_PI;
} }
if ((bsdfType & BSDF::EDelta) && rRec.depth < m_maxSpecularDepth && !cacheQuery) { if (hasSpecular && exhaustiveSpecular
if (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance) { && (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance)) {
/* 1. Specular indirect */
int compCount = bsdf->getComponentCount(); int compCount = bsdf->getComponentCount();
RadianceQueryRecord rRec2; RadianceQueryRecord rRec2;
for (int i=0; i<compCount; i++) { for (int i=0; i<compCount; i++) {
@ -460,7 +469,7 @@ public:
/* Sample the BSDF and recurse */ /* Sample the BSDF and recurse */
BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance); BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance);
bRec.component = i; bRec.component = i;
Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.0f)); Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.5f));
if (bsdfVal.isZero()) if (bsdfVal.isZero())
continue; continue;
@ -472,14 +481,12 @@ public:
LiSurf += bsdfVal * m_parentIntegrator->Li(bsdfRay, rRec2); LiSurf += bsdfVal * m_parentIntegrator->Li(bsdfRay, rRec2);
} }
} }
} else if (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance) {
/* Estimate the direct illumination if this is requested */ /* Estimate the direct illumination if this is requested */
int numEmitterSamples = m_directSamples, numBSDFSamples;
Float weightLum, weightBSDF;
Point2 *sampleArray; Point2 *sampleArray;
Point2 sample; Point2 sample;
int numEmitterSamples = m_directSamples,
numBSDFSamples;
Float weightLum, weightBSDF;
if (rRec.depth > 1 || cacheQuery || adaptiveQuery) { if (rRec.depth > 1 || cacheQuery || adaptiveQuery) {
/* This integrator is used recursively by another integrator. /* This integrator is used recursively by another integrator.
@ -497,14 +504,15 @@ public:
} }
} }
if ((bsdfType & BSDF::ESmooth) && (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance)) {
DirectSamplingRecord dRec(its);
if (numEmitterSamples > 1) { if (numEmitterSamples > 1) {
sampleArray = rRec.sampler->next2DArray(m_directSamples); sampleArray = rRec.sampler->next2DArray(m_directSamples);
} else { } else {
sample = rRec.nextSample2D(); sampleArray = &sample; sample = rRec.nextSample2D(); sampleArray = &sample;
} }
DirectSamplingRecord dRec(its);
if (bsdf->getType() & BSDF::ESmooth) {
for (int i=0; i<numEmitterSamples; ++i) { for (int i=0; i<numEmitterSamples; ++i) {
int interactions = m_maxDepth - rRec.depth - 1; int interactions = m_maxDepth - rRec.depth - 1;
Spectrum value = scene->sampleAttenuatedEmitterDirect( Spectrum value = scene->sampleAttenuatedEmitterDirect(
@ -524,6 +532,10 @@ public:
if (!bsdfVal.isZero()) { if (!bsdfVal.isZero()) {
/* Calculate prob. of having sampled that direction /* Calculate prob. of having sampled that direction
using BSDF sampling */ using BSDF sampling */
if (!hasSpecular || exhaustiveSpecular)
bRec.typeMask = BSDF::ESmooth;
Float bsdfPdf = (emitter->isOnSurface() Float bsdfPdf = (emitter->isOnSurface()
&& dRec.measure == ESolidAngle && dRec.measure == ESolidAngle
&& interactions == 0) && interactions == 0)
@ -532,6 +544,7 @@ public:
/* Weight using the power heuristic */ /* Weight using the power heuristic */
const Float weight = miWeight(dRec.pdf * numEmitterSamples, const Float weight = miWeight(dRec.pdf * numEmitterSamples,
bsdfPdf * numBSDFSamples) * weightLum; bsdfPdf * numBSDFSamples) * weightLum;
LiSurf += value * bsdfVal * weight; LiSurf += value * bsdfVal * weight;
} }
} }
@ -542,6 +555,20 @@ public:
/* BSDF sampling */ /* BSDF sampling */
/* ==================================================================== */ /* ==================================================================== */
/* Sample direct compontent via BSDF sampling if this is generally requested AND
the BSDF is smooth, or there is a delta component that was not handled by the
exhaustive sampling loop above */
bool bsdfSampleDirect = (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance) &&
((bsdfType & BSDF::ESmooth) || (hasSpecular && !exhaustiveSpecular));
/* Sample indirect component via BSDF sampling if this is generally requested AND
the BSDF is non-diffuse (diffuse is handled by the global photon map)
or there is a delta component that was not handled by the exhaustive sampling loop
above. */
bool bsdfSampleIndirect = (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance) &&
!isDiffuse && ((bsdfType & BSDF::ESmooth) || (hasSpecular && !exhaustiveSpecular));
if (bsdfSampleDirect || bsdfSampleIndirect) {
if (numBSDFSamples > 1) { if (numBSDFSamples > 1) {
sampleArray = rRec.sampler->next2DArray( sampleArray = rRec.sampler->next2DArray(
std::max(m_directSamples, m_glossySamples)); std::max(m_directSamples, m_glossySamples));
@ -552,9 +579,13 @@ public:
RadianceQueryRecord rRec2; RadianceQueryRecord rRec2;
Intersection &bsdfIts = rRec2.its; Intersection &bsdfIts = rRec2.its;
DirectSamplingRecord dRec;
for (int i=0; i<numBSDFSamples; ++i) { for (int i=0; i<numBSDFSamples; ++i) {
/* Sample BSDF * cos(theta) */ /* Sample BSDF * cos(theta) */
BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance); BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance);
if (!hasSpecular || exhaustiveSpecular)
bRec.typeMask = BSDF::ESmooth;
Float bsdfPdf; Float bsdfPdf;
Spectrum bsdfVal = bsdf->sample(bRec, bsdfPdf, sampleArray[i]); Spectrum bsdfVal = bsdf->sample(bRec, bsdfPdf, sampleArray[i]);
if (bsdfVal.isZero()) if (bsdfVal.isZero())
@ -567,12 +598,12 @@ public:
bool hitEmitter = false; bool hitEmitter = false;
if (scene->rayIntersect(bsdfRay, bsdfIts)) { if (scene->rayIntersect(bsdfRay, bsdfIts)) {
/* Intersected something - check if it was a luminaire */ /* Intersected something - check if it was a luminaire */
if (bsdfIts.isEmitter()) { if (bsdfIts.isEmitter() && bsdfSampleDirect) {
value = bsdfIts.Le(-bsdfRay.d); value = bsdfIts.Le(-bsdfRay.d);
dRec.setQuery(bsdfRay, bsdfIts); dRec.setQuery(bsdfRay, bsdfIts);
hitEmitter = true; hitEmitter = true;
} }
} else { } else if (bsdfSampleDirect) {
/* Intersected nothing -- perhaps there is an environment map? */ /* Intersected nothing -- perhaps there is an environment map? */
const Emitter *env = scene->getEnvironmentEmitter(); const Emitter *env = scene->getEnvironmentEmitter();
@ -584,8 +615,7 @@ public:
} }
if (hitEmitter) { if (hitEmitter) {
const Float emitterPdf = (!(bRec.sampledType & BSDF::EDelta)) ? const Float emitterPdf = scene->pdfEmitterDirect(dRec);
scene->pdfEmitterDirect(dRec) : 0;
Spectrum transmittance = rRec2.medium ? Spectrum transmittance = rRec2.medium ?
rRec2.medium->evalTransmittance(Ray(bsdfRay, 0, bsdfIts.t)) : Spectrum(1.0f); rRec2.medium->evalTransmittance(Ray(bsdfRay, 0, bsdfIts.t)) : Spectrum(1.0f);
@ -597,7 +627,7 @@ public:
} }
/* Recurse */ /* Recurse */
if (!isDiffuse && (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance) && !cacheQuery) { if (bsdfSampleIndirect) {
rRec2.recursiveQuery(rRec, rRec2.recursiveQuery(rRec,
RadianceQueryRecord::ERadianceNoEmission); RadianceQueryRecord::ERadianceNoEmission);
rRec2.type ^= RadianceQueryRecord::EIntersection; rRec2.type ^= RadianceQueryRecord::EIntersection;
@ -608,35 +638,6 @@ public:
LiSurf += bsdfVal * m_parentIntegrator->Li(bsdfRay, rRec2) * weightBSDF; LiSurf += bsdfVal * m_parentIntegrator->Li(bsdfRay, rRec2) * weightBSDF;
} }
} }
} else if (!isDiffuse && (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance) && !cacheQuery) {
int numBSDFSamples = (rRec.depth > 1 || adaptiveQuery) ? 1 : m_glossySamples;
Float weightBSDF;
Point2 *sampleArray;
Point2 sample;
if (numBSDFSamples > 1) {
sampleArray = rRec.sampler->next2DArray(
std::max(m_directSamples, m_glossySamples));
weightBSDF = m_invGlossySamples;
} else {
sample = rRec.nextSample2D(); sampleArray = &sample;
weightBSDF = 1.0f;
}
RadianceQueryRecord rRec2;
for (int i=0; i<numBSDFSamples; ++i) {
/* Sample BSDF * cos(theta) */
BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance);
Float bsdfPdf;
Spectrum bsdfVal = bsdf->sample(bRec, bsdfPdf, sampleArray[i]);
if (bsdfVal.isZero())
continue;
rRec2.recursiveQuery(rRec,
RadianceQueryRecord::ERadianceNoEmission);
RayDifferential bsdfRay(its.p, its.toWorld(bRec.wo), ray.time);
LiSurf += bsdfVal * m_parentIntegrator->Li(bsdfRay, rRec2) * weightBSDF;
}
} }
return LiSurf * transmittance + LiMedium; return LiSurf * transmittance + LiMedium;