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;
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue