图形学自问自答3——反走样和纹理过滤
1.多重采样MSAA和超SSAA采样有什么区别?
MSAA 和 SSAA 都是反走样(抗锯齿)的手段,具体实现原理有差别。
1.1 SSAA(Super-Sample Anti-Aliasing)原理:
以一个更大的分辨率来渲染场景,然后再把相邻像素值做一个过滤(比如平均等)得到最终的图像(Resolve)。以2倍SSAA 为例,在以 1024x1024 的像素渲染画面时,会以 2048x2048 的分辨率生成缓冲区,缓冲区中的每一个片元都会执行一遍片元着色器,最后再把原本属于一个片元的4个子片元的颜色进行计算得到实际片元的颜色。
- 实际片元如何生成4个子片元?
最常用的一种方法是平均取4个点,也有很多其它的算法,包括随机生成等。如图:
子片元生成方法
- 4个子片元的颜色如何得到实际片元的颜色
最常用的是取平均值
1.2 MSAA(Multiple-Sample Anti-Aliasing)原理:
和SSAA类似,2倍MSAA为例,每个实际片元也生成4个子采样点,也需要使用一个更大分辨率的缓冲区来存放子采样点的颜色。与 SSAA 的差别在于,并不是每个子采样点都会执行片元着色器。而只有实际片元会执行片元着色器,若子采样点被覆盖,则该子采样点的颜色被设置为实际片元执行片元着色器得到的颜色,同时需要记录每个子采样点是否被覆盖,以及覆盖该子采样点的深度值。最终由硬件将子采样的的颜色值计算得到片元的实际颜色。
多重采样简单过程
- 子片元生成和实际片元颜色计算
基本和 SSAA 一样,有多种生成子片元的方法,颜色计算的方法通常是取平均值。
2. 纹理的 FilterType 选项是什么意思?
常用的引擎(Unity、Cocos Creator)等,纹理设置都有 FilterType 这个设置,通常的选项是以下几种:
- Point
- Bilinear
- Triliner
我们知道,屏幕是由若干个像素组成,像素是一个有大小的“格子”。而纹理也是由若干个纹素组成,纹素同样是“格子”。当渲染一张纹理到屏幕时,最理想的情况是,渲染区域分辨率和纹理本身的分辨率一样,也就是说纹素正好和像素一一对应。这种理想情况下,纹理采样时,像素中心的 uv 坐标应该正好落在某一个纹素的中心,可以直接取这个纹素的颜色作为像素的颜色。
然而大部分情况下,纹理和渲染区域不具有相同分辨率,此时像素中心点的uv坐标不会落在纹素的中心,此时该如何确定像素的颜色会得到更好的显示效果呢?
- 纹理尺寸过小
纹理尺寸过小时,多个像素的纹理坐标会映射到同一个纹素,出现锯齿或模糊 - 纹理尺寸过大
一个像素覆盖了多个纹素,此时怎么根据多个纹素来确定像素的颜色呢?通常取距离uv坐标最近的纹素作为采样结果,这会出现摩尔纹现象。
FilterType 的设置就是用来确定当渲染区域和纹理的分辨率不一样时,如何确定像素的颜色,选择合适到 FilterType 能够得到更好到显示效果。
2.1 Point 最近点采样
- 采样策略:
使用距离纹理坐标最近的纹素作为该像素的采样结果。 - 优点:
每个像素只需一次采样,速度快。 - 缺点:
显示区域与纹理尺寸不同时,采样结果就会变形或模糊。
2.2 Bilinear 双线性过滤
- 采样策略:
以纹理坐标为中心,取该纹理坐标周围4个纹素,再取平均作为该像素采样结果。 -
优点:
像素之间的过渡更加平滑,一定程度上改善模糊效果。
*缺点:
只作用于一个MipMap Level,选取但是纹素和像素大小最接近但那一层 MipMap 进行采样,当像素实际大小接近两层MipMap中间时,有些情况效果不太好。
双线性采样示意
2.3 Trilinear 三线性过滤
- 采样策略:
选取与像素实际大小接近的两层 MipMap,分别进行一次双线性采样,针对两个采样结果进行线性差值,得到最终结果。 - 优点:大部分情况下效果理想,特别是纹理尺寸比显示区域大的情况下,可以有效避免摩尔纹的产生。
- 缺点:需要开启 MipMap,在未开启 MipMap 的情况下,将退化为双线性采样;
采样次数较多,性能消耗大。