1. 程式人生 > >PBRT_V2 總結記錄 BxDF::Sample_f

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.