为什么延迟渲染和MSAA不搭 | Blurred code

为什么延迟渲染和MSAA不搭

2022/02/04

LastMod:2022/02/08

Categories: CG

MSAA与延迟渲染

翻了下之前在Games101上写的MSAA的实现,发现错的离谱(逃。 改了一下以后顺手就把MSAA和延迟渲染这部分写了。

MSAA的原理

MSAA

MSAA的buffer里保存的是着色中心点的颜色,buffer的大小为屏幕大小乘以子sample的数量,其需要保存\(n\)sample的深度和sample的颜色。 其渲染流程如如下

GBuffer与MSAA

MSAA的子sample保存的颜色是像素中心点的颜色,其resolve阶段在所有三角形的fshader运行着色以后进行。

延迟渲染的第二个阶段已经丢失了几何信息(其实际是渲染一个quad或者一个大三角形),所以在延迟渲染的第二个阶段运行MSAA是无意义的。

MSAA运用到延迟渲染的第一个阶段是可以的,目前看到两种方法。

Per-Sample Shading

Gbuffer中我们往往还要保存深度、法线等信息,对这些信息resolve是无意义的,比如下图。同一个像素的4个子sample有不同的法线,其加权出来的法线与单独计算光照后再加权得出的结果是不一样的。

Shader X7里的 Deferred Shading with Multisampling Anti-Aliasing in DirectX 10文章采用了multisampled texture来保存所有的GBuffer,在fshader里对每个sample而不是像素进行着色,最后对光照结果进行resolve。为了进一步提高效率,考虑到MSAA对三角形内部是不起作用的,所以用了额外的一个stencil buffer保存三角形的边缘信息,只对边缘做MSAA

优点:

缺点:

Albedo Resolve

延迟渲染与MSAA的那些事看来的,大概意思是在保存GBuffer的时候只考虑Albedo这张纹理采用MSAA,因为对法线和深度进行MSAA是无意义的。在着色阶段的时候采用的是resolve以后的Albedo,其他正常着色。

思考了一下,感觉不太对。把resolve简写为\(R\),把Shading过程简写为\(S\)。MSAA是在着色阶段完成以后进行resolve,其过程不等于对一个resolved的变量进行着色,和逻辑和上面的法线例子比较类似。并且由于MRT不能单独对某张纹理设置MSAA,所以要渲染两个Pass分别记录Albedo和其他Gbufferdrawcall数得翻倍。

\[ R(S(Albedo)) \neq S(R(Albedo)) \]

优点: 没看出来有什么优点

缺点:

总结

MSAA作为一种几何抗锯齿的方法(其只是增加了对几何的采样,没有额外的光照计算),对阴影的闪烁或者PBR中容易出现的高光闪烁是不起作用的。在延迟渲染中应用MSAA是可能的,但是代价较高,尤其是带宽开销,效果又欠佳,所以不如用TAA。

Reference