PBRT_V2 总结记录 <53> Procedural Texturing

Solid Texture And Procedural Texturing :

it is natural to generalize texture functions to be defined
over three-dimensional domains (often called solid textures) rather than just 2D (s , t).

Solid textures introduce a new problem, however: texture representation. A threedimensional
image map takes up a fair amount of storage space and is much harder to
acquire than a two-dimensional texture map, which can be extracted from photographs or painted by an artist.

Therefore, procedural texturing—the idea that programs could
be executed to generate texture values at arbitrary positions on surfaces in the scene—
came into use at the same time that solid texturing was developed.

(Solid Texture 的 texture functions 定义在 三维空间,但是由于 这样的三维空间image 占用 存储空间较大,所以 就引入了 procedural texturing,procedural texturing 其实就是 计算texture的值出来,而不是从图片中取值)

 

UVTexture 类


// UVTexture Declarations
class UVTexture : public Texture<Spectrum> {
public:
    // UVTexture Public Methods
    UVTexture(TextureMapping2D *m) {
        mapping = m;
    }
    ~UVTexture() {
        delete mapping;
    }
    Spectrum Evaluate(const DifferentialGeometry &dg) const {
        float s, t, dsdx, dtdx, dsdy, dtdy;
        mapping->Map(dg, &s, &t, &dsdx, &dtdx, &dsdy, &dtdy);
        float rgb[3] = { s - Floor2Int(s), t - Floor2Int(t), 0.f };
        return Spectrum::FromRGB(rgb);
    }
private:
    TextureMapping2D *mapping;
};

作用:

(UVTexture 是一个 procedural texture,u 表示 红色,v 表示 绿色)

Our first procedural texture converts the surface’s (u, v) coordinates into the red and
green components of a Spectrum It is especially useful when debugging
the parameterization of a new Shape。
(The u parameter is
mapped to the red channel, and the v parameter is mapped to green.)

 

Checkerboard2DTexture 类

template <typename T> class Checkerboard2DTexture : public Texture<T> {
public:
    // Checkerboard2DTexture Public Methods
    Checkerboard2DTexture(TextureMapping2D *m, Reference<Texture<T> > c1,
                          Reference<Texture<T> > c2, const string &aa)
        : mapping(m), tex1(c1), tex2(c2) {
        // Select antialiasing method for _Checkerboard2DTexture_
        if (aa == "none")             aaMethod = NONE;
        else if (aa == "closedform")  aaMethod = CLOSEDFORM;
        else {
            Warning("Antialiasing mode \"%s\" not understood by "
                    "Checkerboard2DTexture; using \"closedform\"", aa.c_str());
            aaMethod = CLOSEDFORM;
        }
    }
    ~Checkerboard2DTexture() {
        delete mapping;
    }
    T Evaluate(const DifferentialGeometry &dg) const {
        float s, t, dsdx, dtdx, dsdy, dtdy;
        mapping->Map(dg, &s, &t, &dsdx, &dtdx, &dsdy, &dtdy);
        if (aaMethod == NONE) {
            // Point sample _Checkerboard2DTexture_
            if ((Floor2Int(s) + Floor2Int(t)) % 2 == 0)
                return tex1->Evaluate(dg);
            return tex2->Evaluate(dg);
        }
        else {
            // Compute closed-form box-filtered _Checkerboard2DTexture_ value

            // Evaluate single check if filter is entirely inside one of them
            float ds = max(fabsf(dsdx), fabsf(dsdy));
            float dt = max(fabsf(dtdx), fabsf(dtdy));
            float s0 = s - ds, s1 = s + ds;
            float t0 = t - dt, t1 = t + dt;
            if (Floor2Int(s0) == Floor2Int(s1) && Floor2Int(t0) == Floor2Int(t1)) {
                // Point sample _Checkerboard2DTexture_
                if ((Floor2Int(s) + Floor2Int(t)) % 2 == 0)
                    return tex1->Evaluate(dg);
                return tex2->Evaluate(dg);
            }

            // Apply box filter to checkerboard region
#define BUMPINT(x) \
                (Floor2Int((x)/2) + \
                 2.f * max((x/2)-Floor2Int(x/2) - .5f, 0.f))
            float sint = (BUMPINT(s1) - BUMPINT(s0)) / (2.f * ds);
            float tint = (BUMPINT(t1) - BUMPINT(t0)) / (2.f * dt);
            float area2 = sint + tint - 2.f * sint * tint;
            if (ds > 1.f || dt > 1.f)
                area2 = .5f;
            return (1.f - area2) * tex1->Evaluate(dg) +
                   area2         * tex2->Evaluate(dg);
        }
    }
private:
    // Checkerboard2DTexture Private Data
    TextureMapping2D *mapping;
    Reference<Texture<T> > tex1, tex2;
    enum { NONE, CLOSEDFORM } aaMethod;
};

类的作用:

(棋盘纹理)

The checkerboard is the canonical(标准) procedural texture . The (s , t) texture
coordinates are used to break up(打碎) parameter space into square regions that are shaded with
alternating patterns. Rather than just supporting checkerboards that switch between two
fixed colors, the implementation here allows the user to pass in two textures to color the
alternating regions. The traditional black-and-white checkerboard is obtained by passing
two ConstantTextures.

 

1. 构造函数

    Checkerboard2DTexture(TextureMapping2D *m, Reference<Texture<T> > c1,
                          Reference<Texture<T> > c2, const string &aa)
        : mapping(m), tex1(c1), tex2(c2) {
        // Select antialiasing method for _Checkerboard2DTexture_
        if (aa == "none")             aaMethod = NONE;
        else if (aa == "closedform")  aaMethod = CLOSEDFORM;
        else {
            Warning("Antialiasing mode \"%s\" not understood by "
                    "Checkerboard2DTexture; using \"closedform\"", aa.c_str());
            aaMethod = CLOSEDFORM;
        }
    }

作用:

(构造函数也是传入 aa 参数,来用棋盘纹理来测试各种抗锯齿方法)

For simplicity, the frequency of the check function is 1 in (s , t) space: checks are one
unit wide in each direction. The effective frequency can always be changed by the
TextureMapping2D class with an appropriate scale of the (s , t) coordinates.

The checkerboard is good for demonstrating trade-offs(权衡) between various antialiasing(抗锯齿) approaches
for procedural textures. The implementation here supports both simple point
sampling (no antialiasing) and a closed-form box filter evaluated over the filter region

 

 

2. T Evaluate(const DifferentialGeometry &dg) const

    T Evaluate(const DifferentialGeometry &dg) const {
        float s, t, dsdx, dtdx, dsdy, dtdy;
        mapping->Map(dg, &s, &t, &dsdx, &dtdx, &dsdy, &dtdy);
        if (aaMethod == NONE) {
            // Point sample _Checkerboard2DTexture_
            if ((Floor2Int(s) + Floor2Int(t)) % 2 == 0)
                return tex1->Evaluate(dg);
            return tex2->Evaluate(dg);
        }
        else {
            // Compute closed-form box-filtered _Checkerboard2DTexture_ value

            // Evaluate single check if filter is entirely inside one of them
            float ds = max(fabsf(dsdx), fabsf(dsdy));
            float dt = max(fabsf(dtdx), fabsf(dtdy));
            float s0 = s - ds, s1 = s + ds;
            float t0 = t - dt, t1 = t + dt;
            if (Floor2Int(s0) == Floor2Int(s1) && Floor2Int(t0) == Floor2Int(t1)) {
                // Point sample _Checkerboard2DTexture_
                if ((Floor2Int(s) + Floor2Int(t)) % 2 == 0)
                    return tex1->Evaluate(dg);
                return tex2->Evaluate(dg);
            }

            // Apply box filter to checkerboard region
#define BUMPINT(x) \
                (Floor2Int((x)/2) + \
                 2.f * max((x/2)-Floor2Int(x/2) - .5f, 0.f))
            float sint = (BUMPINT(s1) - BUMPINT(s0)) / (2.f * ds);
            float tint = (BUMPINT(t1) - BUMPINT(t0)) / (2.f * dt);
            float area2 = sint + tint - 2.f * sint * tint;
            if (ds > 1.f || dt > 1.f)
                area2 = .5f;
            return (1.f - area2) * tex1->Evaluate(dg) +
                   area2         * tex2->Evaluate(dg);
        }
    }

