
一:动机
想了想有一阵子没写文章了,这段时间里改到了引擎的很多方面,也学到了很多东西,但是却没有记录下来,生活上也发生了很多事,但是现在这些烦恼我终于可以不用再管了,静下心来好好提升和沉淀自己吧,不忘初心。
回归正题,很久以前弄过半透明的离屏降分辨率渲染,所以对UE的半透总体流程算是比较熟悉把,最近刚好也有些想法再去改半透,但是UE的半透明其实还是有些坑的... 不把这个坑Fix了改也是白改,所以先开个文章简单记录下,如果有朋友有遇到相同的问题欢迎讨论。
另外PC端渲染的同学就可以不用关心了,因为PC上没有这个问题的,Mobile才会有,感兴趣的话也可以继续看。

二:半透明的景深后渲染
相信经常改UE材质的同学对这个应该比较了解了,UE对于半透是提供了一些特殊Pass的,比如Mobile Separate Translucency,开了这个开关就能够让半透明在景深后渲染

在实现上也是比较简单的,把这部分的绘制命令生成后并不会在RenderTranslucency里去Dispatchdraw,而是与普通的半透明区分开来,在DOF后再去Dispatchdraw,如下图的SeparateTranslucencyPass,在一些后处理效果画完后才回去画

三:这个功能的意义
先贴一下官方的解释
The short answer is that true depth of field on translucency in real time computer graphics is an unsolved research problem.
The versions we have implemented in UE4 are screen space effects that rely on a single depth value per-pixel.
That works great for opaque and masked materials but translucent materials do not write depth values.
Usually translucency is blended on to the scene before depth-of-field is computed resulting in the translucency being blurred as if it were at the same depth as the background opaque layer on to which it was blended.
That's the result you get in UE4 if you disable Separate Translucency on the material.
Separate Translucency is a feature that blends certain translucent objects on to the scene after depth-of-field has been calculated.
That prevents the artifact but those translucent materials will not be affected whatsoever by depth-of-field.
当然我知道你们应该没这个耐心去看

说人话就是有些半透明效果不希望受到景深的影响,比如一些特效技能的释放,如果有景深效果,那么这些特效就会被景深效果给糊掉,而事实上我们是不希望这些效果受到后处理影响的,所以就有了这个功能。
四:IOS存在的坑-深度测试
事实上这个功能在Pc Simulate Mobile的情况下是正常的,能够正常绘制,并且深度测试也正常,能够被其它物体遮挡。
但是在IOS设备上,深度测试就不正常了,不能被其它物体挡住,也就是总是能够被画出来,这个就是问题了,因为深度测试这个问题本身比在景深后渲染这个功能更重要。

一开始我们以为是自己对半透明的改动改坏了一些状态,导致深度测试失败了,后来发现好像UE本来就有这个问题

上面是UE材质开启这个功能的源码部分,可以仔细看下注释 (Note: Depth testing is not available),说实话我看到这段注释的时候内心是操蛋的。。。 你知道有这个问题你还不解决?考虑到自己用到的引擎版本是4-23,于是我开了份4-25的引擎源码看,发现这部分根本没变,好吧 Mobile端的渲染是捡来的,这么重要的问题可以拖这么多子版本...
这个坑所带来的Issue:问我为什么知道?因为我也遇到了,还查了好久,不说了都是泪
UE-69982unreal-engine-issues.herokuapp.com万恶的开始:
我们在IOS上的一个GPU特效在开了景深效果后消失了。。 对,消失了,但是在PC上模拟完全正常,由于之前我有改到半透明的东西,于是我开始在IOS上查这个问题

过程是痛苦的,我得解决思路就不详细阐述了,简单点来说就是排除法,先排除我们自己代码的问题,再排除CPU和GPU特效的问题,最后排除材质中跟深度有关节点问题...
最终我定位到了上面这个Issue,其实可以说是这个坑带来的连带反应吧,简单的来说就是Metal拿不到场景深度,导致如果材质如果勾选了Separete Translucency,并且材质中有Depth fade节点,那么恭喜你,在IOS上,用到这个材质的东西你都看不到了

当然其实要解决(临时)也很简单,规范下材质的制作(兼容下他这个Bug),DOF后画的半透明要什么DepthFade啊,把DepthFade从材质中删了,然后你就可以在手机上看到这个效果了,但是这个特效的深度测试是无效的,我不知道你们能不能忍,不过我想我们是不能忍的,现在看是能看到了,但是特么总是能看到,我想挡都挡不住。。。
五:截帧分析以及自己Fix的思路
UE自己不解决我们就自己找原因咯,深度测试有问题无非就是场景深度有问题,但是PC上模拟正常,IOS上不正常要查起来也挺难的,毕竟涉及到硬件,最终其实我有简单解决这个问题,但是不知道会带来什么坑,毕竟不知道官方的考量,所以我发了个贴问了下官方,希望朋友们能够去支持下。。
(PS:这个应该无所谓了,就是开了个Store深度,唯一可能有坑的地方就是MSAA了,UE如果开了MSAA,就算Store深度,深度在不同平台上Resolve出来都可能有问题,这个是UE自己的问题,遇到过的自然会懂,当然如果支持下UE把这个问题Fix掉了,那么就不用担心这些暗坑了)
链接如下:
https://answers.unrealengine.com/questions/984759/ios-separate-translucency-depth-test-not-work.htmlanswers.unrealengine.com
这里不懂得可以评论区问我,临时解决方案有两个(在IOS上测试过了,深度测试正常了) ,建议用第二个。
一:bRequiresTranslucencyPass设置为True


这是PC模拟Mobile和IOS上得第一个不同点,因为PC模拟这个值总是为true,也就是UE会为半透明再重开一个Pass,因为这个会多一次切换Pass得消耗,所以UE默认在IOS上不会开。
On mobile it's better to render as much as possible in a single pass
但是我觉得为了让深度测试正常,多一次这个消耗其实也不是很耗(会多些设置渲染状态和切RT得消耗),em..... 只是我觉得,毕竟那么多自定义的Pass我都加了...,感兴趣可以去看下面这篇文章TBDR架构相关
针对移动端TBDR架构GPU特性的渲染优化-腾讯游戏学院gameinstitute.qq.com
其实我还有一个疑惑点就是这个开关为什么会和Framebuffer fetch有关
Framebuffer fetch我大概有点概念,能够在画frame buffer的同时获取buffer上的一些值,是硬件级别的支持

有了framebuffer fetch就可以不用关心画出来的深度要不要保存了?我傻了,有大佬懂吗望解惑,
二:bKeepDepthConten设置为true

这个是UE自己的逻辑,大概意思就是要不要保留深度内容到后处理,这个值我在XCode上调试了,一直是False,根据它得判断条件在一些情况下会设置为true,所以这里可以动手脚。
最简单的想法是加个判断,如果后处理中有一些效果必须要深度测试就把这个值设置为true,我测试的逻辑也很简单,我把这个值改成了true(正常改的话那就是这一帧的绘制需要就设置为true,手机端嘛,能省就省。。)
然后在手机上发现之前没有正常深度测试的特效全部都能正常被挡住了。。Ok,笑容出现了

最后,如果有遇到相同问题的欢迎讨论,也欢迎大家在评论区问半透相关的问题
如果有收获记得点赞~
To be continued....