rewrote photon mapper lobe selection logic yet once more -- I hope I got it right this time..
parent
47ef9e2249
commit
473f75ff6f
|
@ -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,53 +457,55 @@ 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)) {
|
||||||
int compCount = bsdf->getComponentCount();
|
/* 1. Specular indirect */
|
||||||
RadianceQueryRecord rRec2;
|
int compCount = bsdf->getComponentCount();
|
||||||
for (int i=0; i<compCount; i++) {
|
RadianceQueryRecord rRec2;
|
||||||
unsigned int type = bsdf->getType(i);
|
for (int i=0; i<compCount; i++) {
|
||||||
if (!(type & BSDF::EDelta))
|
unsigned int type = bsdf->getType(i);
|
||||||
continue;
|
if (!(type & BSDF::EDelta))
|
||||||
/* Sample the BSDF and recurse */
|
continue;
|
||||||
BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance);
|
/* Sample the BSDF and recurse */
|
||||||
bRec.component = i;
|
BSDFSamplingRecord bRec(its, rRec.sampler, ERadiance);
|
||||||
Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.0f));
|
bRec.component = i;
|
||||||
if (bsdfVal.isZero())
|
Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.5f));
|
||||||
continue;
|
if (bsdfVal.isZero())
|
||||||
|
continue;
|
||||||
|
|
||||||
rRec2.recursiveQuery(rRec, RadianceQueryRecord::ERadiance);
|
rRec2.recursiveQuery(rRec, RadianceQueryRecord::ERadiance);
|
||||||
RayDifferential bsdfRay(its.p, its.toWorld(bRec.wo), ray.time);
|
RayDifferential bsdfRay(its.p, its.toWorld(bRec.wo), ray.time);
|
||||||
if (its.isMediumTransition())
|
if (its.isMediumTransition())
|
||||||
rRec2.medium = its.getTargetMedium(bsdfRay.d);
|
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) {
|
if (rRec.depth > 1 || cacheQuery || adaptiveQuery) {
|
||||||
/* This integrator is used recursively by another integrator.
|
/* This integrator is used recursively by another integrator.
|
||||||
Be less accurate as this sample will not directly be observed. */
|
Be less accurate as this sample will not directly be observed. */
|
||||||
numBSDFSamples = numEmitterSamples = 1;
|
numBSDFSamples = numEmitterSamples = 1;
|
||||||
weightLum = weightBSDF = 1.0f;
|
weightLum = weightBSDF = 1.0f;
|
||||||
|
} else {
|
||||||
|
if (isDiffuse) {
|
||||||
|
numBSDFSamples = m_directSamples;
|
||||||
|
weightBSDF = weightLum = m_invEmitterSamples;
|
||||||
} else {
|
} else {
|
||||||
if (isDiffuse) {
|
numBSDFSamples = m_glossySamples;
|
||||||
numBSDFSamples = m_directSamples;
|
weightLum = m_invEmitterSamples;
|
||||||
weightBSDF = weightLum = m_invEmitterSamples;
|
weightBSDF = m_invGlossySamples;
|
||||||
} else {
|
|
||||||
numBSDFSamples = m_glossySamples;
|
|
||||||
weightLum = m_invEmitterSamples;
|
|
||||||
weightBSDF = m_invGlossySamples;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
@ -503,45 +513,62 @@ public:
|
||||||
sample = rRec.nextSample2D(); sampleArray = &sample;
|
sample = rRec.nextSample2D(); sampleArray = &sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectSamplingRecord dRec(its);
|
for (int i=0; i<numEmitterSamples; ++i) {
|
||||||
if (bsdf->getType() & BSDF::ESmooth) {
|
int interactions = m_maxDepth - rRec.depth - 1;
|
||||||
for (int i=0; i<numEmitterSamples; ++i) {
|
Spectrum value = scene->sampleAttenuatedEmitterDirect(
|
||||||
int interactions = m_maxDepth - rRec.depth - 1;
|
dRec, its, rRec.medium, interactions,
|
||||||
Spectrum value = scene->sampleAttenuatedEmitterDirect(
|
sampleArray[i], rRec.sampler);
|
||||||
dRec, its, rRec.medium, interactions,
|
|
||||||
sampleArray[i], rRec.sampler);
|
|
||||||
|
|
||||||
/* Estimate the direct illumination if this is requested */
|
/* Estimate the direct illumination if this is requested */
|
||||||
if (!value.isZero()) {
|
if (!value.isZero()) {
|
||||||
const Emitter *emitter = static_cast<const Emitter *>(dRec.object);
|
const Emitter *emitter = static_cast<const Emitter *>(dRec.object);
|
||||||
|
|
||||||
/* Allocate a record for querying the BSDF */
|
/* Allocate a record for querying the BSDF */
|
||||||
BSDFSamplingRecord bRec(its, its.toLocal(dRec.d));
|
BSDFSamplingRecord bRec(its, its.toLocal(dRec.d));
|
||||||
|
|
||||||
/* Evaluate BSDF * cos(theta) */
|
/* Evaluate BSDF * cos(theta) */
|
||||||
const Spectrum bsdfVal = bsdf->eval(bRec);
|
const Spectrum bsdfVal = bsdf->eval(bRec);
|
||||||
|
|
||||||
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 */
|
||||||
Float bsdfPdf = (emitter->isOnSurface()
|
|
||||||
&& dRec.measure == ESolidAngle
|
|
||||||
&& interactions == 0)
|
|
||||||
? bsdf->pdf(bRec) : (Float) 0.0f;
|
|
||||||
|
|
||||||
/* Weight using the power heuristic */
|
if (!hasSpecular || exhaustiveSpecular)
|
||||||
const Float weight = miWeight(dRec.pdf * numEmitterSamples,
|
bRec.typeMask = BSDF::ESmooth;
|
||||||
bsdfPdf * numBSDFSamples) * weightLum;
|
|
||||||
LiSurf += value * bsdfVal * weight;
|
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) {
|
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;
|
||||||
|
|
Loading…
Reference in New Issue