作用:

The evaluation routine does the usual texture coordinate and differential(微分) computation
and then uses the appropriate fragment to compute an antialiased checkerboard value
(or not antialiased, if point sampling has been selected).

 

细节

a.

        if (aaMethod == NONE) {
            // Point sample _Checkerboard2DTexture_
            if ((Floor2Int(s) + Floor2Int(t)) % 2 == 0)
                return tex1->Evaluate(dg);
            return tex2->Evaluate(dg);
        }

作用:

(没有抗锯齿的情况下,直接利用 s,t 从 tex1 和 tex2 取值)

The simplest case is to ignore antialiasing and just point-sample the checkerboard texture
at the point.
For this case, after getting the (s , t) texture coordinates from the
TextureMapping2D, the integer checkerboard coordinates for that (s , t) position are computed,
added together, and checked for odd or even parity to determine which of the two
textures to evaluate.

 

b.

            // Evaluate single check if filter is entirely inside one of them
            float ds = max(fabsf(dsdx), fabsf(dsdy));
            float dt = max(fabsf(dtdx), fabsf(dtdy));
            float s0 = s - ds, s1 = s + ds;
            float t0 = t - dt, t1 = t + dt;
            if (Floor2Int(s0) == Floor2Int(s1) && Floor2Int(t0) == Floor2Int(t1)) {
                // Point sample _Checkerboard2DTexture_
                if ((Floor2Int(s) + Floor2Int(t)) % 2 == 0)
                    return tex1->Evaluate(dg);
                return tex2->Evaluate(dg);
            }

作用:

(当 整个 filter 区域都在一个 棋盘格子的时候,就直接不进行抗锯齿,那么,怎么判断 整个 filter 区域都在一个 棋盘格子呢?主要的思路就是 计算 filter 的 包围盒,判断这个包围盒的四个角 是否在 同一个格子里面,怎么计算这个包围盒,主要就是利用 偏导数来计算)

The easiest case happens when the entire filter region
lies inside a single check (Figure 10.19). In this case, we simply need to determine which
of the check types we are inside and evaluate that one. As long as the Texture inside that
check does appropriate antialiasing itself, the result for this case will be antialiased.

It’s straightforward to check if the entire filter region is inside a single check by computing
its bounding box and seeing if its extent lies inside the same check.
For the remainder of
this section, we will use the axis-aligned bounding box of the filter region given by the
partial derivatives ∂s/∂x, ∂s/∂y, and so on, as the area to filter over,
rather than trying to
filter over the ellipse defined by the partial derivatives as the EWA filter did (Figure 10.20).
This simplifies the implementation here, although somewhat increases the blurriness of
the filtered values. The variables ds and dt in the following hold half the filter width in
each direction, so the total area filtered over ranges from (s-ds, t-dt) to (s+ds, t+dt).

 

Figure 10.19: The Easy Case for Filtering the Checkerboard. If the filter region around the lookup
point is entirely in one check, the checkerboard texture doesn’t need to worry about antialiasing and
can just evaluate the texture for that check.

 

c.

            #define BUMPINT(x) \
                (Floor2Int((x)/2) + \
                 2.f * max((x/2)-Floor2Int(x/2) - .5f, 0.f))
            float sint = (BUMPINT(s1) - BUMPINT(s0)) / (2.f * ds);
            float tint = (BUMPINT(t1) - BUMPINT(t0)) / (2.f * dt);
            float area2 = sint + tint - 2.f * sint * tint;
            if (ds > 1.f || dt > 1.f)
                area2 = .5f;
            return (1.f - area2) * tex1->Evaluate(dg) +
                   area2         * tex2->Evaluate(dg);

作用:

(这种情况就是,filter 是跨越 多个 棋盘网格,目的就是要计算 哪一种棋盘格子 占用 filter 多少区域, 知道了 占用的  百分比就可以进行 混合了。

因为 棋盘 是一个 2D step function, 就是下面的 c(x),  计算哪一种棋盘格子占用 filter 多少区域,其实就是计算  2D step function 的平均值,因为计算出来的平均值肯定是 [0,1],因为格子不是0, 就是1 ,全部格子相加 再除以 格子的数量,肯定是 [0,1], 那么,平均值就可以表明 1 的格子占用了百分之多少.

BUMPINT 就是 c(x) 的积分, BUMPINT(s0) 表示  从0开始,到 s0 之间 有多少个 "1"格子

float sint = (BUMPINT(s1) - BUMPINT(s0)) / (2.f * ds);  sint 表示 s0-s1 之间平均有多少  "1"格子

float area2 = sint + tint - 2.f * sint * tint;

因为 sint 表示 s0-s1 之间平均有多少  "1"格子, tint 表示 t0-t1 之间平均有多少  "1"格子,

那么  area2 表示的意思就是,sint + tint - 2 * sint * tint = (sint) *(1 - tint) + (1-sint) * tint,  =  "1" 格子 总面积 

the lookup method approximates the filtered value by first computing a
floating-point value that indicates what fraction of the filter region covers each of the
two check types.
This is equivalent to computing the average of the 2D step function that
takes on the value 0 when we are in tex1 and 1 whenwe are in tex2, over the filter region.

Figure 10.21(a) shows a graph of the checkerboard function c(x), defined as

 

 

Given the average value, we can blend between the two subtextures, according to what
fraction of the filter region each one is visible for.

The integral of the 1D checkerboard function c(x) can be used to compute the average
value of the function over some extent.
Inspection of the graph reveals that

To compute the average value of the step function in two dimensions, we separately
compute the integral of the checkerboard in each 1D direction in order to compute its
average value over the filter region.

 

Checkerboard3DTexture 类


template <typename T> class Checkerboard3DTexture : public Texture<T> {
public:
    // Checkerboard3DTexture Public Methods
    Checkerboard3DTexture(TextureMapping3D *m, Reference<Texture<T> > c1,
                          Reference<Texture<T> > c2)
        : mapping(m), tex1(c1), tex2(c2) {
    }
    ~Checkerboard3DTexture() {
        delete mapping;
    }
    T Evaluate(const DifferentialGeometry &dg) const {
        Vector dpdx, dpdy;
        Point p = mapping->Map(dg, &dpdx, &dpdy);
        if ((Floor2Int(p.x) + Floor2Int(p.y) + Floor2Int(p.z)) % 2 == 0)
            return tex1->Evaluate(dg);
        else
            return tex2->Evaluate(dg);
    }
private:
    // Checkerboard3DTexture Private Data
    TextureMapping3D *mapping;
    Reference<Texture<T> > tex1, tex2;
};

类的作用:

(利用 Point 进行 采样 tex1 和tex2)

We can also define a solid checkerboard pattern
based on three-dimensional texture coordinates so that the object appears carved(雕刻) out
of 3D checker cubes 。Like the 2D variant, this implementation chooses
between texture functions based on the lookup position. Note that these two textures
need not be solid textures themselves; the Checkerboard3DTexture merely(只不过) chooses between
them based on the 3D position of the point.

Ignoring antialiasing, the basic computation to see if a point is inside a 3D checker
region is
((Floor2Int(P.x) + Floor2Int(P.y) + Floor2Int(P.z)) % 2 == 0).
The Checkerboard3DTexture doesn’t have any built-in support for antialiasing.

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值