Unity引擎后处理性能优化方案解析

栏目: 后端 · 发布时间: 5年前

内容简介:这是侑虎科技第444篇文章,感谢作者Gordon供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群465082844)作者主页:作者也是U Sparkle活动参与者,UWA欢迎更多开发朋友加入U Sparkle开发者计划,这个舞台有你更精彩!

这是侑虎科技第444篇文章,感谢作者Gordon供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群465082844)

作者主页: https://zhuanlan.zhihu.com/p/39850106

作者也是U Sparkle活动参与者,UWA欢迎更多开发朋友加入U Sparkle开发者计划,这个舞台有你更精彩!

目前我们项目使用的后处理插件是 Unity-Technologies/PostProcessing 。选用前,我们对比过众多后处理插件,最后根据效果和使用方便程度,结合策划的需求,选用了 Unity-Technologies/PostProcessing (我用的v1,大家可以尝试v2版本)。这里我们不讨论后处理的效果,或者哪个插件的好坏。本文将介绍一个能通用的后处理性能优化方案。

一、OnRenderImage的性能问题

在我们看到的后处理教程或者后处理插件中,通常的处理方式是在OnRenderImage方法中处理后处理。

Unity引擎后处理性能优化方案解析

在我刚开始整合后处理的过程中发现,即使不做任何后处理,仅仅一句Graphics.Blit(Source, Destination),也会导致严重的掉帧,这看起来是不符合逻辑的。在Google后,找到问题的说明Post Process Mobile Performance : Alternatives To Graphics.Blit , OnRenderImage,原因如下:

Unity引擎后处理性能优化方案解析

答主给的解决方案如下:

Unity引擎后处理性能优化方案解析

也就是在OnPreRender中,将RenderTexture赋值给Camera,在OnPostRender中处理后处理渲染。

通过这种方案能大幅度减少掉帧。我们测试过用同样的后处理(例如Bloom)在使用OnRenderImage的时候,从60FPS掉到40FPS左右。改用PrePost方法后,从60FPS掉到55FPS左右,改善明显(用中低端手机测试效果明显些,我们是用的360手机。不同手机改善的程度略有差异,但是还是能看到至少几帧的提升)。相信这个优化方案,有不少同学之前已经看到过并已经在使用。

这个方案略有麻烦的一点是,当我们的Camera开启MSAA或者HDR的时候,会导致后处理不起效果。我猜测应该是MSAA和HDR会激活Unity引擎内部的渲染流程必须走OnRenderImage。

这里要特别注意的一点是,我们用的是Gamma Color Space,如果我们要HDR的效果,最好不要用PrePost这个优化方式,因为经测试会导致负优化,帧数反而下降。目前我还没找到好的办法,这里我们按照不需要HDR效果来说。

我们还是可以支持MSAA,解决方案是,根据QualitySettings.antiAliasing和我们的方式来创建Temp的RenderTexture。同时,我们需要关闭摄像机的MSAA和HDR选项。

Unity引擎后处理性能优化方案解析
Unity引擎后处理性能优化方案解析
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(或PrePost方法)中,这样能带来一些性能提升,虽然不如上面的PrePost效果明显,但是优化是一点点积累的,也是值得做。

具体方法, Unity-Technologies/PostProcessing 这个就比较有代表性,它将所有的效果整合到同一个OnRenderImage和同一个Shader中处理,只是通过材质的EnableKeyword来开关对应的功能。详细请看链接里的代码。

这里提一句,如果用PrePost方式优化,将不能和OnRenderImage方式在同一个Camera下混用,这里整合的时候,要根据项目的需求处理好。我们现在是用Unity的 Post Processing方案,改为PrePost的方式。

同时,大家使用各种后处理插件、效果,要注意根据需求做一些裁剪,某些不需要的效果尽量注释或删除,让整合的代码更加清晰可读,也减少一些额外的性能消耗(Shaderlab内存等)。

三、修改材质属性,不要使用String

通常的例子代码中,会使用String作为Key的方式来修改Mat的属性,很多Shader的插件内也是这么用的。

Unity引擎后处理性能优化方案解析 String的方式
Unity引擎后处理性能优化方案解析

这里,我们通过反编译可以看到,String的方式实际上会调用Shader.PropertyToID,所以,我们应该将整个ID Cache下来,通过ID的方式来调用。

Unity引擎后处理性能优化方案解析
Unity引擎后处理性能优化方案解析

这也是一个很小的点,但是如果是后处理这种,可能每帧都会调用的地方,所带来的优化效果还是很有意义的。

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

总结一下,主要的优化就是OnRenderImage转换为PrePost的方式,能大大地改善后处理的渲染效率(Opengles2和Opengles3都测试过)。我们使用的Unity版本是5.6.4,其它版本未测试,如果用其它版本,大家需要自己先测试一下。

无论优化多好,后处理始终对性能影响很大,特别是手机电量不足或者发热导致手机降频的时候,后处理将会导致掉帧加重。如果必须要使用后处理(策划,美术要求),那么做好性能开关、优化好后处理的性能是必须要做的。

最后说明一点:PrePost的优化方案只有在不需要HDR效果下才有优化效果(基于我的测试),如果需要HDR效果,还是用OnRenderImage来做吧。这块优化需要多多测试,不注意就容易出问题哦。

参考文章:

1. Post Process Mobile Performance : Alternatives To Graphics.Blit , OnRenderImage ?

2. OnRenderImage() is SLOW when MSAA is on

文末,再次感谢Gordon的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:465082844)。

也欢迎大家来积极参与U Sparkle开发者计划,简称"US",代表你和我,代表UWA和开发者在一起!

近期重磅 | 他们说“这个 工具 省下的时间可不是一点点”


以上所述就是小编给大家介绍的《Unity引擎后处理性能优化方案解析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

500 Lines or Less

500 Lines or Less

Amy Brown、Michael DiBernardo / 2016-6-28 / USD 35.00

This book provides you with the chance to study how 26 experienced programmers think when they are building something new. The programs you will read about in this book were all written from scratch t......一起来看看 《500 Lines or Less》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码