前提
经过了 MVP 变化,和 是否在三角形内部测试 之后,随之出现的一个问题就是锯齿,也叫作走样,下面讨论如何反走样。
采样会导致的问题
采样的运用其实很广泛,比如视频其实是对时间的采样,因为人眼的视觉暂留才导致在大于 24 帧时会感觉那是连续的。
采样会带来的第一个问题就是 锯齿,第二个是 摩尔纹。
第三个 反转轮胎,这个么滴图片,但大家应该在生活中观察过轮胎在高速运动的时候,人眼观察会觉得它在反转,就是因为人眼的采样率跟不上轮胎的转速。(冷知识:人的余光采样率比焦点高,洗牌的时候可以拿余光试试能不能看清牌面)
总结一下,走样就是因为 信号 变幻太快,采样频率 太小,跟不上。其实很好理解,对于一个正弦波,你在图示地方采样,会以为正弦波是一条直线,因为你得到的值都是 0。(像盲人摸象?采样的范围太小了)
下图也是,对于本身频率就高的函数(f5(x)),使用一样的采样频率,是不能还原原来的函数状态的。
当使用同样的采样频率(竖着的线),对两种完全不同的曲线(蓝色的曲线和黑色曲线)进行采样,结果却是一模一样的时候(黑色圈圈),也就是通过采样结果,我们不能区分这两种曲线的时候,也就是 走样 了:
解决方法是先将图片进行模糊,再采样。下面的 滤波 和 卷积 都是为了解释为什么这样可行的铺垫,最好看懂,看不懂就直接看 如何反走样。
滤波
首先,数学上有很多方法可以对一个函数进行展开,其中有一个 傅里叶级数展开,它可以把任意一个周期函数展开成一系列正弦函数和余弦函数加一个常数项的形式。如下图,我们想用傅里叶级数模拟这个锯齿图,当项数越来越多的时候,模拟的就越精确。
傅里叶变换 可以把一个方程 f(x) 经过一系列复杂的操作之后变成 F(x),并且通过 逆傅里叶变换 把 F(x) 变回 f(x)。也就是说他可以把一张图从时域变成频域,再从频域变回时域。
图片的频率你可以理解为某一个点附近的变化骤缓程度,比如在衣服和脸的交界处,频率就是很高的,在衣服的内部,基本都是黑色,频率就是很低的。频域图中,中间是频率最低的地方,越往外越高。亮度表示在该频率上所携带的信息多少,越多就越亮,这里的信息你可以理解为像素吧,比如变换小的像素最多,所以中间最亮,变换大的像素少(一般只有边界,比如衣服和皮肤的交界处),所以往外亮的地方很少。一般来说,自然界的图片拍出来,频域图都是这样的。
频域图的四条很明显的亮线,是因为我们假设了这个图片是 Repeat 模式的,也就是像贴瓷砖一样重复。因为上边界和下边界,左边界和有边界会有明显的跳变,所以会有四条很亮的线。
滤波 就是把某一频段的信息给去掉,低通滤波就是让低频率通过,高通滤波就是让高频率通过。
卷积
如下图,有一个 3*3 的盒子,卷积的意思就是对原图的每一个像素,都取他自身及周围 8 个像素的颜色相加,再除 9。(当然这个盒子可以有不同的形态)。直接给出一个结论:
时域的卷积等于频域的乘积,时域的乘积等于频域的卷积
将一个函数(a)进行傅里叶变换到(b)(c)傅里叶变换到(d),也就是从时域变成了频域。采样就是(a)*(c)=(e),将一个连续函数变成离散函数。而对应的,就是在频域(b)卷积(d)=(f)的过程。
走样就是在频谱上出现了交叠,也就是出现了 混叠。
如何反走样
走样的核心矛盾就是采样率跟不上频率。那么一种想法就是增加采样率,也就是换分辨率更高的屏幕,但这不属于图形学研究的范围。另一种方法就是保持采样率,降低频率。也就是去掉高频信息,也就是使用低通滤波器,也就是将原图片进行模糊。
具体如何模糊呢?
其实我一开始以为是把下面这个图,每一个像素和周围进行平均 > <。但仔细想一下就会知道这个误差其实很大。
原来是把一半橙色,一半白色的像素变成橙色或者白色二选一,模糊操作其实是让它变成一个白和橙的中间色,而这个中间的程度根据当前像素中橙白的比例来确定的。
但在实际操作中精确的计算比例是不太可行的,所以目前流行的是一些近似的算法:
MSAA 多重采样抗锯齿:在一个像素中使用更多的采样点来近似的确定橙白比例,
可以明显看到,如果使用 2*2 的采样点,那么计算量会扩大 4 倍,但是 MSAA 在工业上的运用其实并不会这样,他们会让一些采样点进行复用,并且也只会针对边缘的像素。
FXAA 快速近似抗锯齿:先生成有锯齿的图像,然后算出边界,再把有锯齿的边界换掉。实际上是一种图像后处理。速度很快。
TAA 时间性抗锯齿:简单高效,但只针对静止的画面,简单来说就是把 MSAA 的几个采样点分布到了时间上,比如 2*2 的采样点分别编号为 0,1,2,3。TAA 在第一帧只计算 0 号位置,第二帧只计算 1 号位置.... 复用 4 帧的结果就是 MASS,但是对当前帧来说没有额外的消耗。