PBRT_V2 总结记录 <37> BSDF

BSDF 类


class BSDF {
public:
    // BSDF Public Methods
    Spectrum Sample_f(const Vector &wo, Vector *wi, const BSDFSample &bsdfSample,
                      float *pdf, BxDFType flags = BSDF_ALL,
                      BxDFType *sampledType = NULL) const;
    float Pdf(const Vector &wo, const Vector &wi,
              BxDFType flags = BSDF_ALL) const;
    BSDF(const DifferentialGeometry &dgs, const Normal &ngeom,
         float eta = 1.f);
    inline void Add(BxDF *bxdf);
    int NumComponents() const { return nBxDFs; }
    int NumComponents(BxDFType flags) const;
    Vector WorldToLocal(const Vector &v) const {
        return Vector(Dot(v, sn), Dot(v, tn), Dot(v, nn));
    }
    Vector LocalToWorld(const Vector &v) const {
        return Vector(sn.x * v.x + tn.x * v.y + nn.x * v.z,
                      sn.y * v.x + tn.y * v.y + nn.y * v.z,
                      sn.z * v.x + tn.z * v.y + nn.z * v.z);
    }
    Spectrum f(const Vector &woW, const Vector &wiW, BxDFType flags = BSDF_ALL) const;
    Spectrum rho(RNG &rng, BxDFType flags = BSDF_ALL,
                 int sqrtSamples = 6) const;
    Spectrum rho(const Vector &wo, RNG &rng, BxDFType flags = BSDF_ALL,
                 int sqrtSamples = 6) const;

    // BSDF Public Data
    const DifferentialGeometry dgShading;
    const float eta;
private:
    // BSDF Private Methods
    ~BSDF() { }

    // BSDF Private Data
    Normal nn, ng;
    Vector sn, tn;
    int nBxDFs;
#define MAX_BxDFS 8
    BxDF *bxdfs[MAX_BxDFS];
    friend class MixMaterial;
};

类的作用:

(BSDF 表示的 是 BRDF 和 BTDF 的 集合。)

The BSDF class represents a collection of BRDFs and BTDFs. Grouping them in this manner
allows the rest of the system to work with composite BSDFs directly, rather than having
to consider all of the components they may have been built from. Equally important, the
BSDF class hides some of the details of shading normals from the rest of the system. Shading
normals, either from per-vertex normals in triangle meshes or from bump mapping,
can substantially improve the visual richness of rendered scenes,
but because they are

an ad hoc construct, they are tricky to incorporate into a physically based renderer. The
issues that they introduce are handled in the BSDF implementation.

 

1. 构造函数


BSDF::BSDF(const DifferentialGeometry &dg, const Normal &ngeom,
           float e)
    : dgShading(dg), eta(e) {
    ng = ngeom;
    nn = dgShading.nn;
    sn = Normalize(dgShading.dpdu);
    tn = Cross(nn, sn);
    nBxDFs = 0;
}

作用:

(构造函数需要一个DifferentialGeometry,DifferentialGeometry表示的就是几何体与Ray的相交点的几何信息集合,包含了相交坐标,法线,dpdu等值,还有,这里需要注意的就是,会利用这个DifferentialGeometry的法线和切线,构造一个 所谓的 reflection coordinate system,就如同之前《Reflection Models 和 The Shading Coordinate System》有说,传入 BRDF和BTDF 的 向量或者从 BRDF和BTDF 传出的 向量 都是 关于定义在 reflection coordinate system空间 上的,所以,一个世界坐标向量 w, 在传入 BRDF 或者 BTDF之前,需要先转换到 reflection coordinate system 空间上)

The BSDF constructor takes a DifferentialGeometry object that represents the shadingi
differential geometry, the true surface normal ngeom, and, optionally, the index of refraction
of the medium enclosed by the surface. It stores these values in member variables
and constructs an orthonormal coordinate system with the shading normal as one of the
axes;
this will be useful for transforming directions to and from the BxDF coordinate system
described in Section 8.1. Throughout this section, we will use the convention that ns
denotes the shading normal and ng the geometric normal
.

 

2. inline void Add(BxDF *bxdf);

inline void BSDF::Add(BxDF *b) {
  Assert(nBxDFs < MAX_BxDFS);
  bxdfs[nBxDFs++] = b;
}

int nBxDFs;
#define MAX_BxDFS 8
BxDF *bxdfs[MAX_BxDFS];

作用:

(BSDF存储固定大小数目的BxDF,8个基本够用)

The BSDF implementation stores only a fixed limited number of individual BxDF components.
It could easily be extended to allocate more space if more components were given
to it, although this isn’t necessary for any of the Material implementations in pbrt thus
far, and the current limit of eight is plenty for almost all practical applications.

 

3. int NumComponents() const { return nBxDFs; }
    int NumComponents(BxDFType flags) const;

作用:

(返回这个BSDF中有多少个BxDF 或者,这个BSDF中,某一个BxDF有多少个)

For other parts of the system that need additional information about the particular
BRDFs and BTDFs present, two different methods return the number of BxDFs stored by
the BSDF; the second only returns the number that matches a particular set of BxDFType
flags.
Note that we could use a single function with a default parameter value of BSDF_
ALL, but the no-argument variant of BSDF::NumComponents() is called frequently, so we
would like to avoid the overhead of checking the flags of the BxDFs individually in that
case.

 

4.  

Vector WorldToLocal(const Vector &v) const

