虚幻4.22移动端实现GrabPass抓屏

最近几天在给UE4.22加上GrabPass这个功能。

目前UE4折射材质在后处理阶段单独渲染一次扭曲VectorPass,然后再和SceneColor做合成。

UE这么做的原因还是因为移动端的GPU架构实在是不合适使用GrabPass的功能,移动端的GPU都是区块状的TBDR架构,虽然有 frame buffer fetch 扩展可以快速的拿到片上的buffer缓存,但是如果想要像要Copy Frame Buffer的话还是非常非常的耗的。

但UE4这种折射的做法带来了新的问题,折射的物体在后处理阶段渲染,那么所有的半透明材质,包括位于折射物体前面的特效,都会被这个折射物体扭曲,看着非常的难受。

UE4.22貌似有个分离不透明物体渲染pass的选项,但是勾上了就没办法使用Bloom效果,比较好的方式还是使用GrabPass类似的效果,像Unity那样。

我参考了Custom Depth的做法,在材质编辑器中的Scene Textures中注册了一个新的Global Texture,然后在Mobile的Render函数中插入了我的GrabPass函数,我想把GrabPass放在第一个要求抓屏贴图的网格渲染前调用,就像Unity那样,但是当我看了看Mobile的Translucency渲染调用,MeshDrawCommand List堆叠的整整齐齐的,然后来个Flush,完全没有我GrabPass插入的位置。

于是我只能在Opaque Mask渲染完后GrabPass了。

最后,在GrabPass时会遇到MSAA的一些小问题(实际上是大问题,我花了三天时间测试不同的机型来确定是否真的会发生),UDN上有大佬说GrabPass后MSAA的Depth Render Buffer会发生Resolve,然后再也Store不回来了。不过我在GrabPass时,显式禁用了该Pass的DepthStencil,在Renderdoc上查看Depth的Render Buffer并没有使用到,后面的Pass也一切正常。

Image

但正常的只有小米手机,华为手机则发生了错误,在同时使用了MSAA和GrabPass时,华为手机会Resolve我的Depth Render Buffer,然后再也拿不回来了,淦。

Image

但是使用Memory Copy的方式可以有效解决这个问题,我看了UE的Copy函数,它先调用了glcopyimagesubdata复制一份原生的数据,再在cpu上解析复制出来的数据,也就是说,使用Copy是不会修改原来的Buffer数据的。

但这也让我很不爽,因为不论是Shader Draw Copy的方式,还是Memory Copy的方式,都在红米Note8上多消耗了3ms。我原先的打算是通过Shader Draw Copy的方式渲染1/2屏,1/4屏这样的方式做性能适配,现在这方法没起效果,似乎没这么轻松了。

© - 2024 · 月光下的旅行。 禁止转载