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;
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);
if (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance && m_globalPhotonMap.get())
LiSurf += m_globalPhotonMap->estimateIrradiance(its.p,
@ -449,53 +457,55 @@ public:
m_causticLookupSize) * bsdf->getDiffuseReflectance(its) * INV_PI;
}
if ((bsdfType & BSDF::EDelta) && rRec.depth < m_maxSpecularDepth && !cacheQuery) {
if (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance) {
int compCount = bsdf->getComponentCount();
RadianceQueryRecord rRec2;
for (int i=0; i<compCount; i++) {
unsigned int type = bsdf->getType(i);
if (!(type & BSDF::EDelta))
continue;
/* Sample the BSDF and recurse */
BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance);
bRec.component = i;
Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.0f));
if (bsdfVal.isZero())
continue;
if (hasSpecular && exhaustiveSpecular
&& (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance)) {
/* 1. Specular indirect */
int compCount = bsdf->getComponentCount();
RadianceQueryRecord rRec2;
for (int i=0; i<compCount; i++) {
unsigned int type = bsdf->getType(i);
if (!(type & BSDF::EDelta))
continue;
/* Sample the BSDF and recurse */
BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance);
bRec.component = i;
Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.5f));
if (bsdfVal.isZero())
continue;
rRec2.recursiveQuery(rRec, RadianceQueryRecord::ERadiance);
RayDifferential bsdfRay(its.p, its.toWorld(bRec.wo), ray.time);
if (its.isMediumTransition())
rRec2.medium = its.getTargetMedium(bsdfRay.d);
rRec2.recursiveQuery(rRec, RadianceQueryRecord::ERadiance);
RayDifferential bsdfRay(its.p, its.toWorld(bRec.wo), ray.time);
if (its.isMediumTransition())
rRec2.medium = its.getTargetMedium(bsdfRay.d);
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 */
Point2 *sampleArray;
Point2 sample;
int numEmitterSamples = m_directSamples,
numBSDFSamples;
}
Float weightLum, weightBSDF;
/* Estimate the direct illumination if this is requested */
int numEmitterSamples = m_directSamples, numBSDFSamples;
Float weightLum, weightBSDF;
Point2 *sampleArray;
Point2 sample;
if (rRec.depth > 1 || cacheQuery || adaptiveQuery) {
/* This integrator is used recursively by another integrator.
Be less accurate as this sample will not directly be observed. */
numBSDFSamples = numEmitterSamples = 1;
weightLum = weightBSDF = 1.0f;
if (rRec.depth > 1 || cacheQuery || adaptiveQuery) {
/* This integrator is used recursively by another integrator.
Be less accurate as this sample will not directly be observed. */
numBSDFSamples = numEmitterSamples = 1;
weightLum = weightBSDF = 1.0f;
} else {
if (isDiffuse) {
numBSDFSamples = m_directSamples;
weightBSDF = weightLum = m_invEmitterSamples;
} else {
if (isDiffuse) {
numBSDFSamples = m_directSamples;
weightBSDF = weightLum = m_invEmitterSamples;
} else {
numBSDFSamples = m_glossySamples;
weightLum = m_invEmitterSamples;
weightBSDF = m_invGlossySamples;
}
numBSDFSamples = m_glossySamples;
weightLum = m_invEmitterSamples;
weightBSDF = m_invGlossySamples;
}
}
if ((bsdfType & BSDF::ESmooth) && (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance)) {
DirectSamplingRecord dRec(its);
if (numEmitterSamples > 1) {
sampleArray = rRec.sampler->next2DArray(m_directSamples);
@ -503,45 +513,62 @@ public:
sample = rRec.nextSample2D(); sampleArray = &sample;
}
DirectSamplingRecord dRec(its);
if (bsdf->getType() & BSDF::ESmooth) {
for (int i=0; i<numEmitterSamples; ++i) {
int interactions = m_maxDepth - rRec.depth - 1;
Spectrum value = scene->sampleAttenuatedEmitterDirect(
dRec, its, rRec.medium, interactions,
sampleArray[i], rRec.sampler);
for (int i=0; i<numEmitterSamples; ++i) {
int interactions = m_maxDepth - rRec.depth - 1;
Spectrum value = scene->sampleAttenuatedEmitterDirect(
dRec, its, rRec.medium, interactions,
sampleArray[i], rRec.sampler);
/* Estimate the direct illumination if this is requested */
if (!value.isZero()) {
const Emitter *emitter = static_cast<const Emitter *>(dRec.object);
/* Estimate the direct illumination if this is requested */
if (!value.isZero()) {
const Emitter *emitter = static_cast<const Emitter *>(dRec.object);
/* Allocate a record for querying the BSDF */
BSDFSamplingRecord bRec(its, its.toLocal(dRec.d));
/* Allocate a record for querying the BSDF */
BSDFSamplingRecord bRec(its, its.toLocal(dRec.d));
/* Evaluate BSDF * cos(theta) */
const Spectrum bsdfVal = bsdf->eval(bRec);
/* Evaluate BSDF * cos(theta) */
const Spectrum bsdfVal = bsdf->eval(bRec);
if (!bsdfVal.isZero()) {
/* Calculate prob. of having sampled that direction
using BSDF sampling */
Float bsdfPdf = (emitter->isOnSurface()
&& dRec.measure == ESolidAngle
&& interactions == 0)
? bsdf->pdf(bRec) : (Float) 0.0f;
if (!bsdfVal.isZero()) {
/* Calculate prob. of having sampled that direction
using BSDF sampling */
/* Weight using the power heuristic */
const Float weight = miWeight(dRec.pdf * numEmitterSamples,
bsdfPdf * numBSDFSamples) * weightLum;
LiSurf += value * bsdfVal * weight;
}
if (!hasSpecular || exhaustiveSpecular)
bRec.typeMask = BSDF::ESmooth;
Float bsdfPdf = (emitter->isOnSurface()
&& dRec.measure == ESolidAngle
&& interactions == 0)
? bsdf->pdf(bRec) : (Float) 0.0f;
/* Weight using the power heuristic */
const Float weight = miWeight(dRec.pdf * numEmitterSamples,
bsdfPdf * numBSDFSamples) * weightLum;
LiSurf += value * bsdfVal * weight;
}
}
}
}
/* ==================================================================== */
/* 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) {
sampleArray = rRec.sampler->next2DArray(
std::max(m_directSamples, m_glossySamples));
@ -552,9 +579,13 @@ public:
RadianceQueryRecord rRec2;
Intersection &bsdfIts = rRec2.its;
DirectSamplingRecord dRec;
for (int i=0; i<numBSDFSamples; ++i) {
/* Sample BSDF * cos(theta) */
BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance);
if (!hasSpecular || exhaustiveSpecular)
bRec.typeMask = BSDF::ESmooth;
Float bsdfPdf;
Spectrum bsdfVal = bsdf->sample(bRec, bsdfPdf, sampleArray[i]);
if (bsdfVal.isZero())
@ -567,12 +598,12 @@ public:
bool hitEmitter = false;
if (scene->rayIntersect(bsdfRay, bsdfIts)) {
/* Intersected something - check if it was a luminaire */
if (bsdfIts.isEmitter()) {
if (bsdfIts.isEmitter() && bsdfSampleDirect) {
value = bsdfIts.Le(-bsdfRay.d);
dRec.setQuery(bsdfRay, bsdfIts);
hitEmitter = true;
}
} else {
} else if (bsdfSampleDirect) {
/* Intersected nothing -- perhaps there is an environment map? */
const Emitter *env = scene->getEnvironmentEmitter();
@ -584,8 +615,7 @@ public:
}
if (hitEmitter) {
const Float emitterPdf = (!(bRec.sampledType & BSDF::EDelta)) ?
scene->pdfEmitterDirect(dRec) : 0;
const Float emitterPdf = scene->pdfEmitterDirect(dRec);
Spectrum transmittance = rRec2.medium ?
rRec2.medium->evalTransmittance(Ray(bsdfRay, 0, bsdfIts.t)) : Spectrum(1.0f);
@ -597,7 +627,7 @@ public:
}
/* Recurse */
if (!isDiffuse && (rRec.type & RadianceQueryRecord::EIndirectSurfaceRadiance) && !cacheQuery) {
if (bsdfSampleIndirect) {
rRec2.recursiveQuery(rRec,
RadianceQueryRecord::ERadianceNoEmission);
rRec2.type ^= RadianceQueryRecord::EIntersection;
@ -608,35 +638,6 @@ public:
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;