锯齿是怎么产生的
现象描述
图形渲染中的锯齿是指在渲染结果图像上颜色剧烈变化的区域出现锯齿状一样的斑纹的现象。在图像色彩边缘线上,由于边缘两边的颜色差异很大,这样的现象特别明显。也有人称它为被狗啃了一样。
锯齿产生的根本原因
推荐文章:
GAMES101 L-6:https://www.bilibili.com/video/BV1X7411F744?p=6
采样相关知识:https://zhuanlan.zhihu.com/p/392738085
图形学的根本过程是一个把图形转化成图像的过程,该过程是一个连续信号经过采样转化成离散信号的过程,之所以产生锯齿现象是因为信号的离散性被人眼识别出来。
抗锯齿就是通过一些手段去重构丢失的信号。我们通常用的抗锯齿算法实际上是降低锯齿,并非消除锯齿。
锯齿是因为不同频率信号之间转换之后造成的数据失真,因此锯齿现象也被称为走样(Aliasing)。
为了减少失真,一种理所应当的抗锯齿思路就是增加采样频率,而另一种思路是由于频率变化快的地方失真越严重,即边缘处(从视觉上也是如此),所以可以通过后处理手段将边缘识别出来再模糊叠加回原画面的手段。
常见的抗锯齿
超采样抗锯齿
SSAA超采样抗锯齿(Super Sample Anti-aliasing)
SSAA本质上是先渲染出一张面具为屏幕分辨率为N倍的图像,然后再通过降采样的方式输出最后的渲染图像,这样输出一个屏幕像素就对应原来N个采样点计算的屏幕大小的图像,这是理论上最完美的抗锯齿。基于GPU硬件实现
上图中最右边有明显的锯齿,但是通过降采样一直输出到左边的话,这种锯齿感从肉眼来看的话就会明显地减弱。
假设最终屏幕输出的分辨率是800x600,4xSSAA就会渲染到一个分辨率1600x1200的Buffer上,然后再把这个放大4倍的Buffer采样输出至800x600。这种做法在数学上是最完美的抗锯齿。但是缺点也很明显,计算量增大了4倍,render target的大小也涨了4倍。
MSAA一类的多重采样抗锯齿
MSAA多重采样(Multi sample Anti-aliasing)
MSAA是GPU在光栅化阶段对片段进行超采样,单个像素中的所有采样都决定像素中心点的着色结果,最后根据样本的覆盖率来计算像素最终颜色的方法。基于GPU硬件实现
它的原理是这样的,在逐像素阶段,如果我们只布置一个采样点,虽然如下图左边三角形虽然占据了像素一部分,但是却没有包含中心采样点,那么不输出颜色,,反之如果我们布置了多个采样点的话,那么根据覆盖的样本的百分比来输出最终的颜色,就如下图右边所示。
这种抗锯齿方式,布置的采样点越多越准确,但是随之计算的性能消耗也会增大。
下面是MSAA抗锯齿输出的颜色示例:
但是MSAA也有一些缺点:
- MSAA在与HDR一起使用时可能会产生问题,必须进行专门处理。
- 由于MSAA是在光栅化阶段对图元进行超采样,因此它只能解决几何走样现象(即物体轮廓地锯齿),不能解决着色走样(高光闪点)问题。
- 延迟渲染无法支持MSAA。
PiexlShader后产生的锯齿:
- 在通用渲染管线中,vs执行之后ps执行之前,这个区间进行的操作叫作光栅化,所以上述操作对于ps执行后产生的锯齿是没有任何效果的,例如:高频高光,部分显示物体如树叶,草这些,也需要抗锯齿。
- 这些物体的边缘是在执行ps计算时对贴图的alpha值进行采样后得到的,所以光栅化阶段得到的coverage mask 对这些物体无效。
- 对于这些物体,要想知道他们的边缘,只能在执行ps时做workaroud,即alpha to coverage,简单来说就是在执行ps时,对alpha值和AlphaTest的Clip Value 进行比较,根据插值修改该像素的coverage mask。
Alpha-To Coverage A2C
- 在渲染一些需要镂空的物体(树叶,草等)时,我们经常会用到alpha test来实现镂空效果
- 通过A2C可以实现alpha test边缘半透明过渡效果。当覆盖测试和深度测试通过后,如果开启了A2C则还会进行一次概率测试,图形硬件会根据SV_Target输出的 alpha 值,再做一次概率判断,如果这次概率判定成功,才会写入颜色。
- 例如,4个采样点,有2个通过了测试,SV_Target输出的alpha值为0.5,则很有可能只能1个采样点输入颜色,最终达到%50半透明效果。
- 简单来说,通过A2C可以修改图元颜色的权重,从而达到抗锯齿,半透明过渡效果。
CSAA覆盖采样抗锯齿(Coverage Sampling Anti-Aliasing)
在MSAA的基础上,将用来计算Coverage的采样点与用来存储色彩的采样点进行分离,这样可以用较少的显存来存储较多的专门用来计算Coverage的采样点,让覆盖率计算的更加精确,从而提升视觉效果。从结果上看,CSAA在性能上比4x的MSAA稍微低一些,但也可以达到8x或16xMSAA的效果。
EQAA(Enhanced Quality Anti-Aliasing)
EQAA(Enhanced Quality Anti-Aliasing),是 AMD 在其 GPU 产品中对 MSAA 的优化实现。在 EQAA 中,也采用了与 CSAA 相同的做法,将计算 Coverage 的采样点和计算 Color 的采样点分开存储,例如,4f8x EQAA 表示有4个颜色采样点并且总共8个采样点。
EQAA与CSAA一样,也采用了Coverage与Color两种类型的采样点。另外EQAA还使用了一个表格来存储采样点的颜色、深度、模板数据,而在采样点上通过索引的方式引用表格中的数据。因为在单个像素中,采样点公用数据的几率非常大,因此这种方法可以节省大量的显存资源。
时域上的抗锯齿
Temporal相关可以看
GAMES202 https://www.bilibili.com/video/BV1YK4y1T7yY?p=12
TAA时间抗锯齿(Temporal Anti-Aliasing)
TAA的核心思想是将点SSAA采样空间不同样本方法改成使用多个历史帧的渲染结果作为样本来达到类似SSAA的效果。它的实现需要N倍的显存空间,但是不需要额外的着色计算。
实现思路如下:
- 把多次采样的过程分布到每一帧中去,每一帧都平均前面几帧保存下来的数据。从下图可以看到将4次采样分布在4帧的运算中。
- 每一帧会有一定的偏移,继承了MSAA采样。从下图可以看到每一帧的采样点的位置并不一样。
- 用motion vector保存每帧移动的偏移。
在实际工程中,需要注意TAA带来的一些细节问题;
- 因为灯光改变、遮挡改变、相机或场景运动所带来的历史帧中的样本失效问题。
- 因为样本来自于多个历史帧而产生的画面收敛延迟(残影)的问题等等。
- HDR协同工作的问题。
TXAA
TXAA 是 NVIDIA 在 GTX 600 及以上版本的显卡上基于传统 MSAA(CSAA?) 的基础上,引入了时间过滤器(TAA的思想)的硬件抗锯齿技术。TXAA 旨在减少时间性锯齿 (运动中的蠕动和闪烁)。 该技术集时间性过滤器、硬件抗锯齿以及定制的 CG 电影式抗锯齿解算法于一身。 要过滤屏幕上任意特定的像素,TXAA 需要使用像素内部和外部的采样以及之前帧中的采样,以便提供最高画质的过滤。 TXAA 在标准 2xMSAA 和 4xMSAA 的基础上改进了时间性过滤。 例如,在栅栏或植物上以及在运动画面中,TXAA 已经开始接近、有时甚至超过了其它高端专业抗锯齿算法的画质。TXAA 由于采用更高画质的过滤,因而与传统 MSAA 较低画质的过滤相比,图像更加柔和。
MFAA多帧采样抗锯齿(Multi-Frame Sampled Anti-Aliasing)
Maxwell 架构提供了一种名为动态超分辨率(Dynamic Super Resolution,DSR)的技术,能在硬件上实现超采样。另外 Maxwell 将AA的样本数据存放在了 RAM 中(以前的架构都是将 AA 样本数据存储在 ROM中),从而提高了样本存储的灵活性和可编程性。借助这样的新的架构,实现了 MFAA。由于 RAM 中的数据是可以自由读写的,通过在时间和空间上交替 AA 样本的模式,MFAA 的样本在历史每帧(甚至同一帧的不同时刻)都可以不同。
4x MFAA 的画质于 4x MSAA 相当,但只需要 2x MSSAA 相当的性能开销。
后处理抗锯齿
FXAA快速近似抗锯齿(Fast Approximate Anti-Aliasing)
- 利用边缘检测有效的模糊混合。
- 在后处理完成不依赖硬件支持。
测试场景中对应的后处理图像:
FXAA本质就是在后处理中对图像进行描边,然后对描边图像进行模糊,之后再与原图像进行混合。
相比于MSAA,FXAA的目标是速度更快、显存占用更低,还有着不会造成镜面模糊和亚像素模糊(表面渲染不足一个像素时的闪烁现象)的优势,而代价就是精度和质量上的损失。
MLAA形态学抗锯齿(morphological Anti-Aliasing)
它的基本思路是检测每帧图像的边缘(通常可对亮度、颜色、深度或者法线进行边缘检测),然后对这些边缘进行模式识别,归类出Z、U、L三种形状,根据形状对边缘进行重新矢量化(re-vectorization),并对边缘上的像素根据覆盖面积计算混合权重,将其与周围的颜色进行混合,从而达到平滑锯齿的目的。
以下图为例详细说明。用绿色标记的线条为检测到的Z形边缘,从这些边缘我们可以推断出原始边缘的形状,即图中蓝色线条。这个过程叫重新矢量化。此时我们能够得知边缘附近每个像素被蓝色线条截断了百分之多少。根据此信息将当前像素与邻近像素的颜色混合,便能得到平滑的边缘。
像素被蓝线截断面积的百分比(小于50%的部分)叫做权重因子。对于任一个边缘像素,要计算其权重因子,只需要知道d_left、d_right,以及两端交叉边的朝向(即边缘的形状,此处为Z形)即可。其中d_left和d_right为当前像素距离边缘两端的距离。得到权重因子a后,通过如下计算实现边缘平滑:
为了节省计算资源,Jimenez为每种形状模式预计算了一张查找表(称作areaTex)以便快速获取权重因子,如下图所示:
注意贴图中的每个像素保存了两个数值(分别储存在R和G通道里),这两个数值分别代表当前像素及共享同一边缘的邻接像素的权重因子。
以上是仅针对水平方向锯齿的情况,对于垂直方向的锯齿,处理方式类似。
MLAA 天然的能与延迟着色完美配合,但它只能用来消除几何锯齿,不能消除着色锯齿。
SMAA增强型子像素形态学抗锯齿(Subpixel Monorplogical Anti-Aiasing)
SMAA是思路是建立在Jimenez版MLAA的基础之上,但是每个步骤都经过了强化或者彻底的更新。
Jimenez版MLAA的处理流程如下图所示:
分为三个步骤:
- 边缘检测
- 计算权重因子
- 混合周围像素
SMAA在(b)、(c)的基础上加入了针对尖锐几何特征的处理,并加入了对角线模式识别;在(d)中加入了对局部对比度的考虑;在(e)改善了距离搜索算法。
深度学习AA算法
DLSS深度学习超采样(Deep Learning Super Samping)
DLSS(Deep Learning Super Sampling),深度学习超采样,是 NVIDIA 于 2018 年在 GeForce 20 系列的显卡上推出的一种基于深度学习算法进行图像缩放的技术。2020 年 NVIDIA 推出了 DLSS 2.0。
这项技术在Turing架构中首次引入,它的工作原理是利用NVIDIA神经图形框架NGX,在超级计算机中以极低的帧率和每像素64个样本对数万张高分辨率的精美图像进行离线渲染,训练出一个深度神经网络。基于无数个小时的训练所获得的数据,网络就可以将分辨率较低的图像作为输入,构建高分辨率的精美图像。
训练好网络后,NGX会通过Game Ready驱动程序和OTA更新将AI模型传递到GeForce RTX PC或笔记本电脑。并借助RTX GPU 中专用于AI计算的Tensor Core,DLSS网络可以与密集的3D游戏同时实时运行。
参考文章
- Anti-Aliasing 技术盘点:https://zhuanlan.zhihu.com/p/90982812
- 主流抗锯齿方案详解(一)MSAA:https://zhuanlan.zhihu.com/p/415087003
- 主流抗锯齿方案详解(三)FXAA:https://zhuanlan.zhihu.com/p/431384101
- 图形学基础 - 着色 - 空间抗锯齿技术:https://zhuanlan.zhihu.com/p/363624370
- learnOpenGl:https://learnopengl-cn.github.io/04 Advanced OpenGL/11 Anti Aliasing/
- OpenGraphic:https://github.com/Gforcex/OpenGraphic
- https://github.com/wlgys8/SRPLearn/wiki/AntiAliasSummary
- 大佬笔记:
作业
对比各个抗锯齿方案的优劣(效果,效率)
效果上SSAA毫无疑问最好,但是性能开销太大了
MSAA采样点上去了,效果也不错,但如果高分辨率情况下感觉优势不是很大,而且延迟渲染还不支持
后处理方案中SMAA效果挺不错的,性能消耗中规中矩,而FXAA虽然快但是有点糊了。
TAA效果不错,但如果画面频繁变换,可能会穿帮。
放一张引用文章中的测试结果: