# 前言

UE 在 5.1 更新了 OIT 算法,其算法原理很简单,把半透明重写写入深度进行排序和颜色混合。这里主要记录一些细节和官方的做法,同时也水一篇文章

# 原理

首先 UE 有两种 OIT 排序,一个是 EOITSortingType::SortedTriangles 三角面排序,另一个是 EOITSortingType::SortedPixels

# SortedTriangles

其中三角面排序,可以直接在 component 里面打开

只能解决半透明物体自身的排序而不能解决多个物体之间的半透明排序。图中有些重叠的面是排序错误的,而且还会产生面之间的闪烁。因为现在还是实验性功能,所以未来肯定会得到解决。

这功能会在 DeferredShadingRenderer 里面 RenderTranslucency 前面调用 OIT::AddSortTrianglesPass 去排序。

做法是先把要排序的物体三角面的中心点在 shader 里转化为屏幕坐标,然后用屏幕坐标的 z,就是深度,转换到 mesh bound 里面深度

""
1
const float fSliceIndex = saturate((ViewP.z - ViewBoundMinZ) / (ViewBoundMaxZ - ViewBoundMinZ));

得到 index 限制 0 到 31, 要是 nVidia 设备就是 64,因为 compute shader 每个 group 的 buffer 设置为 32 个线程。然后把求得的深度放入 shared memory 对应的 index 中写入,进行原子操作,要是里面已经有写入了,就偏移一位,最后按照 primitive id 写入 buffer,之后在下一个 pass 把排序好的 index 获取他的三个顶点写出到输出 buffer 上。

之后会把之前的 indexbuffer 替換为这个 buffer。具体可以查看 OIT.cpp 里面的 AddOITSortTriangleIndexPass 函数

# SortedPixels

而用像素排序则可以解决各个透明排序的问题,用的是 Multi-Layer Alpha Blending (MLAB) 技术,但跟 MLAB 技术有点区别
https://zhuanlan.zhihu.com/p/368065919
首先会开四张贴图,颜色、透射比、深度、当前需要的排序次数,这里有个小优化就是排序最大的次数是你当前像素的 min(overdraw,自己设定最大排序次数)

分辨率是你最大采样个数开方向下取整 X 窗口分辨率,就是说会把多张 pass 合成一张大的,是 R32 格式的,最后会颜色 R11G11B10F 压缩进这帖图了。

在渲染半透明物体时候会填充这些 pass,按深度近向远简单填充和插入这些 pass 中,然后接下来会调用 OIT::AddOITComposePass 这函数去混合,而混合的时候会进行一次 Bubble sort,最后把所有颜色 * 折射比从最近到远加起来。

顺便说一下,现版本 5.2 要是场景没有半透明物体,依然会新开 pass 和清理 pass,这点消耗就有点没必要了

更新于

请我喝[茶]~( ̄▽ ̄)~*

Natsuneko 微信支付

微信支付

Natsuneko 支付宝

支付宝

Natsuneko 贝宝

贝宝