关于Unity图形渲染的性能优化

本文主要参考Unity5.3.7官方文档,如果本人理解的有不正确的地方还请不吝赐教!

图形渲染的性能优化,分两大方面,CPU的优化和GPU的优化。

GPU瓶颈主要受限于填充率和内存带宽(如果降低分辨率可以加速,说明瓶颈在于填充率)

CPU瓶颈主要受限于渲染的批处理数量(看Profiler的Rendering Batches信息 或者Game视图中的Stats信息)

其次造成瓶颈的原因:

GPU需要处理过多的顶点,多少合适取决于硬件性能和shader复杂度,一般移动设备上不超过10万,PC上不超过3百万

CPU需要处理过多的顶点,一般是因为蒙皮骨骼,布料模拟和粒子系统等

以下说说优化策略具体有哪些,分三个部分: CPU部分,GPU部分,两者皆有

一、CPU部分:

 1)最核心的降低DrawCall,合理运用Unity的Darw Call Batching技术(后面具体展开说明,以下简称 : 合并)

 2)控制Material的数量,尽量使用共享材质

 3)尽量少使用反射,阴影等

 4)减少灯光数量,减少实时光照,使用光照贴图和光照探测

 5)使用LOD技术(根据与摄像机的距离,使用不同细致度的模型)

 6)使用Per-Layer Cull Distances(某个Layer的对象,根据与摄像机距离超过设置值剔除)

 7)使用CullingGroup(对不同远近的对象可以自定义策略优化)

 8)远处无法到达的景物可以绘制在skybox上,变成贴图

 9)使用 Occlusion Culling,细小和半透明的对象可以设置Occludee Static

 10)使用God Rays(体积光,曙光):非真正光源,而是用透明纹理表现光线效果

 11)尽量少使用蒙皮骨骼动画,尽量降低骨骼数量

二、GPU部分:

 1)优化模型:尽量减少三角形数量,尽量减少UV映射接缝和硬边的数量

 2)使用纹理压缩(加快加载速度,减少内存占用)和 Mipmaps(原理类似LOD,将贴图映射成一组分辨率不同的纹理,在三角形很远很小时使用分辨率低的纹理)

 3)对Shader代码优化

a)fixed/half/float三种数据类型合理选择:
         fixed : 颜色值,光照信息,法线
         half:纹理uv坐标
         float: 不要在像素着色器使用,用于顶点位置信息

b)少使用pow,sin, cos等函数

c)使用内建函数,而不是自己写

 4)少使用alpha test(如那些cutout shader),使用alpha-blend代替

 5)移动设备选择Mobile或Unlit目录下的shader,会比较高效(和那些复杂的shader的有近似的效果)

 6)尽量不使用Fog,使用渐变面片 或shader模拟

 7)适配屏幕分配率不要过高

 8)合并纹理(Atlas):尽可能把多张小纹理合并到一张大纹理(Atlas)

三、两者皆有:

 1)尽量少使用逐像素光照(正向渲染时),逐像素光照会使网格在多个pass中渲染

 2)不要把相距很远受不同逐像素光照的网格,合并成一个,因为只要照到一部分,整个网格都会拿去逐像素渲染;

 3)Quality Settings可以设置最多多少逐像素光照,超出的自动变成逐顶点光照。其权重依据:灯光设置Important,距离网格的远近和亮度

 4)尽量少使用实时阴影

 5)控制好粒子系统的粒子总数和生存周期

着重讲一下DrawCall Batching,分两部分:静态合并和动态合并

目前只能对Mesh Renderer和 粒子系统进行合并。

1、静态合并(Static batching)

原理:运行游戏后将一组游戏对象的多个模型会被动态合并为1个。这组游戏对象都使用同一材质的在一个DrawCall来完成。这些游戏对象运行后无法移动缩放和旋转。

注意:即使物体都使用了同样的模型,在batch后每一个物体都会创建一份模型对应的geometry,在新的Combined Mesh里。所以过多的batch会增加内存占用。例如场景里的树群就不适合Static Batch,而适合动态合并。

实现方法:

(1)勾选Batching Static: 勾了即可

(2)代码中使用UnityEngine.StaticBatchingUtility实现(可以在任何平台调用):

      1)将所有要合并的静态物体(不须勾Batching Static)放入统一一个root

      2)StaticBatchingUtility.Combine(root);

      之后就合并好了!

区别:

勾选Batching Static:完全自动合并,在MeshFilter里显示的是 Combined Mesh(root:scene)。合并后不能移动

StaticBatchingUtility:合并到一个游戏对象下。合并后可以整体移动

2、动态合并(Dynamic batching)

要进行动态合并,必须满足诸多条件:

 1) 模型文件共计顶点数不超过900。(重复使用同一个Mesh不计)

 2) 单个物体顶点数不超过300个,shader可以使用法线和一个UV。如果shader使用法线,2个UV和Tangent,则不超过180个

 3) 游戏对象使用不同缩放(即xyz轴)的也会被合并

 4) 游戏对象都使用相同的材质(同一个材质对象)

 5) 不使用光照贴图,或者都使用同一光照贴图

 6) 都使用单Pass的Shader

 7) 都要关闭 接收实时阴影

两种合并,三种方式:

三种方式:
①动态合并
优点:内存消耗小;可以自由位移旋转
缺点:要求众多
②标记Light map static合并
优点:最方便快捷,要求最少
缺点:完全不能移动;内存有消耗;只能处理在Scene中默认放置的物体
③代码StaticBatchingUtility合并
优点:方便快捷,要求少;可整体移动;可处理代码动态加载的场景或物体
缺点:内存有消耗

代码合并是要求最少的,并可以整体移动。而动态合并可以移动旋转,并做Animation动画。故推荐StaticBatchingUtility + 动态合并。

另外,半透明物体往往需要渲染顺序颠倒,这时将不能被合并。

来源:CSDN,作者:foxyfred,转载此文目的在于传递更多信息,版权归原作者所有。
原文:https://blog.csdn.net/foxyfred/article/details/74395126
版权声明:本文为博主原创文章,转载请附上博文链接!

推荐阅读