找回密码
 立即注册
查看: 780|回复: 0

[笔记] 十:Unity 后处理 性能优化

[复制链接]
发表于 2020-12-30 09:55 | 显示全部楼层 |阅读模式
实测,在unity 5.6版本已经没有OnRenderImage 性能问题,其他版本未测试,故在此更新说明。
---------------------------------------------------------------------------
在之前的文章“Unity ShaderLab内存优化“ 中,我提到我们后处理,使用的是Unity-Technologies/PostProcessing。之所以选用这个后处理,只是因为在看了众多后处理插件后,根据效果和使用方便程度,结合策划的需求,选用了这个后处理(我用的v1,大家可以尝试v2版本)。这里,我们不讨论后处理的效果,或者哪个插件的好坏。我将介绍一下能通用的后处理性能优化方案。
    OnRenderImage 的性能问题
在我们看到的后处理教程,或者后处理插件中,通常的处理方式是,在OnRenderImage方法中,处理后处理。
在我刚开始整合后处理的过程中,发现,即使不做任何后处理,仅仅一句Graphics.Blit(source, destination),也会导致严重的掉帧,这看起来是不符合逻辑的。在google后,找到问题的说明Post Process Mobile Performance : Alternatives To Graphics.Blit , OnRenderImage,原因如下
答主给的解决方案如下:
也就是,在OnPreRender中,奖rendertexture赋值给camera,在OnPostRender中,处理后处理渲染。
通过这种方案,能大幅度减少掉帧。我们测试过,用同样的后处理(例如bloom)在使用OnRenderImage的时候,从60 FPS 掉到40 FPS左右,改用pre post方法后,从60 FPS,掉到55 FPS左右,改善明显(用中低端手机测试效果明显些,我们是用的360手机。不同手机,改善的程度略有差异,但是还是能看到至少几帧的提升)。
相信这个优化方案,有不少同学之前已经看到过,并已经在使用。
这个方案,略有麻烦的一点是,当我们的camera开启MSAA或者HDR的时候,会导致后处理不起效果。我猜测应该是MSAA和HDR会激活unity内部的渲染流程必须走OnRenderImage。
(这里要特别注意的一点是,我们用的是Gamma color Space如果我们要HDR的效果,最好不要用pre post这个优化方式,因为经过测试下来,会导致负优化,帧数反而下降,目前我还没找到好的办法,这里我们按照不需要HDR效果来说)
我们还是可以支持MSAA,解决方案是,根据QualitySettings.antiAliasing和我们的来创建temp 的rendertexture,同时,我们需要关闭摄像机的MSAA和HDR选项。
https://forum.unity.com/threads/onrenderimage-is-slow-when-msaa-is-on.427006/
这里要注意处理的逻辑是:当我们在游戏设置界面开关后处理的时候,要配对地处理camera的MSAA 选项和rendertexture 的创建参数,以免出现后处理不起作用,或者关闭后处理后,抗锯齿没有正确开启的问题。
这应该是一个能立竿见影的优化,相对需要注意处理好一些细节和各种设置切换的处理,做好测试。
    合并多个后处理效果
当我们使用unity早期的Image Effect,或者一些单个效果后处理插件的时候,他们通常没有考虑整合的效率问题。以OnRenderImage的做法举例:通常是每个效果是一个脚本,他有自己的OnRenderImage,如果我们有4个效果,那是4个单独的OnRenderImage,这在代码层面的简洁性和易扩展性上,当然是有优势的。但是,这样做,性能是有问题的,我们需要尽量将各种后处理效果,整合到同一个OnRenderImage(或pre post方法)中,这样能带来一些性能提升,虽然不如上面的pre post效果明显,但是优化是一点点积累的,也是值得做。
具体方法,Unity-Technologies/PostProcessing这个就比较有代表性,它将所有的效果,整合到同一个OnRenderImage,同一个shader中处理,只是通过材质的EnableKeyword来开关对应的功能。这块我就不展开讲了,大家看链接里的代码,最实在。
这里提一句,如果用pre post方式优化,将不能和OnRenderImage方式在同一个camera下混用,这里整合的时候,要根据项目的需求,处理好。我们现在是用unity 那个 post processing方案,改为pre post的方式。
同时,大家使用各种后处理插件,效果,要注意根据需求做一些裁剪,某些不需要的效果,尽量注释或删除,让整合的代码,更加清晰可读,也减少一些额外的性能消耗(shaderlab内存等)。
    修改材质属性,不要使用string
通常的例子代码中,会使用string作为key的方式来修改mat的属性,很多shader的插件内,也是这么用的。
string的方式
这里,我们通过反编译可以看到,string的方式,实际上会调用Shader.PropertyToID,所以,我们应该将整个id cache下来,通过id的方式来调用
这也是一个很小的点,但是如果是后处理这种,可能每帧都会调用的地方,可能带来的优化,还是很有意义的。


还有一些优化,比如减少rendertexture的尺寸等,在网上很多关于优化的文章中都有提到,就不具体说了,网上能搜到很多。


总结一下,主要的优化,就是OnRenderImage转换为pre post的方式,能大大地改善后处理的渲染效率(opengles2 和 opengles3都测试过)。我们使用的Unity版本是5.6.4,其他版本未测试,如果用其他版本,大家需要自己先测试一下。
无论优化多好,后处理,始终还是对性能影响很大,特别是手机电量不足或者发热导致手机降频的时候,后处理将会导致掉帧加重。如果必须要使用后处理(策划,美术要求),那么做好性能开关,优化好后处理的性能,是必须要做的。我们也在进一步优化中,大家有好的优化心得和方案,也可以在评论里回复,谢谢大家。


最后说明一点:pre post的优化方案,只有在不需要HDR效果下,才有优化效果(基于我的测试),如果需要HDR效果,还是用OnRenderImage来做吧。这块优化,需要多多测试,不注意就容易出问题哦。图形渲染方面是我的弱项,希望大家指正。
参考文章:
    Post Process Mobile Performance : Alternatives To Graphics.Blit , OnRenderImage ? OnRenderImage() is SLOW when MSAA is on

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-12-23 12:39 , Processed in 0.091690 second(s), 27 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表