读书笔记15《Unity Shader入门精要》
第 16 章 Unity 中的渲染优化技术
程序优化的第一条准则 :不要优化。程序优化的第二条准则(仅针对专家 ! ) :不要优化。——Michael A.Jackson
移动平台的特点
- GPU 架构不同。由于处理资源等条件的限制,带宽和功能更小
为了减少overdraw(一个像素被绘制多次),PowerVR芯片(iOS设备和某些Android)使用基于瓦片的延迟渲染(Tiled-based Deferred Rendering,TBDR);Adreno(高通的芯片)和Mali(ARM的芯片)则会使用低精度的深度检测提前剔除片元;而Tegra(英伟达的芯片)使用传统架构,overdraw更可能造成性能的瓶颈。
影响性能的因素
(1)CPU
- draw call 过多
- 脚本或物理模拟复杂
(2)GPU
- 顶点过多;逐顶点计算过多
- 片元过多(分辨率过高 / overdraw);逐片元计算过多
(3)带宽
- 纹理尺寸很大,还不压缩
- 帧缓冲分辨率过高
优化技术
(1)CPU
- 使用批处理技术减少draw call数目
(2)GPU
- 减少需要处理的顶点数目
- 优化几何体(网格)
- 使用模型的 LOD(Level of Detail)技术
- 使用遮挡剔除(Occlusion Culling)技术
- 减少需要处理的片元数目
- 控制绘制顺序
- 警惕透明物体
- 减少实时光照
- 减少计算复杂度
- 使用 Shader 的 LOD(Level of Detail) 技术
- 代码优化
(3)带宽
- 缩小纹理
- 利用分辨率缩放(帧缓冲吧)
Unity 中的渲染分析工具
渲染统计窗口(Rendering Statics Window)
通过 Game 视图的右上角的菜单中 Stats 打开
- Batches:一帧中需要进行的批处理数目
- Saved by batching:合并的批处理数目,表明了批处理为我们节省了多少 draw call
- Tris 和 Verts:绘制的三角面片和顶点数目
- Screen:屏幕的大小,以及它占用的内存大小
- SetPass:渲染使用的 Pass 的数目,每个 Pass 都需要 Unity 的 runtime 来绑定一个新的 Shader,可能造成 CPU 的瓶颈。
- Visible skinned meshes:渲染的蒙皮网格的数目
- Animations:播放的动画数目
性能分析器(Profiler)的渲染区域(Rendering Area)
Window -> Analysis -> Profiler
帧调试器(Frame Debugger)
其他性能分析工具
Android 平台:高通的 Adreno 分析工具;英伟达的 NVPerfHUD
iOS 平台:Unity 内置的分析器;PowerVRAM 的 PVRUniSCo shader 分析器;Xcoed 中的 OpenGL ES Driver Instruments (工具较少;宏观上的统计数据可能更有参考价值)
减少draw call数目
批处理的思想:在每次调用 draw call 时尽可能多地处理多个物体。使用统一材质的物体可以一起处理,他们之间的不同仅仅在于顶点数据的差异。
动态批处理
Unity 自动进行。使用动态批处理的物体仍然可以移动。
条件限制:
- 能够进行动态批处理的网格的顶点属性规模要小于 900 。 例如,如果 shader 中需要使用顶点位置、法线和纹理坐标这 3 个顶点属性,那么要想让模型能够被动态批处理,它的顶点数目不能超过 300 。需要注意的是,这个数字在未来有可能会发生变化,因此不要依赖这个数据 。
- 使用光照纹理(Lightmap) 的物体需要小心处理 。 这些物体需要额外的渲染参数,例如,在光照纹理上的索引、偏移量和缩放信息等 。因此,为了让这些物体可以被动态批处理,我们需要保证它们指向光照纹理中的同 一个位置 。
- 多 Pass 的 shader 会中断批处理。在前向渲染中,我们有时需要使用额外的 Pass 来为模型添加更多的光照效果,但这样一来模型就不会被动态批处理了 。
静态批处理
在运行开始阶段,把需要进行静态批处理的模型合并到一个新的网格结构中。只需要进行一次合并操作,比动态批处理更加高效。
条件限制:
- 不可以在运行时刻被移动
- 需要占用更多的内存来存储合并后的几何结构
- 额外的 Pass 不会被批处理。(处理平行光的部 Base Pass 部分仍然会被静态批处理)
如果在静态批处理前一些物体共享了相同的网格,那么在内存中每一个物体都会对应一个该网格的复制品,即一个网格会变成多个网格再发送给 GPU 。如果这类使用同一网格的对象很多 ,那么这就会成为一个性能瓶颈了。例如,如果在一个使用了 1 000 个相同树模型的森林中使用静态批处理,那么,就会多使用 1 000 倍的内存,这会造成严重的内存影响 。
共享材质
如果两个材质之间只有使用的纹理不同, 我们可以把这些纹理合并到一张更大的纹理中, 这张更大的纹理被称为是一张图集 (atlas)。 一旦使用了同一张纹理, 我们就可以使用同一个材质,再使用不同的采样坐标对纹理采样即可。
除了纹理不同外, 不同的物体在材质上还有一些微小的参数变化,例如,颜色不同某些浮点屈性不同。一种常用的方法就是使用网格的顶点数据(最常见的就是顶点颜色数据)来存储这些参数。
建议
- 尽可能使用静态批处理,但小心对内存的消耗。
- 用动态批处理注意条件限制。
- 游戏中的小道具,例如可以捡的金币等,可以使用动态批处理。
- 包含动画的物体,其中不动的部分可以标记为“Static”(使用静态批处理)
减少需要处理的顶点数目
优化几何体
尽可能减少模型中三角面片的数目。
模型的 LOD 技术
当对象逐渐远离摄像机时,减少模型上的面片数量,从而提高性能。
要为同一个对象准备多个包含不同细节程度的模型。
遮挡剔除技术
遮挡剔除会使用一个虚拟的摄像机来遍历场景, 从而构建个潜在可见的对象集合的层级结构。在运行时刻,每个摄像机将会使用这个数据来识别哪些物体是可见的,而哪些被其他物体挡住不可见。使用遮挡剔除技术,不仅可以减少处理的顶点数目,还可以减少overdraw, 提高游戏性能。
Unity 手册
减少需要处理的片元数目
减少overdraw
控制绘制顺序
- 尽可能让物体从前往后绘制(使用不透明物体的渲染队列)
- 把占据屏幕比例大的,总是在前面的物体优先绘制;天空盒最后绘制(它永远出现在所有物体后面)。
时刻警惕透明物体
几乎一定会造成 overdraw。
- 尽量减少半透明 GUI 所占面积。实在不行就把 GUI 绘制 和 三维场景的绘制交给不同的摄像机。
- 透明度测试的 clip/discard 会导致一些硬件的优化策略失效。
减少实时光照和阴影
- 使用烘焙技术,把光照提前烘焙到一张光照纹理(lightmap)中。把静态物体的阴影信息存储到光照纹理中,只对动态物体使用适当的实时阴影。
- God Ray:不是真的光源,而是通过透明纹理模拟得到的。
- 把复杂的光照计算存储到一张查找纹理(lookup texture,LUT)中。运行时只要使用光源方向、视角方向、法线方向等参数,对LUT采样就能得到光照结果。对主要角色可以用更大分辨率的LUT,而NPC使用较小的LUT。
节省带宽
减小纹理大小
- 用正方形纹理;纹理的长宽值是 2 的整数幂
- 多级渐远纹理技术(mipmapping)
- 纹理压缩。不同的 GPU 架构有自己的纹理压缩格式。Unity 可以根据不同的设备选择不同的压缩格式。(但 GUI 纹理,出于对画质的要求,有时不选择压缩)
利用分辨率缩放
雨松 MOMO - Unity3D研究院之使用Android的硬件缩放技术优化执行效率
降低计算复杂度
Shader 的 LOD 技术
1 | SubShader { |
可以使用 Shader.maximumLOD 或 Shader.globalMaximumLOD 来设置最大的 LOD 值。
也就是有选择地使用 Shader。。
代码优化
对象数 < 顶点数 < 像素数
- 尽可能地把计算放在每个对象或逐顶点上。例如在实现高斯模糊和边缘检测时,把采样坐标的计算放在顶点着色器中,这样的做法远好于把它们放在片元着色器中。
- 尽可能使用低精度的浮点值进行运算。
- 最高精度的 float/highp 适用于存储顶点坐标等变量,计算速度最慢,尽量避免在片元着色器中使用这种精度;
- half/mediump 适用于一些标量、纹理坐标等变量;
- fixed/lowp 适用于绝大多数颜色变量和归一化后的方向矢量。
- 避免对这些低精度变量进行平凡的 swizzle 操作。
- 尽量避免在不同精度之间的转换。
- 使用尽可能少的插值变量。如果需要对两个纹理坐标插值,通常会把它们打包在同一个 float4 变量中。但是在 PowerVR 上,不应该这么做。
- 尽可能不使用全屏的屏幕后处理效果。尽量使用低精度运算。高精度的运算可以使用查找表(LUT),或者转移到顶点着色器中进行处理。
- 尽量把多个特效合并到一个 Shader 中。 选择性地开启特效。
- 尽可能不要使用分支语句和循环语句。
- 尽可能避免使用类似 sin、tan、pow、log 等复杂的数学运算。用查找表替代。
- 尽可能不要使用 discard 操作,因为会影响硬件的某些优化。
根据硬件条件缩放
先保证游戏最基本的配置可以在所有平台上运行良好,然后再对一些具有更高表现能力的设备,开启一些更“养眼”的效果,例如更高的分辨率,屏幕后处理特效,粒子效果等。
扩展阅读
- Unity 手册中的移动平台优化实践指南(自己去搜)
- Unity 手册 - 优化图像性能
- SIGGRAPH 2011 上,Unity 进行的一个关于移动平台上 Shader 优化的演讲
- Unite 2013 会议上,Unity 名为 针对移动平台优化 Unity 游戏的演讲
- GDC 2014 上,Unity 展示的如何使用内置的分析器分析移动平台的游戏性能(可以去 Youtube 上找视频)
- SIGGRAPH 2015 会议上,名为 Moving Mobile Graphics 的课程中,移动平台上 PBR 的优化技术。(可以去 Unity 的博客找)
- 成功的移动平台游戏也是很好的学习资料。如《ShadowGun》,Unite 2011 上,该游戏的开发者给出了游戏中使用的渲染和优化技术。
- 游戏优化实例——Unity 自带的项目《Angry Bots》。可以在 Unity 资源商店下载到完整的项目源代码。
- 标题: 读书笔记15《Unity Shader入门精要》
- 作者: 铁名_IronName
- 创建于 : 2026-01-30 10:14:15
- 更新于 : 2026-02-15 15:21:11
- 链接: https://blog.ironname.top/2026/01/30/读书笔记15《Unity-Shader入门精要》/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。