bugfix in volpath regarding index-matched participating media. improved the handling of the strictNormals parameter in all path tracers
parent
29a6b06247
commit
ad02615d34
|
@ -167,12 +167,17 @@ public:
|
||||||
* extent information, as well as a time (which applies when
|
* extent information, as well as a time (which applies when
|
||||||
* the shapes are animated)
|
* the shapes are animated)
|
||||||
*
|
*
|
||||||
|
* \param medium
|
||||||
|
* Initial medium containing the ray \c ray
|
||||||
|
*
|
||||||
* \param its
|
* \param its
|
||||||
* A detailed intersection record, which will be filled by the
|
* A detailed intersection record, which will be filled by the
|
||||||
* intersection query
|
* intersection query
|
||||||
*
|
*
|
||||||
* \param medium
|
* \param indexMatchedMediumTransition
|
||||||
* Initial medium containing the ray \c ray.
|
* This parameter is used to return whether or not this routine
|
||||||
|
* passed through an index-matched medium-to-medium transition
|
||||||
|
* while computing the attenuation.
|
||||||
*
|
*
|
||||||
* \param transmittance
|
* \param transmittance
|
||||||
* Transmittance from the ray origin to the returned intersection
|
* Transmittance from the ray origin to the returned intersection
|
||||||
|
@ -180,8 +185,9 @@ public:
|
||||||
*
|
*
|
||||||
* \return \c true if an intersection was found
|
* \return \c true if an intersection was found
|
||||||
*/
|
*/
|
||||||
bool attenuatedRayIntersect(const Ray &ray, const Medium *medium,
|
bool attenuatedRayIntersect(const Ray &ray, const Medium * medium,
|
||||||
Intersection &its, Spectrum &transmittance, Sampler *sampler = NULL) const;
|
Intersection &its, bool &indexMatchedMediumTransition,
|
||||||
|
Spectrum &transmittance, Sampler *sampler = NULL) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Intersect a ray against all primitives stored in the scene
|
* \brief Intersect a ray against all primitives stored in the scene
|
||||||
|
|
|
@ -84,7 +84,7 @@ public:
|
||||||
/* Luminaire sampling */
|
/* Luminaire sampling */
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
|
||||||
/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
|
/* Prevent light leaks due to the use of shading normals */
|
||||||
Float wiDotGeoN = -dot(its.geoFrame.n, ray.d),
|
Float wiDotGeoN = -dot(its.geoFrame.n, ray.d),
|
||||||
wiDotShN = Frame::cosTheta(its.wi);
|
wiDotShN = Frame::cosTheta(its.wi);
|
||||||
if (wiDotGeoN * wiDotShN < 0 && m_strictNormals)
|
if (wiDotGeoN * wiDotShN < 0 && m_strictNormals)
|
||||||
|
@ -95,12 +95,17 @@ public:
|
||||||
if (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance &&
|
if (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance &&
|
||||||
scene->sampleLuminaire(its.p, ray.time, lRec, rRec.nextSample2D())) {
|
scene->sampleLuminaire(its.p, ray.time, lRec, rRec.nextSample2D())) {
|
||||||
/* Allocate a record for querying the BSDF */
|
/* Allocate a record for querying the BSDF */
|
||||||
const BSDFQueryRecord bRec(its, its.toLocal(-lRec.d));
|
const Vector wo = -lRec.d;
|
||||||
|
const BSDFQueryRecord bRec(its, its.toLocal(wo));
|
||||||
|
|
||||||
/* Evaluate BSDF * cos(theta) */
|
/* Evaluate BSDF * cos(theta) */
|
||||||
const Spectrum bsdfVal = bsdf->fCos(bRec);
|
const Spectrum bsdfVal = bsdf->fCos(bRec);
|
||||||
|
|
||||||
if (!bsdfVal.isZero()) {
|
Float woDotGeoN = dot(its.geoFrame.n, wo);
|
||||||
|
|
||||||
|
/* Prevent light leaks due to the use of shading normals */
|
||||||
|
if (!bsdfVal.isZero() && (!m_strictNormals
|
||||||
|
|| woDotGeoN * Frame::cosTheta(bRec.wo) > 0)) {
|
||||||
/* Calculate prob. of having sampled that direction
|
/* Calculate prob. of having sampled that direction
|
||||||
using BSDF sampling */
|
using BSDF sampling */
|
||||||
Float bsdfPdf = (lRec.luminaire->isIntersectable()
|
Float bsdfPdf = (lRec.luminaire->isIntersectable()
|
||||||
|
@ -125,7 +130,7 @@ public:
|
||||||
break;
|
break;
|
||||||
bsdfVal /= bsdfPdf;
|
bsdfVal /= bsdfPdf;
|
||||||
|
|
||||||
/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
|
/* Prevent light leaks due to the use of shading normals */
|
||||||
const Vector wo = its.toWorld(bRec.wo);
|
const Vector wo = its.toWorld(bRec.wo);
|
||||||
Float woDotGeoN = dot(its.geoFrame.n, wo);
|
Float woDotGeoN = dot(its.geoFrame.n, wo);
|
||||||
if (woDotGeoN * Frame::cosTheta(bRec.wo) <= 0 && m_strictNormals)
|
if (woDotGeoN * Frame::cosTheta(bRec.wo) <= 0 && m_strictNormals)
|
||||||
|
@ -178,8 +183,9 @@ public:
|
||||||
break;
|
break;
|
||||||
rRec.type = RadianceQueryRecord::ERadianceNoEmission;
|
rRec.type = RadianceQueryRecord::ERadianceNoEmission;
|
||||||
|
|
||||||
/* Russian roulette - Possibly stop the recursion. Don't use for transmission
|
/* Russian roulette - Possibly stop the recursion. Don't do this when
|
||||||
due to IOR weighting factors, which throw the heuristic off */
|
dealing with a transmission component, since solid angle compression
|
||||||
|
factors cause problems with the heuristic below */
|
||||||
if (rRec.depth >= m_rrDepth && !(bRec.sampledType & BSDF::ETransmission)) {
|
if (rRec.depth >= m_rrDepth && !(bRec.sampledType & BSDF::ETransmission)) {
|
||||||
/* Assuming that BSDF importance sampling is perfect,
|
/* Assuming that BSDF importance sampling is perfect,
|
||||||
'bsdfVal.max()' should equal the maximum albedo
|
'bsdfVal.max()' should equal the maximum albedo
|
||||||
|
|
|
@ -75,10 +75,11 @@ public:
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
/* Luminaire sampling */
|
/* Luminaire sampling */
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
|
||||||
/* Estimate the single scattering component if this is requested */
|
/* Estimate the single scattering component if this is requested */
|
||||||
if (rRec.type & RadianceQueryRecord::EDirectMediumRadiance &&
|
if (rRec.type & RadianceQueryRecord::EDirectMediumRadiance &&
|
||||||
scene->sampleAttenuatedLuminaire(mRec.p, ray.time, rRec.medium, lRec, rRec.nextSample2D(), rRec.sampler)) {
|
scene->sampleAttenuatedLuminaire(mRec.p, ray.time, rRec.medium,
|
||||||
|
lRec, rRec.nextSample2D(), rRec.sampler)) {
|
||||||
/* Evaluate the phase function */
|
/* Evaluate the phase function */
|
||||||
Float phaseVal = phase->f(PhaseFunctionQueryRecord(mRec, -ray.d, -lRec.d));
|
Float phaseVal = phase->f(PhaseFunctionQueryRecord(mRec, -ray.d, -lRec.d));
|
||||||
|
|
||||||
|
@ -94,7 +95,7 @@ public:
|
||||||
Li += pathThroughput * lRec.value * phaseVal * weight;
|
Li += pathThroughput * lRec.value * phaseVal * weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
/* Phase function sampling */
|
/* Phase function sampling */
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
@ -110,10 +111,11 @@ public:
|
||||||
ray = Ray(mRec.p, pRec.wo, ray.time);
|
ray = Ray(mRec.p, pRec.wo, ray.time);
|
||||||
ray.mint = 0;
|
ray.mint = 0;
|
||||||
|
|
||||||
bool hitLuminaire = false;
|
bool hitLuminaire = false, indexMatchedMediumTransition = false;
|
||||||
Spectrum transmittance;
|
Spectrum transmittance;
|
||||||
|
|
||||||
if (scene->attenuatedRayIntersect(ray, rRec.medium, its, transmittance, rRec.sampler)) {
|
if (scene->attenuatedRayIntersect(ray, rRec.medium, its,
|
||||||
|
indexMatchedMediumTransition, transmittance, rRec.sampler)) {
|
||||||
/* Intersected something - check if it was a luminaire */
|
/* Intersected something - check if it was a luminaire */
|
||||||
if (its.isLuminaire()) {
|
if (its.isLuminaire()) {
|
||||||
lRec = LuminaireSamplingRecord(its, -ray.d);
|
lRec = LuminaireSamplingRecord(its, -ray.d);
|
||||||
|
@ -130,7 +132,7 @@ public:
|
||||||
hitLuminaire = true;
|
hitLuminaire = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a luminaire was hit, estimate the local illumination and
|
/* If a luminaire was hit, estimate the local illumination and
|
||||||
weight using the power heuristic */
|
weight using the power heuristic */
|
||||||
if (hitLuminaire && (rRec.type & RadianceQueryRecord::EDirectMediumRadiance)) {
|
if (hitLuminaire && (rRec.type & RadianceQueryRecord::EDirectMediumRadiance)) {
|
||||||
|
@ -140,6 +142,14 @@ public:
|
||||||
Li += pathThroughput * lRec.value * phaseVal * weight * transmittance;
|
Li += pathThroughput * lRec.value * phaseVal * weight * transmittance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (indexMatchedMediumTransition) {
|
||||||
|
/* The previous ray intersection code passed through an index-matched
|
||||||
|
medium transition while looking for a luminaire. For the recursion,
|
||||||
|
we need to rewind and account for this transition -- therefore,
|
||||||
|
another ray intersection call is neccessary */
|
||||||
|
scene->rayIntersect(ray, its);
|
||||||
|
}
|
||||||
|
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
/* Multiple scattering */
|
/* Multiple scattering */
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
@ -174,7 +184,7 @@ public:
|
||||||
Li += pathThroughput * scene->LeBackground(ray);
|
Li += pathThroughput * scene->LeBackground(ray);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Possibly include emitted radiance if requested */
|
/* Possibly include emitted radiance if requested */
|
||||||
if (its.isLuminaire() && (rRec.type & RadianceQueryRecord::EEmittedRadiance))
|
if (its.isLuminaire() && (rRec.type & RadianceQueryRecord::EEmittedRadiance))
|
||||||
Li += pathThroughput * its.Le(-ray.d);
|
Li += pathThroughput * its.Le(-ray.d);
|
||||||
|
@ -185,19 +195,19 @@ public:
|
||||||
|
|
||||||
if (rRec.depth == m_maxDepth && m_maxDepth > 0)
|
if (rRec.depth == m_maxDepth && m_maxDepth > 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const BSDF *bsdf = its.getBSDF(ray);
|
const BSDF *bsdf = its.getBSDF(ray);
|
||||||
if (!bsdf) {
|
if (!bsdf) {
|
||||||
/* Pass right through the surface (there is no BSDF) */
|
/* Pass right through the surface (there is no BSDF) */
|
||||||
if (its.isMediumTransition())
|
if (its.isMediumTransition())
|
||||||
rRec.medium = its.getTargetMedium(ray.d);
|
rRec.medium = its.getTargetMedium(ray.d);
|
||||||
ray.setOrigin(its.p);
|
ray.setOrigin(its.p);
|
||||||
ray.mint = Epsilon;
|
ray.mint = Epsilon;
|
||||||
scene->rayIntersect(ray, its);
|
scene->rayIntersect(ray, its);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
|
/* Prevent light leaks due to the use of shading normals */
|
||||||
Float wiDotGeoN = -dot(its.geoFrame.n, ray.d),
|
Float wiDotGeoN = -dot(its.geoFrame.n, ray.d),
|
||||||
wiDotShN = Frame::cosTheta(its.wi);
|
wiDotShN = Frame::cosTheta(its.wi);
|
||||||
if (wiDotGeoN * wiDotShN < 0 && m_strictNormals)
|
if (wiDotGeoN * wiDotShN < 0 && m_strictNormals)
|
||||||
|
@ -209,14 +219,21 @@ public:
|
||||||
|
|
||||||
/* Estimate the direct illumination if this is requested */
|
/* Estimate the direct illumination if this is requested */
|
||||||
if (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance &&
|
if (rRec.type & RadianceQueryRecord::EDirectSurfaceRadiance &&
|
||||||
scene->sampleAttenuatedLuminaire(its, rRec.medium, lRec, rRec.nextSample2D(), rRec.sampler)) {
|
scene->sampleAttenuatedLuminaire(its, rRec.medium, lRec,
|
||||||
/* Allocate a record for querying the BSDF */
|
rRec.nextSample2D(), rRec.sampler)) {
|
||||||
const BSDFQueryRecord bRec(its, its.toLocal(-lRec.d));
|
const Vector wo = -lRec.d;
|
||||||
|
|
||||||
|
/* Allocate a record for querying the BSDF */
|
||||||
|
const BSDFQueryRecord bRec(its, its.toLocal(wo));
|
||||||
|
|
||||||
/* Evaluate BSDF * cos(theta) */
|
/* Evaluate BSDF * cos(theta) */
|
||||||
const Spectrum bsdfVal = bsdf->fCos(bRec);
|
const Spectrum bsdfVal = bsdf->fCos(bRec);
|
||||||
|
|
||||||
if (!bsdfVal.isZero()) {
|
Float woDotGeoN = dot(its.geoFrame.n, wo);
|
||||||
|
|
||||||
|
/* Prevent light leaks due to the use of shading normals */
|
||||||
|
if (!bsdfVal.isZero() && (!m_strictNormals
|
||||||
|
|| woDotGeoN * Frame::cosTheta(bRec.wo) > 0)) {
|
||||||
/* Calculate prob. of having sampled that direction
|
/* Calculate prob. of having sampled that direction
|
||||||
using BSDF sampling */
|
using BSDF sampling */
|
||||||
Float bsdfPdf = (lRec.luminaire->isIntersectable()
|
Float bsdfPdf = (lRec.luminaire->isIntersectable()
|
||||||
|
@ -242,7 +259,7 @@ public:
|
||||||
|
|
||||||
bsdfVal /= bsdfPdf;
|
bsdfVal /= bsdfPdf;
|
||||||
|
|
||||||
/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
|
/* Prevent light leaks due to the use of shading normals */
|
||||||
const Vector wo = its.toWorld(bRec.wo);
|
const Vector wo = its.toWorld(bRec.wo);
|
||||||
Float woDotGeoN = dot(its.geoFrame.n, wo);
|
Float woDotGeoN = dot(its.geoFrame.n, wo);
|
||||||
if (woDotGeoN * Frame::cosTheta(bRec.wo) <= 0 && m_strictNormals)
|
if (woDotGeoN * Frame::cosTheta(bRec.wo) <= 0 && m_strictNormals)
|
||||||
|
@ -254,10 +271,11 @@ public:
|
||||||
if (its.isMediumTransition())
|
if (its.isMediumTransition())
|
||||||
rRec.medium = its.getTargetMedium(ray.d);
|
rRec.medium = its.getTargetMedium(ray.d);
|
||||||
|
|
||||||
bool hitLuminaire = false;
|
bool hitLuminaire = false, indexMatchedMediumTransition = false;
|
||||||
Spectrum transmittance;
|
Spectrum transmittance;
|
||||||
|
|
||||||
if (scene->attenuatedRayIntersect(ray, rRec.medium, its, transmittance, rRec.sampler)) {
|
if (scene->attenuatedRayIntersect(ray, rRec.medium, its,
|
||||||
|
indexMatchedMediumTransition, transmittance, rRec.sampler)) {
|
||||||
/* Intersected something - check if it was a luminaire */
|
/* Intersected something - check if it was a luminaire */
|
||||||
if (its.isLuminaire()) {
|
if (its.isLuminaire()) {
|
||||||
lRec = LuminaireSamplingRecord(its, -ray.d);
|
lRec = LuminaireSamplingRecord(its, -ray.d);
|
||||||
|
@ -285,6 +303,14 @@ public:
|
||||||
Li += pathThroughput * lRec.value * bsdfVal * weight * transmittance;
|
Li += pathThroughput * lRec.value * bsdfVal * weight * transmittance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (indexMatchedMediumTransition) {
|
||||||
|
/* The previous ray intersection code passed through an index-matched
|
||||||
|
medium transition while looking for a luminaire. For the recursion,
|
||||||
|
we need to rewind and account for this transition -- therefore,
|
||||||
|
another ray intersection call is neccessary */
|
||||||
|
scene->rayIntersect(ray, its);
|
||||||
|
}
|
||||||
|
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
/* Indirect illumination */
|
/* Indirect illumination */
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
@ -294,8 +320,9 @@ public:
|
||||||
break;
|
break;
|
||||||
rRec.type = RadianceQueryRecord::ERadianceNoEmission;
|
rRec.type = RadianceQueryRecord::ERadianceNoEmission;
|
||||||
|
|
||||||
/* Russian roulette - Possibly stop the recursion. Don't use for transmission
|
/* Russian roulette - Possibly stop the recursion. Don't do this when
|
||||||
due to IOR weighting factors, which throw the heuristic off */
|
dealing with a transmission component, since solid angle compression
|
||||||
|
factors cause problems with the heuristic below */
|
||||||
if (rRec.depth >= m_rrDepth && !(bRec.sampledType & BSDF::ETransmission)) {
|
if (rRec.depth >= m_rrDepth && !(bRec.sampledType & BSDF::ETransmission)) {
|
||||||
/* Assuming that BSDF importance sampling is perfect,
|
/* Assuming that BSDF importance sampling is perfect,
|
||||||
'bsdfVal.max()' should equal the maximum albedo
|
'bsdfVal.max()' should equal the maximum albedo
|
||||||
|
@ -317,8 +344,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Float miWeight(Float pdfA, Float pdfB) const {
|
inline Float miWeight(Float pdfA, Float pdfB) const {
|
||||||
pdfA *= pdfA;
|
pdfA *= pdfA; pdfB *= pdfB;
|
||||||
pdfB *= pdfB;
|
|
||||||
return pdfA / (pdfA + pdfB);
|
return pdfA / (pdfA + pdfB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,6 @@ public:
|
||||||
if (rRec.type & RadianceQueryRecord::EDirectMediumRadiance &&
|
if (rRec.type & RadianceQueryRecord::EDirectMediumRadiance &&
|
||||||
scene->sampleAttenuatedLuminaire(mRec.p, ray.time,
|
scene->sampleAttenuatedLuminaire(mRec.p, ray.time,
|
||||||
rRec.medium, lRec, rRec.nextSample2D(), rRec.sampler)) {
|
rRec.medium, lRec, rRec.nextSample2D(), rRec.sampler)) {
|
||||||
|
|
||||||
Li += pathThroughput * lRec.value * phase->f(
|
Li += pathThroughput * lRec.value * phase->f(
|
||||||
PhaseFunctionQueryRecord(mRec, -ray.d, -lRec.d));
|
PhaseFunctionQueryRecord(mRec, -ray.d, -lRec.d));
|
||||||
}
|
}
|
||||||
|
@ -153,7 +152,7 @@ public:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
|
/* Prevent light leaks due to the use of shading normals */
|
||||||
Float wiDotGeoN = -dot(its.geoFrame.n, ray.d),
|
Float wiDotGeoN = -dot(its.geoFrame.n, ray.d),
|
||||||
wiDotShN = Frame::cosTheta(its.wi);
|
wiDotShN = Frame::cosTheta(its.wi);
|
||||||
if (wiDotGeoN * wiDotShN < 0 && m_strictNormals)
|
if (wiDotGeoN * wiDotShN < 0 && m_strictNormals)
|
||||||
|
@ -168,8 +167,14 @@ public:
|
||||||
scene->sampleAttenuatedLuminaire(its, rRec.medium, lRec,
|
scene->sampleAttenuatedLuminaire(its, rRec.medium, lRec,
|
||||||
rRec.nextSample2D(), rRec.sampler)) {
|
rRec.nextSample2D(), rRec.sampler)) {
|
||||||
/* Allocate a record for querying the BSDF */
|
/* Allocate a record for querying the BSDF */
|
||||||
const BSDFQueryRecord bRec(its, its.toLocal(-lRec.d));
|
const Vector wo = -lRec.d;
|
||||||
Li += pathThroughput * lRec.value * bsdf->fCos(bRec);
|
const BSDFQueryRecord bRec(its, its.toLocal(wo));
|
||||||
|
|
||||||
|
Float woDotGeoN = dot(its.geoFrame.n, wo);
|
||||||
|
/* Prevent light leaks due to the use of shading normals */
|
||||||
|
if (!m_strictNormals ||
|
||||||
|
woDotGeoN * Frame::cosTheta(bRec.wo) > 0)
|
||||||
|
Li += pathThroughput * lRec.value * bsdf->fCos(bRec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
@ -182,7 +187,7 @@ public:
|
||||||
if (bsdfVal.isZero())
|
if (bsdfVal.isZero())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
|
/* Prevent light leaks due to the use of shading normals */
|
||||||
const Vector wo = its.toWorld(bRec.wo);
|
const Vector wo = its.toWorld(bRec.wo);
|
||||||
Float woDotGeoN = dot(its.geoFrame.n, wo);
|
Float woDotGeoN = dot(its.geoFrame.n, wo);
|
||||||
if (woDotGeoN * Frame::cosTheta(bRec.wo) <= 0 && m_strictNormals)
|
if (woDotGeoN * Frame::cosTheta(bRec.wo) <= 0 && m_strictNormals)
|
||||||
|
@ -231,8 +236,9 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Russian roulette - Possibly stop the recursion. Don't use for transmission
|
/* Russian roulette - Possibly stop the recursion. Don't do this when
|
||||||
due to IOR weighting factors, which throw the heuristic off */
|
dealing with a transmission component, since solid angle compression
|
||||||
|
factors cause problems with the heuristic below */
|
||||||
if (rRec.depth >= m_rrDepth && !(bRec.sampledType & BSDF::ETransmission)) {
|
if (rRec.depth >= m_rrDepth && !(bRec.sampledType & BSDF::ETransmission)) {
|
||||||
/* Assuming that BSDF importance sampling is perfect,
|
/* Assuming that BSDF importance sampling is perfect,
|
||||||
'bsdfVal.max()' should equal the maximum albedo
|
'bsdfVal.max()' should equal the maximum albedo
|
||||||
|
|
|
@ -431,7 +431,8 @@ Spectrum Scene::getTransmittance(const Point &p1, const Point &p2,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scene::attenuatedRayIntersect(const Ray &_ray, const Medium *medium,
|
bool Scene::attenuatedRayIntersect(const Ray &_ray, const Medium *medium,
|
||||||
Intersection &its, Spectrum &transmittance, Sampler *sampler) const {
|
Intersection &its, bool &indexMatchedMediumTransition,
|
||||||
|
Spectrum &transmittance, Sampler *sampler) const {
|
||||||
Ray ray(_ray);
|
Ray ray(_ray);
|
||||||
transmittance = Spectrum(1.0f);
|
transmittance = Spectrum(1.0f);
|
||||||
int iterations = 0;
|
int iterations = 0;
|
||||||
|
@ -446,10 +447,12 @@ bool Scene::attenuatedRayIntersect(const Ray &_ray, const Medium *medium,
|
||||||
return false;
|
return false;
|
||||||
else if (its.shape->isOccluder())
|
else if (its.shape->isOccluder())
|
||||||
return true;
|
return true;
|
||||||
else if (its.shape->isMediumTransition())
|
else if (its.shape->isMediumTransition()) {
|
||||||
medium = dot(its.geoFrame.n, ray.d) > 0 ?
|
medium = dot(its.geoFrame.n, ray.d) > 0 ?
|
||||||
its.shape->getExteriorMedium()
|
its.shape->getExteriorMedium()
|
||||||
: its.shape->getInteriorMedium();
|
: its.shape->getInteriorMedium();
|
||||||
|
indexMatchedMediumTransition = true;
|
||||||
|
}
|
||||||
|
|
||||||
ray.o = ray(its.t);
|
ray.o = ray(its.t);
|
||||||
ray.mint = Epsilon;
|
ray.mint = Epsilon;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <mitsuba/core/timer.h>
|
#include <mitsuba/core/timer.h>
|
||||||
#include <mitsuba/core/properties.h>
|
#include <mitsuba/core/properties.h>
|
||||||
#include <mitsuba/render/subsurface.h>
|
#include <mitsuba/render/subsurface.h>
|
||||||
|
#include <mitsuba/render/medium.h>
|
||||||
#include <mitsuba/render/bsdf.h>
|
#include <mitsuba/render/bsdf.h>
|
||||||
#include <mitsuba/render/luminaire.h>
|
#include <mitsuba/render/luminaire.h>
|
||||||
|
|
||||||
|
@ -803,8 +804,12 @@ std::string TriMesh::toString() const {
|
||||||
<< " surfaceArea = " << m_surfaceArea << "," << endl
|
<< " surfaceArea = " << m_surfaceArea << "," << endl
|
||||||
<< " aabb = " << m_aabb.toString() << "," << endl
|
<< " aabb = " << m_aabb.toString() << "," << endl
|
||||||
<< " bsdf = " << indent(m_bsdf.toString()) << "," << endl
|
<< " bsdf = " << indent(m_bsdf.toString()) << "," << endl
|
||||||
<< " subsurface = " << indent(m_subsurface.toString()) << "," << endl
|
<< " subsurface = " << indent(m_subsurface.toString()) << "," << endl;
|
||||||
<< " luminaire = " << indent(m_luminaire.toString()) << endl
|
if (isMediumTransition()) {
|
||||||
|
oss << " interiorMedium = " << indent(m_interiorMedium.toString()) << "," << endl
|
||||||
|
<< " exteriorMedium = " << indent(m_exteriorMedium.toString()) << "," << endl;
|
||||||
|
}
|
||||||
|
oss << " luminaire = " << indent(m_luminaire.toString()) << endl
|
||||||
<< "]";
|
<< "]";
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue