GPUPro360 Alpha Blending as a Post-Process

#brief
- 要处理的问题是foliage的渲染。alpha blend排序无解,alpha test效果不行(硬边缘、camera移动的时候洞在闪),alpha to coverage的gradiant不好、硬件支持参差不齐
- 分3个pass来做
- opaque pass:正常地画普通的opaque物体, pure还用MSAA
- mask pass:用add和max operator分别累加alpha值,生成alpha mask(就是说要知道opaque物体在多大程度上被树挡住了)
- color pass:画foliage的颜色
- composition pass:用mask pass得到的alpha值来blend opaque和color
# 个人感觉
- 感觉这个方法还是有优势的:用这个方法真的是实际上做了真blend(而不是像alpha to coverage那样用coverage sample平均做了个假blend。比如我想做一个人藏在一颗小树后面的效果,小树的alpha值比较小,应该是blend才行),而且还确实很大程度上还是有alpha test(有深度、earlyz这些还是享受到了)
- 带宽占用:用了好几个rt,但是你仔细算算,其实就是用了8个channel的RT(opaque 3, mask 2, color 3),比起4x、8x的MSAA确实是省的(更别提4x、8x的alpha to coverage效果怎么可能比得上alpha blend)


# 3.2 The Alternatives
- alpha blend. 要排序、而且排序都不一定能够有用(物体内的面片穿插),总之行不通。
- alpha test,可行,配合zbuffering technique(就是preclip)还能省掉opaque排序,就算还是做opaque排序,那还能降低fillrate。alpha test效果会不好,边缘锐利
- alpha to coverage. 原理是利用硬件提供的功能,把alpha值转化成MSAA用的coverage mask,通过MSAA的计算对coverage sample进行平均,获得平滑的效果。边缘比alpha test更好,而且alpha test的好处(不用排序,prez)都有。但是alpha gradient的quality会不如alpha blend(这个不看图我不知道咋回事啊)

# 3.4 initial attempts
- 最早是alphatest+preclip,需要调一调 alphatest的reference value。效果能看但是不好,主要是视角相对树移动的时候那些洞的闪烁
- alpha to coverage,由于有了soft edge,洞的问题好多了,但是由于依赖了MSAA,不同平台的表现不一样(我想是因为支持的MSAA级数不同),另外fillrate增大

# 3.5 The Screen Space Alpha Mask
- 需要3个rendertarget
- rtOpaque(3 channels)
- rtFoliage(3 channels)
- rtMask(minimum 2 channels)

# 3.5.1 opaque pass
- 以2x且MSAA的分辨率渲染(我的天),然后downsample到screen resolution,而且downsample有另外有门道
- 同时生成rtDpeth(depthBuffer)

# 3.5.2 mask pass
- 生成foliage的silhouette
- 内容就是alpha值,而且是additive blend。而且enable depth test、backface culling和depth write
- 虽然additive blend可以做到order independent,但是很快会saturate。这在你眼前有个很透明的东西的时候就有问题了。因为和远处的东西叠加后全saturate成实的了。
- 另外又说为了由detail,所以要把alpha reference value 设成0,这样所有alpha值都会叠加上来
- 用max operator,得到的silhouette依然能看出结构来,而且从物体中间到边缘的梯度变化还是有
- 但是max operator单独用是不对的(显得transparent),所以考虑是不是结合着用。。
- 需要同时输出max和additive。也就是要color和alpha用不同的blend方式
- shader compile有对应的优化。也就是说可以用一个uber shader,只不过在这个stage,加上最后那几行(out.color.xyzw = out.color.wwww)后前面的都是dead code,可以自动消除

# 3.5.3 color pass
- 输出到rtFoliage
- disable backface culling, alpha blend, enable depth test depth write
- alpha reference value有讲究,后面讲

# 3.5.4 final compose pass
- 就是用mask pass把opaque pass和color pass的结果blend起来
- mask本身又有2个值,又要lerp,都是调调调

# 3.6 alpha reference issues
- 由于要blend,所以color pass本身还是开alpha test的,那问题来了,这个alpha test的reference value 是多少呢?不够大,那就没alpha test的效果了,太高了,会导致color pass画上去的东西其实很小,blend的时候就会把clear color给blend上去。
- 所以这里想了个奇葩方法,把color pass的blend值也提供给artist,调一调让artifact减少。文章自己都说了work well but suboptimal。全局一个肯定是顾头不顾腚
- 另外还提到,把mask给square一下,这样mask衰减更快,但是还是可以保持alpha test的效果(卧槽这不就是人为调整mask值么)。感觉这个就是瞎调了

# 3.8 conclusion
- cons里面提到了一点:这种方法用来搞草这种大量、半透明的东西,会有artifact


# uber shader

猜你喜欢

转载自blog.csdn.net/killer4747/article/details/80782365