Unity OIT(Weighted Blended Order-Independent ...
背景[*]半透明物体的渲染,大部分情况下是使用与顺序相关的alpha-blending技术实现的。大致原理是依据透明度将半透明物体的颜色和当前color Buffer中的颜色进行混合,使物体看起来好像透过它看到了其他物体。
[*]然而,由于半透明的混合算法大部分是前后不对称的,例如srcAlpha oneMinusSrcAlpha, 因此渲染出来的效果严重依赖渲染顺序。当面对一个复杂的场景时,透明渲染几何间的按顺序排序是非常困难且耗时的,并且如果某个几何体出现自交叉的情况,那么就无法进行正确排序,也会导致渲染效果不正确问题。因此,需要设计一种方法来避免几何间按顺序排序。
原理
[*]Order independent transparency,就是跟顺序无关的透明。其基本思想是计算每个像素的最终叠加颜色,将透明物体逐像素进行叠加,而无需考虑叠加的顺序。而加权混合方法是在第一代算法的基础上的优化版本,其根据当前片元的深度与透明度,计算出每个片元对于最终像素的贡献比重。当片元透明度很高,或者距离相机很远时,它的贡献比重就会相应的变低。基本原理可以参考如下图的伪代码:
实现
[*]本例在Unity Buildin管线下实现的,由于无法方便的修改管线的绘制流程,因此无奈使用了比较麻烦的后处理的方式实现。
[*]整体的绘制需要三张RT:
[*]首先是先正常绘制场景中不使用OIT的物体和OIT中不透明的物体,将该部分绘制到opaqueTex上面。
opaqueTex
[*]然是绘制需要排序的透明物体,此时给物体特殊的 "LightMode",使用commandbuffer进行手动绘制,将物体的颜色和α分别绘制OIT记录片元颜色的accumTex以及OIT记录片元透明度的revealageTex上。
accumTex
revealageTex
[*]最后将三张rt根据公式进行混合,最终得到正确的图形。
finalTex
效果
[*]经过测试发现,使用OIT可以有效的解决一些因透明排序错误所造成的渲染问题。具体对比如下图所示(本例中裙子使用的均为半透材质):
OIT
ODT
OIT
ODT
性能
[*]本例在安卓平台下进行的测试,实际数据就不po了,结论是:
[*]在CPU瓶颈下,由于OIT不需要进行透明排序,因此OIT的耗时会比ODT的小;
[*]而在GPU瓶颈下,由于OIT在shader中增加了一些新的计算,同时增加了几次全屏RT Blit,因此OIT的耗时会比ODT的大。
参考文献
[*]倪朝浩:Web端的实时透明渲染算法
[*]https://jcgt.org/published/0002/02/09/paper-lowres.pdf
页:
[1]