PBRT_V2 总结记录 BxDF::Sample_f

Spectrum BxDF::Sample_f(const Vector &wo, Vector *wi,
                        float u1, float u2, float *pdf) const {
    // Cosine-sample the hemisphere, flipping the direction if necessary
    *wi = CosineSampleHemisphere(u1, u2);
    if (wo.z < 0.) wi->z *= -1.f;
    *pdf = Pdf(wo, *wi);
    return f(wo, *wi);
}

inline bool SameHemisphere(const Vector &w, const Vector &wp) {
    return w.z * wp.z > 0.f;
}

float BxDF::Pdf(const Vector &wo, const Vector &wi) const {
    return SameHemisphere(wo, wi) ? AbsCosTheta(wi) * INV_PI : 0.f;
}

作用:

(BxDF::Sample_f() 的作用:之前《PBRT_V2 总结记录 BxDF 和 BRDFToBTDF 和 ScaledBxDF》 有说到 Sample_f的作用:

【 为什么会有 bsdf->Sample_f(), 因为不是所有的 bsdf 都可以利用 wi, wo来获得一个反射值,像一些镜面反射只会反射某一个方向的,类似这样的镜面反射的BSDF用 delta distributions 来描述是最好的,所以,PBRT就专门用 Sample_f 来特殊处理这些 delta distributions 的 BSDF,Sample_f() 与f() 不同的还有的就是,Sample_f() 会计算wi】,那么这里的BxDF Sample_f 提供了实现了一个默认的方法,而且这个方法的主要目的随机选择一个方向,存储到wi中,而且选择方向的时候,根据的就是 CosineSampleHemisphere,《PBRT_V2 总结记录 Uniformly Sampling Tool Function And Distribution2D》 有说)

The BxDF::Sample_f() method randomly chooses a direction according to a distribution
that is similar to its corresponding scattering function.

BxDF::Sample_f() takes two sample values in the
range [0, 1) that are intended to be used by a transformation-based sampling algorithm

This method returns the sampled direction in *wi and returns the value of p(ωi) in
*pdf. The value of the BSDF for the chosen direction is returned with a Spectrum return
value. The PDF value returned should be measured with respect to solid angle on the
hemisphere, and both the outgoing direction ωo and the sampled incident direction
ωi should be in the standard reflection coordinate system

The default implementation of this method samples the unit hemisphere with a cosineweighted
distribution.
Samples from this distribution will give correct results for any
BRDF that isn’t described by a delta distribution, since there is some probability of
sampling all directions where the BRDF’s value is nonzero: p(ω) > 0 for all ω.

细节

a.

*wi = CosineSampleHemisphere(u1, u2);
if (wo.z < 0.) wi->z *= -1.f;

作用:

(如果传入来的wo.z 是负的话,那么wi 也要取负,保证是wo,wi是同一半球的)

There is a subtlety related to the orientation of the normal in the reflection coordinate
system that must be accounted for here: the direction returned by Malley’s method
will always be in the hemisphere around (0, 0, 1). If the ωo direction is in the opposite
hemisphere, then ωi must be flipped to lie in the same hemisphere as ωo. This issue is a
direct consequence(直接后果) of the fact that pbrt does not flip the normal to be on the same side
of the surface as the ωo direction.

b.

float BxDF::Pdf(const Vector &wo, const Vector &wi) const {
    return SameHemisphere(wo, wi) ? AbsCosTheta(wi) * INV_PI : 0.f;
}

作用:

(BxDF 默认的返回 PDF,如果是同一半球的话,就 p(ω) = cos θ/π,如果不是的话,就是0

While BxDF::Sample_f() returns the value of the PDF for the direction it chose, the
BxDF::Pdf() method returns the value of the PDF for an arbitrary given direction. This
method is useful for multiple importance sampling,
where it is necessary to be able
to find the PDF for directions sampled from other distributions. It is crucial(重要) that any

BxDF subclass that overrides the BxDF::Sample_f() method also override the BxDF::Pdf()
method so that the two return consistent results.

To actually evaluate the PDF for the cosine-weighted sampling method (which we
showed earlier was p(ω) = cos θ/π), it is first necessary to check that ωo and ωi lie
on the same side of the surface; if not, the sampling probability is zero.
Otherwise, the
method computes |n · ωi|. One potential pitfall with this method is that the order of the
ωo and ωi arguments is significant. For the cosine-weighted distribution here, for example,
p(ωo) != p(ωi) in general. Code that calls this method must be careful to use the
correct argument ordering.

猜你喜欢

转载自blog.csdn.net/aa20274270/article/details/84927831