本文整理汇总了C++中Spectrum::isZero方法的典型用法代码示例。如果您正苦于以下问题:C++ Spectrum::isZero方法的具体用法?C++ Spectrum::isZero怎么用?C++ Spectrum::isZero使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Spectrum
的用法示例。
在下文中一共展示了Spectrum::isZero方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: handleMediumInteraction
void CaptureParticleWorker::handleMediumInteraction(int depth, int nullInteractions, bool caustic,
const MediumSamplingRecord &mRec, const Medium *medium, const Vector &wi,
const Spectrum &weight) {
if (m_bruteForce || (depth >= m_maxPathDepth && m_maxPathDepth > 0))
return;
DirectSamplingRecord dRec(mRec);
int maxInteractions = m_maxPathDepth - depth - 1;
Spectrum value = weight * m_scene->sampleAttenuatedSensorDirect(
dRec, medium, maxInteractions, m_sampler->next2D(), m_sampler);
if (value.isZero())
return;
/* Evaluate the phase function */
const PhaseFunction *phase = medium->getPhaseFunction();
PhaseFunctionSamplingRecord pRec(mRec, wi, dRec.d, EImportance);
value *= phase->eval(pRec);
if (value.isZero())
return;
/* Splat onto the accumulation buffer */
m_workResult->put(dRec.uv, (Float *) &value[0]);
}
示例2: handleSurfaceInteraction
void CaptureParticleWorker::handleSurfaceInteraction(int depth, int nullInteractions,
bool caustic, const Intersection &its, const Medium *medium,
const Spectrum &weight) {
if (its.isSensor()) {
if (!m_bruteForce && !caustic)
return;
const Sensor *sensor = its.shape->getSensor();
if (sensor != m_sensor)
return;
Vector wi = its.toWorld(its.wi);
Point2 uv;
Spectrum value = sensor->eval(its, wi, uv) * weight;
if (value.isZero())
return;
m_workResult->put(uv, (Float *) &value[0]);
return;
}
if (m_bruteForce || (depth >= m_maxPathDepth && m_maxPathDepth > 0))
return;
int maxInteractions = m_maxPathDepth - depth - 1;
DirectSamplingRecord dRec(its);
Spectrum value = weight * m_scene->sampleAttenuatedSensorDirect(
dRec, its, medium, maxInteractions,
m_sampler->next2D(), m_sampler);
if (value.isZero())
return;
const BSDF *bsdf = its.getBSDF();
Vector wo = dRec.d;
BSDFSamplingRecord bRec(its, its.toLocal(wo), EImportance);
/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
Vector wi = its.toWorld(its.wi);
Float wiDotGeoN = dot(its.geoFrame.n, wi),
woDotGeoN = dot(its.geoFrame.n, wo);
if (wiDotGeoN * Frame::cosTheta(bRec.wi) <= 0 ||
woDotGeoN * Frame::cosTheta(bRec.wo) <= 0)
return;
/* Adjoint BSDF for shading normals -- [Veach, p. 155] */
Float correction = std::abs(
(Frame::cosTheta(bRec.wi) * woDotGeoN)/
(Frame::cosTheta(bRec.wo) * wiDotGeoN));
value *= bsdf->eval(bRec) * correction;
/* Splat onto the accumulation buffer */
m_workResult->put(dRec.uv, (Float *) &value[0]);
}
示例3: sample
Spectrum sample(BSDFSamplingRecord &bRec, Float &pdf, const Point2 &_sample) const {
Point2 sample(_sample);
if (bRec.component == -1) {
/* Choose a component based on the normalized weights */
size_t entry = m_pdf.sampleReuse(sample.x);
Spectrum result = m_bsdfs[entry]->sample(bRec, pdf, sample);
if (result.isZero()) // sampling failed
return result;
result *= m_weights[entry] * pdf;
pdf *= m_pdf[entry];
EMeasure measure = BSDF::getMeasure(bRec.sampledType);
for (size_t i=0; i<m_bsdfs.size(); ++i) {
if (entry == i)
continue;
pdf += m_bsdfs[i]->pdf(bRec, measure) * m_pdf[i];
result += m_bsdfs[i]->eval(bRec, measure) * m_weights[i];
}
bRec.sampledComponent += m_offsets[entry];
return result/pdf;
} else {
/* Pick out an individual component */
int requestedComponent = bRec.component;
int bsdfIndex = m_indices[requestedComponent].first;
bRec.component = m_indices[requestedComponent].second;
Spectrum result = m_bsdfs[bsdfIndex]->sample(bRec, pdf, sample)
* m_weights[bsdfIndex];
bRec.component = bRec.sampledComponent = requestedComponent;
return result;
}
}
示例4: E
Spectrum E(const Scene *scene, const Intersection &its, const Medium *medium,
Sampler *sampler, int nSamples, bool handleIndirect) const {
Spectrum EDir(0.0f), EIndir(0.0f);
DirectSamplingRecord dRec(its);
/* Sample the direct illumination component */
for (int i=0; i<nSamples; i++) {
int maxIntermediateInteractions = -1;
Spectrum directRadiance = scene->sampleAttenuatedEmitterDirect(
dRec, its, medium, maxIntermediateInteractions, sampler->next2D());
if (!directRadiance.isZero()) {
Float dp = dot(dRec.d, its.shFrame.n);
if (dp > 0)
EDir += directRadiance * dp;
}
}
if (handleIndirect) {
RadianceQueryRecord rRec(scene, sampler);
rRec.newQuery(RadianceQueryRecord::ERadianceNoEmission, medium);
rRec.its = its;
if (!m_irrCache->get(rRec.its, EIndir))
handleMiss(RayDifferential(), rRec, EIndir);
}
return (EDir / (Float) nSamples) + EIndir;
}
示例5: handleEmission
void CaptureParticleWorker::handleEmission(const PositionSamplingRecord &pRec,
const Medium *medium, const Spectrum &weight) {
if (m_bruteForce)
return;
DirectSamplingRecord dRec(pRec.p, pRec.time);
int maxInteractions = m_maxPathDepth - 1;
/* Create a dummy intersection to ensure that sampleAttenuatedSensorDirect()
treats the light source vertex as being located on a surface */
Intersection its;
its.p = pRec.p;
Spectrum value = weight * m_scene->sampleAttenuatedSensorDirect(
dRec, its, medium, maxInteractions, m_sampler->next2D(), m_sampler);
if (value.isZero())
return;
const Emitter *emitter = static_cast<const Emitter *>(pRec.object);
value *= emitter->evalDirection(DirectionSamplingRecord(dRec.d), pRec);
/* Splat onto the accumulation buffer */
m_workResult->put(dRec.uv, (Float *) &value[0]);
}
示例6: eval
Spectrum eval(const BSDFSamplingRecord &bRec, EMeasure measure) const {
bool hasNested = (bRec.typeMask & m_nested->getType() & BSDF::EAll)
&& (bRec.component == -1 || bRec.component < (int) m_components.size()-1);
bool hasSpecular = (bRec.typeMask & EGlossyReflection)
&& (bRec.component == -1 || bRec.component == (int) m_components.size()-1)
&& measure == ESolidAngle;
/* Evaluate the roughness texture */
Float alpha = m_alpha->eval(bRec.its).average();
Float alphaT = m_distribution.transformRoughness(alpha);
Spectrum result(0.0f);
if (hasSpecular && Frame::cosTheta(bRec.wo) * Frame::cosTheta(bRec.wi) > 0) {
/* Calculate the reflection half-vector */
const Vector H = normalize(bRec.wo+bRec.wi)
* signum(Frame::cosTheta(bRec.wo));
/* Evaluate the microsurface normal distribution */
const Float D = m_distribution.eval(H, alphaT);
/* Fresnel term */
const Float F = fresnelDielectricExt(absDot(bRec.wi, H), m_eta);
/* Smith's shadow-masking function */
const Float G = m_distribution.G(bRec.wi, bRec.wo, H, alphaT);
/* Calculate the specular reflection component */
Float value = F * D * G /
(4.0f * std::abs(Frame::cosTheta(bRec.wi)));
result += m_specularReflectance->eval(bRec.its) * value;
}
if (hasNested) {
BSDFSamplingRecord bRecInt(bRec);
bRecInt.wi = refractTo(EInterior, bRec.wi);
bRecInt.wo = refractTo(EInterior, bRec.wo);
Spectrum nestedResult = m_nested->eval(bRecInt, measure) *
m_roughTransmittance->eval(std::abs(Frame::cosTheta(bRec.wi)), alpha) *
m_roughTransmittance->eval(std::abs(Frame::cosTheta(bRec.wo)), alpha);
Spectrum sigmaA = m_sigmaA->eval(bRec.its) * m_thickness;
if (!sigmaA.isZero())
nestedResult *= (-sigmaA *
(1/std::abs(Frame::cosTheta(bRecInt.wi)) +
1/std::abs(Frame::cosTheta(bRecInt.wo)))).exp();
if (measure == ESolidAngle) {
/* Solid angle compression & irradiance conversion factors */
nestedResult *= m_invEta * m_invEta *
Frame::cosTheta(bRec.wi) * Frame::cosTheta(bRec.wo)
/ (Frame::cosTheta(bRecInt.wi) * Frame::cosTheta(bRecInt.wo));
}
result += nestedResult;
}
return result;
}
示例7: E
Spectrum SamplingIntegrator::E(const Scene *scene, const Intersection &its,
const Medium *medium, Sampler *sampler, int nSamples, bool handleIndirect) const {
Spectrum E(0.0f);
RadianceQueryRecord query(scene, sampler);
DirectSamplingRecord dRec(its);
Frame frame(its.shFrame.n);
sampler->generate(Point2i(0));
for (int i=0; i<nSamples; i++) {
/* Sample the direct illumination component */
int maxIntermediateInteractions = -1;
Spectrum directRadiance = scene->sampleAttenuatedEmitterDirect(
dRec, its, medium, maxIntermediateInteractions, query.nextSample2D());
if (!directRadiance.isZero()) {
Float dp = dot(dRec.d, its.shFrame.n);
if (dp > 0)
E += directRadiance * dp;
}
/* Sample the indirect illumination component */
if (handleIndirect) {
query.newQuery(RadianceQueryRecord::ERadianceNoEmission, medium);
Vector d = frame.toWorld(Warp::squareToCosineHemisphere(query.nextSample2D()));
++query.depth;
query.medium = medium;
E += Li(RayDifferential(its.p, d, its.time), query) * M_PI;
}
sampler->advance();
}
return E / (Float) nSamples;
}
示例8: createGatherPoints
int createGatherPoints(Scene *scene, const RayDifferential &ray,
const Point2 &sample, Sampler *sampler, const Spectrum &weight,
std::vector<GatherPoint> &gatherPoints, int depth) {
int count = 0;
if (depth >= m_maxDepth && m_maxDepth != -1)
return 0;
GatherPoint p;
if (scene->rayIntersect(ray, p.its)) {
const BSDF *bsdf = p.its.shape->getBSDF();
if (!bsdf) {
p.radius = 0;
p.sample = sample;
gatherPoints.push_back(p);
++count;
} else {
if (bsdf->getType() & BSDF::ESmooth) {
p.weight = weight;
p.sample = sample;
p.radius = m_initialRadius;
p.depth = depth;
if (p.its.isLuminaire())
p.emission = p.its.Le(-ray.d);
gatherPoints.push_back(p);
++count;
}
if (bsdf->getType() & BSDF::EDelta) {
int compCount = bsdf->getComponentCount();
for (int i=0; i<compCount; i++) {
if ((bsdf->getType(i) & BSDF::EDelta) == 0)
continue;
/* Sample the BSDF and recurse */
BSDFQueryRecord bRec(p.its, sampler);
bRec.component = i;
Spectrum bsdfVal = bsdf->sample(bRec, Point2(0.0f));
if (bsdfVal.isZero())
continue;
bsdfVal = bsdf->eval(bRec, EDiscrete);
const Float rrProb = depth < 4 ? 1 : 0.8f;
if (sampler->independent1D() < rrProb) {
RayDifferential recursiveRay(p.its.p, p.its.toWorld(bRec.wo), ray.time);
count += createGatherPoints(scene, recursiveRay, sample, sampler,
weight * bsdfVal / rrProb, gatherPoints, depth+1);
}
}
}
}
} else if (depth == 1) {
/* Generate an invalid sample */
p.emission = scene->LeBackground(ray);
p.radius = 0;
p.sample = sample;
gatherPoints.push_back(p);
++count;
}
return count;
}
示例9: handleSurfaceInteraction
void CaptureParticleWorker::handleSurfaceInteraction(int depth,
bool caustic, const Intersection &its, const Medium *medium,
const Spectrum &weight) {
const ProjectiveCamera *camera = static_cast<const ProjectiveCamera *>(m_camera.get());
Point2 screenSample;
if (camera->positionToSample(its.p, screenSample)) {
Point cameraPosition = camera->getPosition(screenSample);
Float t = dot(camera->getImagePlaneNormal(), its.p-cameraPosition);
if (t < camera->getNearClip() || t > camera->getFarClip())
return;
if (its.isMediumTransition())
medium = its.getTargetMedium(cameraPosition - its.p);
Spectrum transmittance = m_scene->getTransmittance(its.p,
cameraPosition, its.time, medium);
if (transmittance.isZero())
return;
const BSDF *bsdf = its.shape->getBSDF();
Vector wo = cameraPosition - its.p;
Float dist = wo.length(); wo /= dist;
BSDFQueryRecord bRec(its, its.toLocal(wo));
bRec.quantity = EImportance;
Float importance;
if (m_isPerspectiveCamera)
importance = ((const PerspectiveCamera *) camera)->importance(screenSample) / (dist * dist);
else
importance = 1/camera->areaDensity(screenSample);
Vector wi = its.toWorld(its.wi);
/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
Float wiDotGeoN = dot(its.geoFrame.n, wi),
woDotGeoN = dot(its.geoFrame.n, wo);
if (wiDotGeoN * Frame::cosTheta(bRec.wi) <= 0 ||
woDotGeoN * Frame::cosTheta(bRec.wo) <= 0)
return;
/* Adjoint BSDF for shading normals -- [Veach, p. 155] */
Float correction = std::abs(
(Frame::cosTheta(bRec.wi) * woDotGeoN)/
(Frame::cosTheta(bRec.wo) * wiDotGeoN));
/* Splat onto the accumulation buffer */
Ray ray(its.p, wo, 0, dist, its.time);
Spectrum sampleVal = weight * bsdf->fCos(bRec)
* transmittance * (importance * correction);
m_workResult->splat(screenSample, sampleVal, m_filter);
}
}
示例10: sample
Spectrum sample(BSDFSamplingRecord &bRec, const Point2 &_sample) const {
Point2 sample(_sample);
Float weights[2];
weights[1] = std::min((Float) 1.0f, std::max((Float) 0.0f,
m_weight->eval(bRec.its).average()));
weights[0] = 1-weights[1];
if (bRec.component == -1) {
size_t entry;
if (sample.x < weights[0]) {
entry = 0; sample.x /= weights[0];
} else {
entry = 1; sample.x = (sample.x - weights[0]) / weights[1];
}
Float pdf;
Spectrum result = m_bsdfs[entry]->sample(bRec, pdf, sample);
if (result.isZero()) // sampling failed
return result;
result *= weights[entry] * pdf;
pdf *= weights[entry];
EMeasure measure = BSDF::getMeasure(bRec.sampledType);
for (size_t i=0; i<m_bsdfs.size(); ++i) {
if (entry == i)
continue;
pdf += m_bsdfs[i]->pdf(bRec, measure) * weights[i];
result += m_bsdfs[i]->eval(bRec, measure) * weights[i];
}
bRec.sampledComponent += m_offsets[entry];
return result/pdf;
} else {
/* Pick out an individual component */
int requestedComponent = bRec.component;
int bsdfIndex = m_indices[requestedComponent].first;
bRec.component = m_indices[requestedComponent].second;
Spectrum result = m_bsdfs[bsdfIndex]->sample(bRec, sample)
* weights[bsdfIndex];
bRec.component = bRec.sampledComponent = requestedComponent;
return result;
}
}
示例11: sample
Spectrum sample(BSDFSamplingRecord &bRec, const Point2 &sample) const {
const Intersection& its = bRec.its;
Intersection perturbed(its);
perturbed.shFrame = getFrame(its);
BSDFSamplingRecord perturbedQuery(perturbed, bRec.sampler, bRec.mode);
perturbedQuery.wi = perturbed.toLocal(its.toWorld(bRec.wi));
perturbedQuery.sampler = bRec.sampler;
perturbedQuery.typeMask = bRec.typeMask;
perturbedQuery.component = bRec.component;
Spectrum result = m_nested->sample(perturbedQuery, sample);
if (!result.isZero()) {
bRec.sampledComponent = perturbedQuery.sampledComponent;
bRec.sampledType = perturbedQuery.sampledType;
bRec.wo = its.toLocal(perturbed.toWorld(perturbedQuery.wo));
bRec.eta = perturbedQuery.eta;
if (Frame::cosTheta(bRec.wo) * Frame::cosTheta(perturbedQuery.wo) <= 0)
return Spectrum(0.0f);
}
return result;
}
示例12: sample
Spectrum sample(BSDFSamplingRecord &bRec, Float &pdf, const Point2 &sample) const {
bool flipped = false;
if (Frame::cosTheta(bRec.wi) < 0) {
bRec.wi.z *= -1;
flipped = true;
if (bRec.component != -1)
bRec.component -= m_nestedBRDF[0]->getComponentCount();
}
Spectrum result = m_nestedBRDF[flipped ? 1 : 0]->sample(bRec, pdf, sample);
if (flipped) {
bRec.wi.z *= -1;
if (bRec.component != -1)
bRec.component += m_nestedBRDF[0]->getComponentCount();
if (!result.isZero() && pdf != 0) {
bRec.wo.z *= -1;
bRec.sampledComponent += m_nestedBRDF[0]->getComponentCount();
}
}
return result;
}
示例13: handleMediumInteraction
void CaptureParticleWorker::handleMediumInteraction(int depth, bool caustic,
const MediumSamplingRecord &mRec, const Medium *medium,
Float time, const Vector &wi, const Spectrum &weight) {
const ProjectiveCamera *camera = static_cast<const ProjectiveCamera *>(m_camera.get());
Point2 screenSample;
if (camera->positionToSample(mRec.p, screenSample)) {
Point cameraPosition = camera->getPosition(screenSample);
Float t = dot(camera->getImagePlaneNormal(), mRec.p-cameraPosition);
if (t < camera->getNearClip() || t > camera->getFarClip())
return;
Spectrum transmittance = m_scene->getTransmittance(mRec.p,
cameraPosition, time, medium);
if (transmittance.isZero())
return;
Vector wo = cameraPosition - mRec.p;
Float dist = wo.length(); wo /= dist;
Float importance;
if (m_isPerspectiveCamera)
importance = ((const PerspectiveCamera *) camera)->importance(screenSample) / (dist * dist);
else
importance = 1/camera->areaDensity(screenSample);
/* Splat onto the accumulation buffer */
Ray ray(mRec.p, wo, 0, dist, time);
Spectrum sampleVal = weight * medium->getPhaseFunction()->f(
PhaseFunctionQueryRecord(mRec, wi, wo)) * transmittance * importance;
m_workResult->splat(screenSample, sampleVal, m_filter);
}
}
示例14: generateVPLs
size_t generateVPLs(const Scene *scene, Random *random,
size_t offset, size_t count, int maxDepth, bool prune, std::deque<VPL> &vpls) {
if (maxDepth <= 1)
return 0;
static Sampler *sampler = NULL;
if (!sampler) {
Properties props("halton");
props.setInteger("scramble", 0);
sampler = static_cast<Sampler *> (PluginManager::getInstance()->
createObject(MTS_CLASS(Sampler), props));
sampler->configure();
}
const Sensor *sensor = scene->getSensor();
Float time = sensor->getShutterOpen()
+ 0.5f * sensor->getShutterOpenTime();
const Frame stdFrame(Vector(1,0,0), Vector(0,1,0), Vector(0,0,1));
while (vpls.size() < count) {
sampler->setSampleIndex(++offset);
PositionSamplingRecord pRec(time);
DirectionSamplingRecord dRec;
Spectrum weight = scene->sampleEmitterPosition(pRec,
sampler->next2D());
size_t start = vpls.size();
/* Sample an emitted particle */
const Emitter *emitter = static_cast<const Emitter *>(pRec.object);
if (!emitter->isEnvironmentEmitter() && emitter->needsDirectionSample()) {
VPL lumVPL(EPointEmitterVPL, weight);
lumVPL.its.p = pRec.p;
lumVPL.its.shFrame = pRec.n.isZero() ? stdFrame : Frame(pRec.n);
lumVPL.emitter = emitter;
appendVPL(scene, random, lumVPL, prune, vpls);
weight *= emitter->sampleDirection(dRec, pRec, sampler->next2D());
} else {
/* Hack to get the proper information for directional VPLs */
DirectSamplingRecord diRec(
scene->getKDTree()->getAABB().getCenter(), pRec.time);
Spectrum weight2 = emitter->sampleDirect(diRec, sampler->next2D())
/ scene->pdfEmitterDiscrete(emitter);
if (weight2.isZero())
continue;
VPL lumVPL(EDirectionalEmitterVPL, weight2);
lumVPL.its.p = Point(0.0);
lumVPL.its.shFrame = Frame(-diRec.d);
lumVPL.emitter = emitter;
appendVPL(scene, random, lumVPL, false, vpls);
dRec.d = -diRec.d;
Point2 offset = Warp::squareToUniformDiskConcentric(sampler->next2D());
Vector perpOffset = Frame(diRec.d).toWorld(Vector(offset.x, offset.y, 0));
BSphere geoBSphere = scene->getKDTree()->getAABB().getBSphere();
pRec.p = geoBSphere.center + (perpOffset - dRec.d) * geoBSphere.radius;
weight = weight2 * M_PI * geoBSphere.radius * geoBSphere.radius;
}
int depth = 2;
Ray ray(pRec.p, dRec.d, time);
Intersection its;
while (!weight.isZero() && (depth < maxDepth || maxDepth == -1)) {
if (!scene->rayIntersect(ray, its))
break;
const BSDF *bsdf = its.getBSDF();
BSDFSamplingRecord bRec(its, sampler, EImportance);
Spectrum bsdfVal = bsdf->sample(bRec, sampler->next2D());
if (bsdfVal.isZero())
break;
/* Assuming that BSDF importance sampling is perfect,
the following should equal the maximum albedo
over all spectral samples */
Float approxAlbedo = std::min((Float) 0.95f, bsdfVal.max());
if (sampler->next1D() > approxAlbedo)
break;
else
weight /= approxAlbedo;
VPL vpl(ESurfaceVPL, weight);
vpl.its = its;
if (BSDF::getMeasure(bRec.sampledType) == ESolidAngle)
appendVPL(scene, random, vpl, prune, vpls);
weight *= bsdfVal;
Vector wi = -ray.d, wo = its.toWorld(bRec.wo);
ray = Ray(its.p, wo, 0.0f);
//.........这里部分代码省略.........
示例15: sample
inline Spectrum sample(BSDFSamplingRecord &bRec, Float &_pdf, const Point2 &_sample) const {
bool hasNested = (bRec.typeMask & m_nested->getType() & BSDF::EAll)
&& (bRec.component == -1 || bRec.component < (int) m_components.size()-1);
bool hasSpecular = (bRec.typeMask & EGlossyReflection)
&& (bRec.component == -1 || bRec.component == (int) m_components.size()-1);
bool choseSpecular = hasSpecular;
Point2 sample(_sample);
/* Evaluate the roughness texture */
Float alpha = m_alpha->eval(bRec.its).average();
Float alphaT = m_distribution.transformRoughness(alpha);
Float probSpecular;
if (hasSpecular && hasNested) {
/* Find the probability of sampling the diffuse component */
probSpecular = 1 - m_roughTransmittance->eval(std::abs(Frame::cosTheta(bRec.wi)), alpha);
/* Reallocate samples */
probSpecular = (probSpecular*m_specularSamplingWeight) /
(probSpecular*m_specularSamplingWeight +
(1-probSpecular) * (1-m_specularSamplingWeight));
if (sample.y <= probSpecular) {
sample.y /= probSpecular;
} else {
sample.y = (sample.y - probSpecular) / (1 - probSpecular);
choseSpecular = false;
}
}
if (choseSpecular) {
/* Perfect specular reflection based on the microsurface normal */
Normal m = m_distribution.sample(sample, alphaT);
bRec.wo = reflect(bRec.wi, m);
bRec.sampledComponent = (int) m_components.size() - 1;
bRec.sampledType = EGlossyReflection;
bRec.eta = 1.0f;
/* Side check */
if (Frame::cosTheta(bRec.wo) * Frame::cosTheta(bRec.wi) <= 0)
return Spectrum(0.0f);
} else {
Vector wiBackup = bRec.wi;
bRec.wi = refractTo(EInterior, bRec.wi);
Spectrum result = m_nested->sample(bRec, _pdf, sample);
bRec.wi = wiBackup;
if (result.isZero())
return Spectrum(0.0f);
bRec.wo = refractTo(EExterior, bRec.wo);
if (bRec.wo.isZero())
return Spectrum(0.0f);
}
/* Guard against numerical imprecisions */
EMeasure measure = getMeasure(bRec.sampledType);
_pdf = pdf(bRec, measure);
if (_pdf == 0)
return Spectrum(0.0f);
else
return eval(bRec, measure) / _pdf;
}