CPU在渲染管线中的工作
1)检测需要被绘制的对象
2)准备发送给GPU的指令
3)向GPU发送指令
多线程渲染
0)Unity 包含三种线程类型:主线程、渲染线程、工作线程
1)主线程:大部分的CPU工作,和部分渲染任务
2)渲染线程:专门用于CPU向GPU发送指令
3)工作线程:执行单独的任务(比如剔除、网格蒙皮)
4)不是所有平台都支持多线程渲染
多线程优化方法:
1)尝试开启 Player Settings 中的 Graphic Jobs 选项,看是否有性能提升
2)使用 Profiler Window 找到引起问题的任务
向GPU发送指令
线程:通常在渲染线程,特定平台在工作线程(PS4)
1)这步通常是导致CPU绑定的原因。
2)有两种指令:Draw Call 和 SetPass Call;其中 SetPass Call 最耗性能。
3)降低 batch 数,让更多对象共享相同的渲染状态,能够减少 SetPass Call。
4)三种方式降低 batch 和 SPC:减少渲染对象数量、减少对象渲染次数、合批
减少渲染对象数量
1)减少场景中对象数量
2)减少摄像机的绘制距离(Far Clip Plane)
3)使用摄像机的分层剔除功能(Layer Cull Distance)
4)使用遮挡剔除(Occlusion Culling)
5)实现定制的更高效的遮挡剔除
减少对象渲染次数
说明:实时灯光、阴影、反射,会导致对象被渲染多次。
两种渲染路径:前向渲染路径(Forward Rendering)、延迟渲染路径(Deferred Rendering)
优化方法:
1)优化动态光
2)使用烘焙光照替代动态光
3)降低阴影质量和显示距离
4)控制使用反射探针的数量
合批
说明:一个 Batch 包含了多个对象的数据。
合批规则:使用相同材质实例、具有标准化的材质设置
优化说明:就算合批没有减少SPC也能提升性能,因为CPU处理单个Batch要比多个高效
优化方法:
1)静态合批:相邻静态对象;缺点是提高内存占用
2)动态合批:静态或动态对象;缺点是提高CPU计算
3)GPU instancing:大量相同对象
4)UI合批
5)纹理图集:UI、2D、3D;Unity 内置 Sprite Pachker 工具
6)通过 Unity Editor 或代码,手动合并网格。缺点是不能单独剔除对象。
7)任何对 Render.material 的使用,都会返回一个新的材质实例。因为不再是同一个材质,因此无法被合批。使用 Render.sharedMaterial 替代。
剔除、准备与合批
线程:主线程,或工作线程
1)剔除工作通常消耗不大:关闭不需要的摄像机、renderer
2)合批能提升发送指令的速度,但是也要注意合批是否引起了CPU绑定
蒙皮(Skinned meshes)
线程:主线程,或工作线程
说明:使用骨骼动画驱动网格时,需要使用 SkinnedMeshRenderer 组件。
优化方法:
1)对于没有动画的对象,使用 MeshRenderer 组件替代 SkinnedMeshRenderer 组件;或导入时选择不导入动画,则自动替换为 MeshRenderer。
2)对于只有一段时间播放动画的,在不播放动画时替换为更简单的Mesh,或使用 MeshRenderer 替换 SkinnedMeshRenderer。
3)优化动画对象,减少模型顶点。
4)某些平台,可以使用 GPU Skinning。
主线程中和渲染无关的操作
主线程还要处理许多和渲染无关的操作,当渲染优化无法解决问题时,可以通过优化渲染无关的部分,来提升性能。