Vector LocalToWorld(const Vector &v) const

Vector WorldToLocal(const Vector &v) const {
        return Vector(Dot(v, sn), Dot(v, tn), Dot(v, nn));
    }
    Vector LocalToWorld(const Vector &v) const {
        return Vector(sn.x * v.x + tn.x * v.y + nn.x * v.z,
                      sn.y * v.x + tn.y * v.y + nn.y * v.z,
                      sn.z * v.x + tn.z * v.y + nn.z * v.z);
    }

作用:

(主要就是把 world的向量 变换到 Shading Coordinate System 中,或者是相反的操作)

The BSDF also has methods that perform transformations to and from the local coordinate
system expected by BxDFs. Recall that, in this coordinate system, the surface normal
is along the z axis (0, 0, 1), the primary tangent is (1, 0, 0), and the secondary tangent
is (0, 1, 0). The transformation of directions into “shading space” simplifies many of the
BxDF implementations in Chapter 8.

In this case, we don’t need to compute the inverse transpose of M to transform normals
(recall the discussion of transforming normals in Section 2.8.3). BecauseMis an orthogonal
matrix (its rows and columns are mutually orthogonal), its inverse is equal to its
transpose, so it is its own inverse transpose already.

The method that takes vectors back from local space to world space uses the transpose to
invert M before doing the appropriate dot products.

 

5. Spectrum f(const Vector &woW, const Vector &wiW, BxDFType flags = BSDF_ALL) const;

Spectrum BSDF::f(const Vector &woW, const Vector &wiW,
                 BxDFType flags) const {
    PBRT_STARTED_BSDF_EVAL();
    Vector wi = WorldToLocal(wiW), wo = WorldToLocal(woW);
    if (Dot(wiW, ng) * Dot(woW, ng) > 0) // ignore BTDFs
        flags = BxDFType(flags & ~BSDF_TRANSMISSION);
    else // ignore BRDFs
        flags = BxDFType(flags & ~BSDF_REFLECTION);
    Spectrum f = 0.;
    for (int i = 0; i < nBxDFs; ++i)
        if (bxdfs[i]->MatchesFlags(flags))
            f += bxdfs[i]->f(wo, wi);
    PBRT_FINISHED_BSDF_EVAL();
    return f;
}

作用:

(这里有一个规则,如果wi ,wo 同时都和 ng 在同一个半球,那么就只计算 BRDF,如果不是这种情况的话,就只计算 BTDF,之后计算入射线与法线的夹角的时候,不是使用ng, 而是使用ns,ng只是用来判断使用BRDF或者BTDF )

The geometric normal, ng, defined by the surface geometry, and the shading normal,
ns, given by per-vertex normals and/or bump mapping, will generally define different hemispheres
for integrating incident illumination to compute surface reflection.
This inconsistency is important to
handle carefully since it can otherwise lead to artifacts in images.

When evaluating the BSDF, we use the geometric normal to decide if we should be evaluating reflection or transmission:
if ωi and ωo lie in the same hemisphere with respect to ng, we evaluate the BRDFs, and
otherwise we evaluate the BTDFs.
In evaluating the scattering equation, however, the dot
product of the normal and the incident direction is still taken with the shading normal,
rather than the geometric normal.

Given these conventions, the method that evaluates the BSDF for a given pair of directions
is straightforward. It starts by transforming the world space direction vectors to
local BSDF space and then determines whether it should use the BRDFs or the BTDFs. It
then loops over the appropriate set and evaluates the sum of their contributions.

 

6. 

Spectrum rho(RNG &rng, BxDFType flags = BSDF_ALL,
                 int sqrtSamples = 6) const;
Spectrum rho(const Vector &wo, RNG &rng, BxDFType flags = BSDF_ALL,
                 int sqrtSamples = 6) const;


Spectrum BSDF::rho(RNG &rng, BxDFType flags, int sqrtSamples) const {
    int nSamples = sqrtSamples * sqrtSamples;
    float *s1 = ALLOCA(float, 2 * nSamples);
    StratifiedSample2D(s1, sqrtSamples, sqrtSamples, rng);
    float *s2 = ALLOCA(float, 2 * nSamples);
    StratifiedSample2D(s2, sqrtSamples, sqrtSamples, rng);

    Spectrum ret(0.);
    for (int i = 0; i < nBxDFs; ++i)
        if (bxdfs[i]->MatchesFlags(flags))
            ret += bxdfs[i]->rho(nSamples, s1, s2);
    return ret;
}


Spectrum BSDF::rho(const Vector &wo, RNG &rng, BxDFType flags,
                   int sqrtSamples) const {
    int nSamples = sqrtSamples * sqrtSamples;
    float *s1 = ALLOCA(float, 2 * nSamples);
    StratifiedSample2D(s1, sqrtSamples, sqrtSamples, rng);
    Spectrum ret(0.);
    for (int i = 0; i < nBxDFs; ++i)
        if (bxdfs[i]->MatchesFlags(flags))
            ret += bxdfs[i]->rho(wo, nSamples, s1);
    return ret;
}

作用:

pbrt also provides BSDF methods that return the summed reflectance values of their
individual BxDFs.
These methods just loop over the BxDFs and call the appropriate
BxDF::rho() methods and therefore won’t be shown here. A RNG must be passed to these
methods so that they can generate random samples for BxDF implementations for use in
Monte Carlo sampling algorithms if needed—recall the BxDF::rho() interface defined in
Section 8.1.1.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值