[图形]光栅化

2022.2.8修订

经过viewing transformation的图元全都处于NDC归一化设备坐标中

接下来要将正方体里的图元画在屏幕上

Screen 屏幕

什么是屏幕?

  • 是由像素组成的二维数组
  • 数组大小是屏幕的分辨率
  • 屏幕是光栅成像设备

像素(Pixel)是什么?

  • (picture element缩写)
  • 简单认为像素是一个一个的小方块,内部填充一种颜色
  • 像素颜色可以用RGB表示

什么是屏幕空间?

  • 左下角作为原点
  • 向右是+X
  • 向上是+Y
  • 像素坐标是整数
  • 像素中心在(x+0.5,y+0.5)(x+0.5,y+0.5)

Viewport Transform 视口变换

视口变换做的事情很简单

  • 把NDC左下角移动到屏幕空间原点
  • 把NDC拉伸覆盖整个屏幕空间

Rasterization 光栅化

经过视口变换,屏幕空间中储存的还是连续的多边形,要将其显示在一格一格的像素上,就要将其离散化

选择三角形作为基本图元

  • 最基础的多边形

  • 任何其他多边形都可以被拆解为很多三角形

  • 三角形一定表示一个平面,而例如四边形可能会弯折

  • 三角形内部外部定义清晰

  • 三角形三个顶点属性确定后,三角形面上属性可以插值

Sampling 采样

采样就是将函数离散化的过程

最简单的光栅化方法就是:给定一个屏幕空间内的三角形,判断某个像素是否处于三角形内

写成伪代码就是:

1
2
3
4
5
for (int x = 0; x < xmax; ++x) {
for (int y = 0; y < xmax; ++y) {
image[x][y] = inside(tri, x + 0.5, y + 0.5);
}
}

如果不在三角形内,inside函数会返回0,否则返回1

那么如何判断像素中心是否处于三角形内呢?

用三角形三条边分别和像素中心叉乘,如果三个结果的方向大小都是正的或负的,则说明这个像素确实在三角形内。

不过呢,万一这个像素中心点正好在三角形的边界上,怎么办?对于这类问题,在图形学中,要么不做处理,要么特殊处理。(这课里就不对它处理了233

再看看刚刚的采样伪代码,我们对一个三角形光栅化的时候,把屏幕上所有像素点都测了一遍,事实上这没必要。

三角形只可能存在于蓝色的像素内。所以我们可以先求出三角形的轴向包围盒(Axis Align Bounding Box),再对这个包围盒的范围进行光栅化

Antialiasing 反走样/抗锯齿

一个三角形是一个连续的函数,给定屏幕中任意一个点,我们可以测试这个点是不是在三角形内部。关于三角形,我们可以认为它的颜色是均匀的,所以每个在三角形内的像素,我们都可以把它们涂成三角形的颜色。但是如果只是这样做,结果会得到一个类似三角形的图案。

抗锯齿就是为了解决这个原版和光栅化后的图形不一致的问题。

(之后的关于抗锯齿都没看懂,反正就是把原图模糊一下(低通滤波,去掉高频信息,实际操作就是取该点周围点的颜色平均一下)再采样,锯齿就不明显了,大概原理是啥,用到的知识,频域啊时域啊,都是信号处理的,搞不懂,留个坑)

Z-Buffer 深度缓冲

实际场景中,空间里会有很多很多三角形,它们可能会互相遮挡。如何解决互相遮挡的问题需要深度测试。

最古老的解决这个问题的算法是画家算法(Painter Algorithm),先画远处的物体再画近处的,重叠部分直接覆盖,算法复杂度O(nlogn),因为要对所有三角形排序。基本可以保证遮挡顺序是对的。但是在某些特殊情况下

不管哪个三角形先画都有问题

因为空间中的三角形不好排先后顺序,所以深度缓冲记录的是,每个像素所在的几何图形最浅的深度

最终生成的有两张图像,一个是最终结果(frame buffer),另一个是任何一个像素对应的深度(depth buffer)

为了简化计算,我们认为相机到顶点的距离就是深度,距离永远是正数,而且越小表示离相机越近,否则越远

之前说过我们的相机放在原点,并且向负z方向看过去,这样的话所有z都是负数,所以z绝对值越小离相机越近,绝对值越大离相机越远


深度图里,越黑的地方离相机越近



这张图可以很清晰看出深度测试如何工作,更近的像素会覆盖掉更远的像素

算法大致过程:

  • 将深度缓冲初始值设为无限大
  • 遍历所有三角形,在对三角形光栅化后,遍历所有光栅化后的像素
  • 如果像素的深度小于buffer中对应位置像素的深度,就替换掉

算法复杂度:O(n),n是三角形数量(只针对深度缓冲算法,不考虑光栅化)。能做到线性时间复杂度是因为实际上并没有对三角形进行排序,它和三角形在空间中的顺序(从摄像机到三角形)没有关系。两个三角形的某些像素深度相同的情况另说

(Zbuffer处理不了透明物体,需要特殊处理0.0


[图形]光栅化
https://ksgfk.github.io/2020/11/01/图形-光栅化/
作者
ksgfk
发布于
2020年11月1日
许可协议