三、SSAA(super-sampling anti-aliasing)
SSAA最初的思路是先上采样渲染图像,然后再下采样输出图像,比如我们要渲染输出一个256*256的图像,可以设置color buffer为512*512(4倍的SSAA),这个时候我们的ps需要执行512*512个thread,同时深度模版测试也要进行512*512次,最后把4倍的color buffer resolve成256*256,就是4个像素取平局值,得到最终的图像。这种方法运算量和存储空间都会增大4倍,cost很高,但效果也最好。
下图是一个3*3图像4xSSAA的例子,绿色的RGB为(34,177,76),深红色的RGB为(136,0,21),边缘处的颜色为((34,177,76)*3 + (136,0,21))/4 = (59, 133, 62)
对于现在的计算机硬件来说,我们可以针对每个像素,进行子像素级的采样,其中采样点的位置选择有多种方式,常用的有grid,随机等等,如下图所示:
其中,旋转方式是最常用的采样方式。
在D3D11中,我们能够在sample级别来执行ps,如果采用grid方式的采样点分布,就间接实现了SSAA,就是每个采样执行一次ps(采样的中心就是ps的位置),对于每个采样来说,我们可以输出颜色。下面是一段在sample上执行ps的代码,其中一个像素中不同的sample用SV_SampleIndex区分:
float 4PSMainPerSample(infloat4screenPos:SV_Position,
in uint subSamplelndex:SV_SampleIndex):SV_Target0
{
float 3normal;
fioat 3position;
floatspecularPower;
GetGBufferAttributes(screenPos.xy,ViewRay,subSamplelndex, normal,position,specularPower);
Return CalcLighting(normal,position,specularPower);
}
四、MSAA(multi-sampling anti-aliasing)
MSAA基本上是现在gpu硬件上反锯齿的标配,大多数gpu都实现了该功能。
MSAA的基本思想就是每个像素有多个采样,但ps只对该像素执行一次(ps在像素中心位置被调用),即ps输出的color被所有sample使用,然后每个sample进行深度模版测试,通过该测试后,会接受ps输出的颜色,如果没有通过深度模版测试,则会拒绝ps输出的颜色(此时会使用color buffer中的原来的颜色,一般就是我们clear背景的颜色),生成该sample的输出图像,最后resolve所有采样的图像,生成最终的输出图像。就是就是说对于32*32的输出图像,如果是4xMSAA,则要输出4个32*32的图像。[注:ps 会对每个光栅化后的primitive的像素来进行]
上图就是4xMSAA的例子,我们看如何得到最终的结果:
1. 执行到黄色三角形,该三角形覆盖到了该像素中心,执行ps,输出黄色,三个sample深度测试fail,保持原来的像素颜色(背景色为白色),第二个采样深度测试pass,对于4个采样,采样像素颜色为
2. 蓝色三角形进行光栅化,覆盖到了该像素中心位置,像素执行ps,输出蓝色,对于4个采样,2个采样深度测试pass,用蓝色替代原来的颜色,最终的采样颜色为:
3. 最后resolve这个sample的颜色,得到最终的颜色
在shader3 model之前,ps执行都在像素的中心,后来加入了centroid插值,PS的输入属性就可以是三角形所覆盖的所有采样点的中心。如下图所示,对于昨天的no centroid,ps输出为白色,而对右边的centroid,则ps的输出为黄色。