Loading... # Lec05~06: Rasterization 光栅化 在前面几节中,我们将一个物体压缩到了一个“标准立方体”中。接下来,我们需要将图像画在**屏幕**上 图形学中的**屏幕**:一个二维数组,分辨率就是其大小,数组中的元素都是**像素**组成,一个典型**光栅** (raster,德语中的"屏幕") 成像设备。 **光栅化**(rasterization):把图像画在屏幕上 **屏幕空间**:在屏幕上建立坐标系。左下角是原点(0,0),向右是x轴正方向,向上是y轴正方向 ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211006215807.png?x-oss-process=image/resize,p_50) - 屏幕跨度为:$(0,0)$ 到 $(width, height) $ - 像素的索引形式:$(x, y)$,$x,y$ 都是整数 - 像素的索引跨度:$(0,0)$ 到 $(width-1, height-1) $ - 像素中心:$(x+0.5,\ y+0.5)$ ## 1. 视口变换 Viewport Transfomation 现在需要将物体变换到一个xy平面上,**显然与z值暂时无关**,即$[-1,1]^{2}$ 到 $[0, weight] × [0,height]$ 可得,**视口变换矩阵**为: ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211006221101.png?x-oss-process=image/resize,p_50) ## 2. 光栅化一个三角形 ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211006223323.png?x-oss-process=image/resize,p_50) 将一个连续的三角形图像(函数)绘制到一个离散的屏幕上,各个点的像素该怎么画? 一个简单的方法:**采样**(Sampling) 比如,对于每一个像素点中心,如果它在三角形图像内,那么那块像素就为1,否则为0 判断是否在三角形内可以用叉积判断。 当然,没有必要判断每一个像素是否在三角形中,比如下图中的白色区域,是必然不可能在三角形中的。而蓝色的区域被称为“包围盒”,可以提前根据三角形函数计算得出。 ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211006224527.png?x-oss-process=image/resize,p_40) 同时,我们没必要每一行的每一个像素都进行判断。如下图所示,每一行的**可能的像素点**的起始和末尾都是可以计算得出的。 ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211006224748.png?x-oss-process=image/resize,p_40) 最后,我们得到这样的一个图像: ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211010221811.png?x-oss-process=image/resize,p_50) 很显然,这个图像非常的奇怪,边缘部分仿佛有很多“狗牙”,这种东西被叫做 **“锯齿”** (jaggies)。这是离散化必然会导致的问题。 ## 3. 反走样 ![锯齿](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211007204953.png?x-oss-process=image/resize,p_30) ![摩尔纹](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211007205058.png?x-oss-process=image/resize,p_30) ![车轮效应(顺时针高速旋转被看成逆时针)](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211007205707.png?x-oss-process=image/resize,p_40) - 锯齿:空间上的采样 - 摩尔纹:未充分采样的图像 - 车轮效应:时间上的采样 - ... 这些种种现象都称为:**Sampling Artifact**、**走样(alias)**。其本质就是:信号“变化”过快,采样频率不满足奈奎采样定理,导致的信息失真。为了消除这一现象而产生的技术统称为**反走样(antialias)** ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211008002635.png?x-oss-process=image/resize,p_50) > 如上图所示,蓝色的高频信号并没有被充分的采样(圆点即为采样点),所有的采样点错误地形成了一个黑色的低频信号 随着信号频率越来越快,采样得到的效果就越来越差,难以与原本的信号匹配 ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211008212640.png?x-oss-process=image/resize,p_50) > 时域上的走样失真,在频域上的体现为频谱的混叠。而图形学上的渲染,实际上是对连续函数(图像几何关系、着色参数、着色方程等)在空间的离散的采样。然而这个函数的频率范围理论上是**连续的**,不论用多大的采样频率,**离散的**采样都无法完美恢复原始信号,因此走样无法避免,在图形渲染中能做的只是减轻走样 > > —— 摘自 https://blog.csdn.net/weixin_43803133/article/details/108040669 所以,消除走样的方法有2种: - **增加采样频率**,比如增加屏幕设备的像素点数,单位面积内的像素点数越多,走样就越不明显 - **反走样**,先对图像进行模糊化把结果的的高频信息拿掉(比如根据傅里叶变换),再进行采样,实质上是**降低的信号的速度** ### 3.1 预先滤波 Pre-filtering 先将图像**滤波模糊化**,再进行采样。 ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211008183305.png?x-oss-process=image/resize,p_50) ![左图为滤波前采样,右图为滤波后采样](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211008183354.png?x-oss-process=image/resize,p_70) 可以通过**卷积**进行滤波 ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211009170328.png?x-oss-process=image/resize,p_60) 或者说,可以以像素为单位,根据像素被图像覆盖面积来决定该像素的颜色: ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211009173828.png) 这样也算是一种卷积。 ### 3.2 基于超采样的反走样 但是在实际中,要计算具体的覆盖面积是一件比较困难的事,我们只能用一种近似的方法去计算。 > 本部分内容摘自:[清清!的CSDN博客](https://blog.csdn.net/weixin_43803133/article/details/108040669) #### 3.2.1 SSAA(Supersampling Anti-Aliasing) **超采样反走样技术**(SSAA)是一种比较简单的反走样方法,同时也很有效,缺点就是性能很差。 其原理便是:在一个像素内取多个子采样点,对子采样点进行颜色计算,而后合成出该像素的颜色。**本质上是先用更大的分辨率采样,再采样到原本的分辨率** ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211009174324.png?x-oss-process=image/resize,p_30) > 拿4xSSAA举例子,假设最终屏幕输出的分辨率是800x600,4xSSAA就会先渲染到一个分辨率1600x1200的buffer上,然后再直接把这个放大4倍的buffer下采样至800x600。这种做法在数学上是最完美的抗锯齿。但是劣势也很明显,光栅化和着色的计算负荷都比原来多了4倍,render target的大小也涨了4倍。 增加采样数的操作可以有效解决走样问题,但是过大的计算量与内存占用使得其难以投入实际使用。 #### 3.2.2 MSAA(Multisample Anti-Aliasing) **多重采样反走样技术(MSAA)** 同样把一个像素分为若干个子采样点。但是与SSAA相比,它的子采样点的颜色和像素颜色值相同,不进行单独计算。 如下图我们把一个像素进一步细分为4个采样点根据他覆盖的细分像素的不同来定义他所占的像素的颜色。 ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211009195244.png?x-oss-process=image/resize,p_70) ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211009200101.png?x-oss-process=image/resize,p_50) 此外,还有其他很多抗锯齿方案。比如快速近似抗锯齿(FXAA),是一种后处理技术,先得到一个带锯齿的图像,然后通过边缘检测对边缘的锯齿进行优化。此外还有TAA(Temporal AA),相当于里复用上一帧的计算结果以此来降低性能消耗。 ## 4. 可视性/遮挡 在之前的绘制过程中我们没有考虑Z的信息,那么如何画出*前后关系* 以及*深度* 需要用到**Z缓冲** 深度值存储在每个片段里面(作为片段的z值),当片段想要输出它的颜色时,我们会将它的深度值和z缓冲进行比较,如果当前的片段在其它片段之后,它将会被丢弃,否则将会覆盖。 这个过程称为**深度测试**(Depth Testing) ### 4.1 画家算法 按照离相机的距离从远到近画,近处的完全 *遮盖* 远处的,这样一层一层叠加的算法就叫做**画家算法**(painter's algorithm)。这样子的时间复杂度为$O(n logn)$,需要进行一个排序。 但是我们发现画家算法不能解决一些比较复杂的情况,如下图三个物体互相遮挡,我们就不能判断他们的远近顺序。 ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211009222624.png?x-oss-process=image/resize,p_50) ### 4.2 Z-Buffer 所以我们在图形学中引入了一个新的概念**深度缓存(Z-Buffer)**,我们通过分析单个像素的深度关系来表示,在**一个像素上永远只保存较近深度的信息**,一般我们会在渲染最后结果的时候会得到两张图,一个是我们想要的图,另一张是记录了这张图中每个像素的最浅的深度信息的图,我们把它称为深度图。 ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211009225341.png) 在之前我们规定了我们的摄像机是从原点向-z方向看,所以深度信息是z的值越小反而离我们越近,这里为了方便理解我们把z的值取绝对值,**z的值永远是正的且越小离我们越近。** 获取Z-Buffer的算法伪代码如下: ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211009230246.png?x-oss-process=image/resize,p_80) ![](https://irimskyblog.oss-cn-beijing.aliyuncs.com/content/20211009230633.png?x-oss-process=image/resize,p_70) 这样子的算法是一个$O(n)$复杂度 最后修改:2021 年 11 月 10 日 02 : 23 AM © 允许规范转载