这里回顾GAMES101 Lecture 9,着色(插值、高级纹理映射)。

课程主页:

课程作业:

课程视频:

本讲内容:

  • 着色(第三部分)
    • 重心坐标
    • 纹理查询
    • 纹理的应用

三角形内插值:重心坐标

我们为什么要在三角形内插值?

  • 在顶点指定值;
  • 获得三角形内平滑变化的值;

我们要插值什么?

  • 纹理坐标、颜色、法线向量;

我们如何插值?

  • 重心坐标;

重心坐标

介绍

重心坐标是指利用$(\alpha, \beta, \gamma)$描述三角形内点$(x,y )$的坐标系:

图示:

证明:

假设点为$P=(x,y)$,根据平面向量分解定理:

那么:

即:

注意到$P$在三角形内部等价于:

这等价于$\alpha, \beta,\gamma$非负。

系数计算

那么系数该如何计算呢?可以利用对应区域的三角形面积来表示:

具体计算系数为:

计算方式,解方程即可:

使用重心坐标

利用重心坐标可以插值:

其中:

  • $V_A,V_B,V_C$可以是位置、纹理坐标、颜色、法线、深度、材质属性……

图示:

简单纹理映射:漫反射颜色

  • 对于每个光栅化屏幕样本 (x,y)(通常是像素中心):
    • (u,v) = 评估(x,y)处的纹理坐标(使用重心坐标);
    • texcolor = texture.sample(u,v);
    • 将样本的颜色设置为texcolor(通常是漫反射系数$K_d$(回想一下Blinn-Phong反射模型));

如果只按上述操作,实际中会出现一些问题,这也是后续介绍的内容。

一些纹理问题

纹理放大(如果纹理太小怎么办?)

假设有一面4k分辨率的墙,纹理的分辨率为256,此时墙上的点会对应于纹理上的一个非整数坐标(即无法查到对应的值),这时就需要一些技术来进行补救,分别有如下方法:

  • Nearest
    • 将小数四舍五入到最近的整数;
  • Bilinear
    • 双线性插值;
  • Bicubic
    • 三线性插值;

其效果如下:

双线性插值

线性插值是指在线段内根据端点的值计算线段内的其他值,即计算公式可以表达为:

双线性插值是指执行两次线性插值,以小数坐标为例,可以根据其周围的整数坐标进行双线性插值:

如上图所示,第一次插值计算$u_0, u_1$:

第二次插值根据$u_0, u_1$进行插值:

纹理放大(如果纹理太大怎么办?)

如果纹理太大也会产生问题:

之所以产生这样的原因,是因为在近处,一个点覆盖的纹理范围较小,而在远处,一个点覆盖的纹理范围较大,即平面上点覆盖的纹理区域大不相同。如果一个像素覆盖的范围不大,则可以用像素中心查询纹理值,但如果一个像素覆盖的范围太大, 那么中心无法代表整体的纹理值:

可以利用超采样的方式解决这个问题,但是开销会很大:

分析

该现象产生的原因是:

  • 一个像素内的纹理变化很大;
  • 即以像素为单位的信号频率太大;
  • 所以需要更高的采样频率;
  • 利用超采样可以解决但计算开销很大;

让我们用另一种方式来理解这个问题:

  • 采样会引起走样,那如果我们不采样会怎样?
  • 采样的目标是得到的一个区域内的均值;
  • 所以实际上我们只需要得到一个范围内的均值即可;

这是一个经典的问题,后续会介绍如何解决。

Mipmap ——允许(快速、近似、方形)范围查询

Mipmap是一个层次化的纹理图,第$i$层的纹理分辨率是第$i-1$层的一半:

Mipmap的总存储量为:

计算Mipmap的层数$D$

先考虑如何计算每个像素点覆盖的纹理区域大小,一个方式为对于每个像素,找到该像素中心,以及其邻居像素中心,共四个点(例如下图中红/蓝色的四个点),然后投影到纹理空间,计算投影四个点围城的面积大小:

注意到相邻像素中心的距离大约为一个像素边长,所以一个像素边长对应的纹理边长为纹理空间中像素中心投影点的距离,即下图中的$L$,$L$定义为两个边长中较长的边长,即:

图示:

我们用$L$近似下述粉红区域的边长,所以$L^2$即为面积:

根据$L$的值可以得到Mipmap的层数,例如第0层对应的是$1\times 1$的像素,第1层对应的是$2\times 2$的像素,所以第$L\times L$对应的层数为$D=\log_2 L$,可以在第$D$层直接查询结果($D$一般近似到最近的整数)。

Mipmap Level可视化结果

根据Mipmap可以得到如下可视化结果:

可以看到颜色渐变不连续,其原因是小数会近似到整数,一个方案是利用三线性插值:

  • 在层内利用双线性插值;
  • 在层之间利用线性插值;

图示如下:

三线性插值的可视化结果:

局限性

假设超采样的结果为:

Mipmap的结果为:

即远处的结果会糊掉。

一个方案是各向异性过滤(Anisotropic Filtering):

异性过滤(Anisotropic Filtering)

考虑Ripmaps和总面积表(沿着水平和竖直方向压缩):

Mipmap实际上只计算了对角线的值,即矩形区域;利用Ripmaps可以计算非矩形区域的结果:

总开销为:

EWA 过滤

各向异性过滤任然无法解决问题,因为斜的矩形很难被覆盖,更准确的方案是EWA:

  • 利用椭圆覆盖区域,可以处理不规则的区域;
  • 使用多次查询;
    • 会增加开销;
  • 利用加权平均得到结果;

图示: