switched to a new BSDFQueryRecord constructor, which encapsulates the assumption that a sampler instance is always available when sampling the model
parent
fad581de2f
commit
0230c6fbe7
|
@ -49,12 +49,17 @@ public:
|
||||||
*
|
*
|
||||||
* \param its
|
* \param its
|
||||||
* An reference to the underlying intersection record
|
* An reference to the underlying intersection record
|
||||||
* \param typeMask
|
*
|
||||||
* The list of components that should be sampled
|
* \param sampler
|
||||||
|
* A source of (pseudo-) random numbers. Note that this sampler
|
||||||
|
* is only used when the scattering model for some reason needs
|
||||||
|
* more than the two unformly distributed numbers supplied in
|
||||||
|
* the \ref BSDF::sample() methods
|
||||||
|
*
|
||||||
* \param quantity
|
* \param quantity
|
||||||
* The transported quantity (\ref ERadiance or \ref EImportance)
|
* The transported quantity (\ref ERadiance or \ref EImportance)
|
||||||
*/
|
*/
|
||||||
explicit inline BSDFQueryRecord(const Intersection &its,
|
explicit inline BSDFQueryRecord(const Intersection &its, Sampler *sampler,
|
||||||
ETransportQuantity quantity = ERadiance);
|
ETransportQuantity quantity = ERadiance);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,8 +117,8 @@ public:
|
||||||
* Some BSDF implementations can significantly improve
|
* Some BSDF implementations can significantly improve
|
||||||
* the quality of their importance sampling routines
|
* the quality of their importance sampling routines
|
||||||
* when having access to extra random numbers. This
|
* when having access to extra random numbers. This
|
||||||
* attribute provides a means of providing this capability
|
* attribute provides a means of providing this
|
||||||
* to the BSDF.
|
* capability to the BSDF.
|
||||||
*/
|
*/
|
||||||
Sampler *sampler;
|
Sampler *sampler;
|
||||||
|
|
||||||
|
|
|
@ -115,53 +115,54 @@ public:
|
||||||
/// List of suported query types. These can be combined by a binary OR.
|
/// List of suported query types. These can be combined by a binary OR.
|
||||||
enum ERadianceQuery {
|
enum ERadianceQuery {
|
||||||
/// Emitted radiance from a luminaire intersected by the ray
|
/// Emitted radiance from a luminaire intersected by the ray
|
||||||
EEmittedRadiance = 0x0001,
|
EEmittedRadiance = 0x0001,
|
||||||
|
|
||||||
/// Emitted radiance from a subsurface integrator */
|
/// Emitted radiance from a subsurface integrator */
|
||||||
ESubsurfaceRadiance = 0x0002,
|
ESubsurfaceRadiance = 0x0002,
|
||||||
|
|
||||||
/// Direct (surface) radiance */
|
/// Direct (surface) radiance */
|
||||||
EDirectSurfaceRadiance = 0x0004,
|
EDirectSurfaceRadiance = 0x0004,
|
||||||
|
|
||||||
/*! \brief Indirect (surface) radiance, where the last bounce did not go
|
/*! \brief Indirect (surface) radiance, where the last bounce did not go
|
||||||
through a Dirac delta BSDF */
|
through a Dirac delta BSDF */
|
||||||
EIndirectSurfaceRadiance = 0x0008,
|
EIndirectSurfaceRadiance = 0x0008,
|
||||||
|
|
||||||
/*! \brief Indirect (surface) radiance, where the last bounce went
|
/*! \brief Indirect (surface) radiance, where the last bounce went
|
||||||
through a Dirac delta BSDF */
|
through a Dirac delta BSDF */
|
||||||
ECausticRadiance = 0x0010,
|
ECausticRadiance = 0x0010,
|
||||||
|
|
||||||
/// In-scattered radiance due to volumetric scattering (direct)
|
/// In-scattered radiance due to volumetric scattering (direct)
|
||||||
EDirectMediumRadiance = 0x0020,
|
EDirectMediumRadiance = 0x0020,
|
||||||
|
|
||||||
/// In-scattered radiance due to volumetric scattering (indirect)
|
/// In-scattered radiance due to volumetric scattering (indirect)
|
||||||
EIndirectMediumRadiance = 0x0040,
|
EIndirectMediumRadiance = 0x0040,
|
||||||
|
|
||||||
/// Distance to the next surface intersection
|
/// Distance to the next surface intersection
|
||||||
EDistance = 0x0080,
|
EDistance = 0x0080,
|
||||||
|
|
||||||
/*! \brief Store an opacity value, which is equal to 1 when a shape
|
/*! \brief Store an opacity value, which is equal to 1 when a shape
|
||||||
was intersected and 0 when the ray passes through empty space.
|
was intersected and 0 when the ray passes through empty space.
|
||||||
When there is a participating medium, it can also take on fractional
|
When there is a participating medium, it can also take on fractional
|
||||||
values. */
|
values. */
|
||||||
EOpacity = 0x0100,
|
EOpacity = 0x0100,
|
||||||
|
|
||||||
/*! \brief A ray intersection may need to be performed. This can be set to
|
/*! \brief A ray intersection may need to be performed. This can be set to
|
||||||
zero if the caller has already provided the intersection */
|
zero if the caller has already provided the intersection */
|
||||||
EIntersection = 0x0200,
|
EIntersection = 0x0200,
|
||||||
|
|
||||||
/* Radiance from volumes */
|
/* Radiance from volumes */
|
||||||
EVolumeRadiance = EDirectMediumRadiance | EIndirectMediumRadiance,
|
EVolumeRadiance = EDirectMediumRadiance | EIndirectMediumRadiance,
|
||||||
|
|
||||||
/// Radiance query without emitted radiance, ray intersection required
|
/// Radiance query without emitted radiance, ray intersection required
|
||||||
ERadianceNoEmission = ESubsurfaceRadiance | EDirectSurfaceRadiance | EIndirectSurfaceRadiance
|
ERadianceNoEmission = ESubsurfaceRadiance | EDirectSurfaceRadiance
|
||||||
| ECausticRadiance | EDirectMediumRadiance | EIndirectMediumRadiance | EIntersection,
|
| EIndirectSurfaceRadiance | ECausticRadiance | EDirectMediumRadiance
|
||||||
|
| EIndirectMediumRadiance | EIntersection,
|
||||||
|
|
||||||
/// Default radiance query, ray intersection required
|
/// Default radiance query, ray intersection required
|
||||||
ERadiance = ERadianceNoEmission | EEmittedRadiance,
|
ERadiance = ERadianceNoEmission | EEmittedRadiance,
|
||||||
|
|
||||||
/// Radiance + opacity
|
/// Radiance + opacity
|
||||||
ECameraRay = ERadiance | EOpacity
|
ECameraRay = ERadiance | EOpacity
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Construct an invalid radiance query record
|
/// Construct an invalid radiance query record
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
MTS_NAMESPACE_BEGIN
|
MTS_NAMESPACE_BEGIN
|
||||||
|
|
||||||
inline BSDFQueryRecord::BSDFQueryRecord(const Intersection &its, ETransportQuantity quantity)
|
inline BSDFQueryRecord::BSDFQueryRecord(const Intersection &its, Sampler *sampler, ETransportQuantity quantity)
|
||||||
: its(its), sampler(NULL), wi(its.wi), quantity(quantity),
|
: its(its), sampler(sampler), wi(its.wi), quantity(quantity),
|
||||||
typeMask(BSDF::EAll), sampledType(0), component(-1), sampledComponent(-1) {
|
typeMask(BSDF::EAll), sampledType(0), component(-1), sampledComponent(-1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -195,9 +195,8 @@ public:
|
||||||
Intersection perturbed;
|
Intersection perturbed;
|
||||||
perturbIntersection(its, perturbed);
|
perturbIntersection(its, perturbed);
|
||||||
|
|
||||||
BSDFQueryRecord perturbedQuery(perturbed, bRec.quantity);
|
BSDFQueryRecord perturbedQuery(perturbed, bRec.sampler, bRec.quantity);
|
||||||
perturbedQuery.wi = perturbed.toLocal(its.toWorld(bRec.wi));
|
perturbedQuery.wi = perturbed.toLocal(its.toWorld(bRec.wi));
|
||||||
perturbedQuery.sampler = bRec.sampler;
|
|
||||||
perturbedQuery.typeMask = bRec.typeMask;
|
perturbedQuery.typeMask = bRec.typeMask;
|
||||||
perturbedQuery.component = bRec.component;
|
perturbedQuery.component = bRec.component;
|
||||||
Spectrum result = m_nested->sample(perturbedQuery, pdf, sample);
|
Spectrum result = m_nested->sample(perturbedQuery, pdf, sample);
|
||||||
|
@ -218,7 +217,7 @@ public:
|
||||||
Intersection perturbed;
|
Intersection perturbed;
|
||||||
perturbIntersection(its, perturbed);
|
perturbIntersection(its, perturbed);
|
||||||
|
|
||||||
BSDFQueryRecord perturbedQuery(perturbed, bRec.quantity);
|
BSDFQueryRecord perturbedQuery(perturbed, bRec.sampler, bRec.quantity);
|
||||||
perturbedQuery.wi = perturbed.toLocal(its.toWorld(bRec.wi));
|
perturbedQuery.wi = perturbed.toLocal(its.toWorld(bRec.wi));
|
||||||
perturbedQuery.sampler = bRec.sampler;
|
perturbedQuery.sampler = bRec.sampler;
|
||||||
perturbedQuery.typeMask = bRec.typeMask;
|
perturbedQuery.typeMask = bRec.typeMask;
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
#include <mitsuba/core/fresolver.h>
|
#include <mitsuba/core/fresolver.h>
|
||||||
#include <mitsuba/render/bsdf.h>
|
#include <mitsuba/render/bsdf.h>
|
||||||
#include <mitsuba/render/sampler.h>
|
|
||||||
#include <mitsuba/hw/basicshader.h>
|
#include <mitsuba/hw/basicshader.h>
|
||||||
#include "microfacet.h"
|
#include "microfacet.h"
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <mitsuba/render/bsdf.h>
|
#include <mitsuba/render/bsdf.h>
|
||||||
#include <mitsuba/render/sampler.h>
|
|
||||||
#include <mitsuba/hw/basicshader.h>
|
#include <mitsuba/hw/basicshader.h>
|
||||||
#include "microfacet.h"
|
#include "microfacet.h"
|
||||||
#include "ior.h"
|
#include "ior.h"
|
||||||
|
|
|
@ -135,7 +135,6 @@ public:
|
||||||
if (scene->sampleLuminaire(its.p, ray.time, lRec, sampleArray[i])) {
|
if (scene->sampleLuminaire(its.p, ray.time, lRec, sampleArray[i])) {
|
||||||
/* Allocate a record for querying the BSDF */
|
/* Allocate a record for querying the BSDF */
|
||||||
BSDFQueryRecord bRec(its, its.toLocal(-lRec.d));
|
BSDFQueryRecord bRec(its, its.toLocal(-lRec.d));
|
||||||
bRec.sampler = rRec.sampler;
|
|
||||||
|
|
||||||
/* Evaluate BSDF * cos(theta) */
|
/* Evaluate BSDF * cos(theta) */
|
||||||
const Spectrum bsdfVal = bsdf->eval(bRec);
|
const Spectrum bsdfVal = bsdf->eval(bRec);
|
||||||
|
@ -167,8 +166,7 @@ public:
|
||||||
|
|
||||||
for (size_t i=0; i<numBSDFSamples; ++i) {
|
for (size_t i=0; i<numBSDFSamples; ++i) {
|
||||||
/* Sample BSDF * cos(theta) */
|
/* Sample BSDF * cos(theta) */
|
||||||
BSDFQueryRecord bRec(its);
|
BSDFQueryRecord bRec(its, rRec.sampler, ERadiance);
|
||||||
bRec.sampler = rRec.sampler;
|
|
||||||
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())
|
||||||
|
|
|
@ -131,8 +131,7 @@ public:
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
|
||||||
/* Sample BSDF * cos(theta) */
|
/* Sample BSDF * cos(theta) */
|
||||||
BSDFQueryRecord bRec(its);
|
BSDFQueryRecord bRec(its, rRec.sampler, ERadiance);
|
||||||
bRec.sampler = rRec.sampler;
|
|
||||||
Float bsdfPdf;
|
Float bsdfPdf;
|
||||||
Spectrum bsdfVal = bsdf->sample(bRec, bsdfPdf, rRec.nextSample2D());
|
Spectrum bsdfVal = bsdf->sample(bRec, bsdfPdf, rRec.nextSample2D());
|
||||||
if (bsdfVal.isZero())
|
if (bsdfVal.isZero())
|
||||||
|
|
|
@ -225,7 +225,6 @@ public:
|
||||||
|
|
||||||
/* Allocate a record for querying the BSDF */
|
/* Allocate a record for querying the BSDF */
|
||||||
BSDFQueryRecord bRec(its, its.toLocal(wo));
|
BSDFQueryRecord bRec(its, its.toLocal(wo));
|
||||||
bRec.sampler = rRec.sampler;
|
|
||||||
|
|
||||||
/* Evaluate BSDF * cos(theta) */
|
/* Evaluate BSDF * cos(theta) */
|
||||||
const Spectrum bsdfVal = bsdf->eval(bRec);
|
const Spectrum bsdfVal = bsdf->eval(bRec);
|
||||||
|
@ -252,8 +251,7 @@ public:
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
|
||||||
/* Sample BSDF * cos(theta) */
|
/* Sample BSDF * cos(theta) */
|
||||||
BSDFQueryRecord bRec(its);
|
BSDFQueryRecord bRec(its, rRec.sampler, ERadiance);
|
||||||
bRec.sampler = rRec.sampler;
|
|
||||||
Float bsdfPdf;
|
Float bsdfPdf;
|
||||||
Spectrum bsdfVal = bsdf->sample(bRec, bsdfPdf, rRec.nextSample2D());
|
Spectrum bsdfVal = bsdf->sample(bRec, bsdfPdf, rRec.nextSample2D());
|
||||||
if (bsdfVal.isZero())
|
if (bsdfVal.isZero())
|
||||||
|
|
|
@ -183,8 +183,7 @@ public:
|
||||||
/* ==================================================================== */
|
/* ==================================================================== */
|
||||||
|
|
||||||
/* Sample BSDF * cos(theta) */
|
/* Sample BSDF * cos(theta) */
|
||||||
BSDFQueryRecord bRec(its);
|
BSDFQueryRecord bRec(its, rRec.sampler, ERadiance);
|
||||||
bRec.sampler = rRec.sampler;
|
|
||||||
Spectrum bsdfVal = bsdf->sample(bRec, rRec.nextSample2D());
|
Spectrum bsdfVal = bsdf->sample(bRec, rRec.nextSample2D());
|
||||||
if (bsdfVal.isZero())
|
if (bsdfVal.isZero())
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -368,7 +368,7 @@ public:
|
||||||
int compCount = bsdf->getComponentCount();
|
int compCount = bsdf->getComponentCount();
|
||||||
for (int i=0; i<compCount; i++) {
|
for (int i=0; i<compCount; i++) {
|
||||||
/* Sample the BSDF and recurse */
|
/* Sample the BSDF and recurse */
|
||||||
BSDFQueryRecord bRec(its);
|
BSDFQueryRecord bRec(its, rRec.sampler);
|
||||||
bRec.component = i;
|
bRec.component = i;
|
||||||
Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.0f));
|
Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.0f));
|
||||||
if (bsdfVal.isZero())
|
if (bsdfVal.isZero())
|
||||||
|
@ -388,7 +388,7 @@ public:
|
||||||
Float weight = 1 / (Float) m_glossySamples;
|
Float weight = 1 / (Float) m_glossySamples;
|
||||||
|
|
||||||
for (int i=0; i<m_glossySamples; ++i) {
|
for (int i=0; i<m_glossySamples; ++i) {
|
||||||
BSDFQueryRecord bRec(its);
|
BSDFQueryRecord bRec(its, rRec.sampler);
|
||||||
bRec.sampler = rRec.sampler;
|
bRec.sampler = rRec.sampler;
|
||||||
Spectrum bsdfVal = bsdf->sample(bRec, sampleArray[i]);
|
Spectrum bsdfVal = bsdf->sample(bRec, sampleArray[i]);
|
||||||
|
|
||||||
|
|
|
@ -246,7 +246,7 @@ public:
|
||||||
if ((bsdf->getType(i) & BSDF::EDelta) == 0)
|
if ((bsdf->getType(i) & BSDF::EDelta) == 0)
|
||||||
continue;
|
continue;
|
||||||
/* Sample the BSDF and recurse */
|
/* Sample the BSDF and recurse */
|
||||||
BSDFQueryRecord bRec(p.its);
|
BSDFQueryRecord bRec(p.its, sampler);
|
||||||
bRec.component = i;
|
bRec.component = i;
|
||||||
Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.0f));
|
Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.0f));
|
||||||
if (bsdfVal.isZero())
|
if (bsdfVal.isZero())
|
||||||
|
|
|
@ -237,8 +237,7 @@ public:
|
||||||
} else {
|
} else {
|
||||||
/* Recurse for dielectric materials and (specific to SPPM):
|
/* Recurse for dielectric materials and (specific to SPPM):
|
||||||
recursive "final gathering" for glossy materials */
|
recursive "final gathering" for glossy materials */
|
||||||
BSDFQueryRecord bRec(gatherPoint.its);
|
BSDFQueryRecord bRec(gatherPoint.its, sampler);
|
||||||
bRec.sampler = sampler;
|
|
||||||
weight *= bsdf->sample(bRec, sampler->next2D());
|
weight *= bsdf->sample(bRec, sampler->next2D());
|
||||||
if (weight.isZero()) {
|
if (weight.isZero()) {
|
||||||
gatherPoint.depth = -1;
|
gatherPoint.depth = -1;
|
||||||
|
|
|
@ -62,8 +62,7 @@ void BSDF::configure() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum BSDF::getDiffuseReflectance(const Intersection &its) const {
|
Spectrum BSDF::getDiffuseReflectance(const Intersection &its) const {
|
||||||
BSDFQueryRecord bRec(its);
|
BSDFQueryRecord bRec(its, Vector(0, 0, 1), Vector(0, 0, 1));
|
||||||
bRec.wi = bRec.wo = Vector(0, 0, 1);
|
|
||||||
bRec.typeMask = EDiffuseReflection;
|
bRec.typeMask = EDiffuseReflection;
|
||||||
return eval(bRec) * M_PI;
|
return eval(bRec) * M_PI;
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,8 +190,7 @@ void ParticleTracer::process(const WorkUnit *workUnit, WorkResult *workResult,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BSDFQueryRecord bRec(its, EImportance);
|
BSDFQueryRecord bRec(its, m_sampler, EImportance);
|
||||||
bRec.sampler = m_sampler;
|
|
||||||
bsdfVal = bsdf->sample(bRec, m_sampler->next2D());
|
bsdfVal = bsdf->sample(bRec, m_sampler->next2D());
|
||||||
if (bsdfVal.isZero())
|
if (bsdfVal.isZero())
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -107,8 +107,7 @@ size_t generateVPLs(const Scene *scene, Random *random,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BSDFQueryRecord bRec(its, EImportance);
|
BSDFQueryRecord bRec(its, sampler, EImportance);
|
||||||
bRec.sampler = sampler;
|
|
||||||
bsdfVal = bsdf->sample(bRec, sampler->next2D());
|
bsdfVal = bsdf->sample(bRec, sampler->next2D());
|
||||||
if (bsdfVal.isZero())
|
if (bsdfVal.isZero())
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -108,7 +108,7 @@ public:
|
||||||
|
|
||||||
boost::tuple<Vector, Float, EMeasure> generateSample() {
|
boost::tuple<Vector, Float, EMeasure> generateSample() {
|
||||||
Point2 sample(m_sampler->next2D());
|
Point2 sample(m_sampler->next2D());
|
||||||
BSDFQueryRecord bRec(m_its);
|
BSDFQueryRecord bRec(m_its, m_fakeSampler);
|
||||||
bRec.component = m_component;
|
bRec.component = m_component;
|
||||||
bRec.wi = m_wi;
|
bRec.wi = m_wi;
|
||||||
|
|
||||||
|
@ -118,14 +118,6 @@ public:
|
||||||
|
|
||||||
Float pdfVal, pdfVal2;
|
Float pdfVal, pdfVal2;
|
||||||
|
|
||||||
/* Only make the sampler available to the BSDF when requested
|
|
||||||
by the testcase. This allows testing both sampling variants
|
|
||||||
where applicable: those that can improve by having access to
|
|
||||||
an arbitrary random number stream vs. those that only use
|
|
||||||
a single uniform 2D sample */
|
|
||||||
|
|
||||||
bRec.sampler = m_fakeSampler;
|
|
||||||
|
|
||||||
/* Check the various sampling routines for agreement
|
/* Check the various sampling routines for agreement
|
||||||
amongst each other */
|
amongst each other */
|
||||||
m_fakeSampler->clear();
|
m_fakeSampler->clear();
|
||||||
|
@ -190,11 +182,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Float pdf(const Vector &wo, EMeasure measure) {
|
Float pdf(const Vector &wo, EMeasure measure) {
|
||||||
BSDFQueryRecord bRec(m_its);
|
BSDFQueryRecord bRec(m_its, m_wi, wo);
|
||||||
bRec.component = m_component;
|
bRec.component = m_component;
|
||||||
bRec.wi = m_wi;
|
|
||||||
bRec.wo = wo;
|
|
||||||
bRec.sampler = m_sampler;
|
|
||||||
|
|
||||||
#if defined(MTS_DEBUG_FP)
|
#if defined(MTS_DEBUG_FP)
|
||||||
enableFPExceptions();
|
enableFPExceptions();
|
||||||
|
|
Loading…
Reference in New Issue