Babybus-u3d技术交流-减少Draw Call(批渲染)
描绘调用批处理 Draw Call Batching
Date:2013-08-11 08:47
To draw an object on the screen, the engine has to issue a draw call to the graphics API (OpenGL ES
in the case of iOS). Every single draw call requires a significant amount of work on the part of the graphics API, causing significant performance overhead on the CPU side.
在屏幕上渲染物体,引擎需要发出一个描绘调用来访问图形API(iOS系统中为OpenGL ES)。每个描绘调用需要进行大量的工作来访问图形API,从而导致了CPU方面显著的性能开销。
Unity combines a number of objects at runtime and draws them together with a single draw call. This operation is called "batching". The more objects Unity can batch together, the better rendering performance you will get.
Unity在运行时可以将一些物体进行合并,从而用一个描绘调用来渲染他们。这一操作,我们称之为"批处理"。一般来说,Unity批处理的物体越多,你就会得到越好的渲染性能。
Built-in batching support in Unity has significant benefit over simply combining geometry in the modeling tool (or using the CombineChildren
script from the Standard Assets package). Batching in Unity happens after
visibility determination step. The engine does culling on each object individually, and the amount of rendered geometry is going to be the same as without batching. Combining geometry in the modeling tool, on the other hand, prevents effecient culling and results in much higher amount of geometry being rendered.
Unity中内建的批处理机制所达到的效果要明显强于使用几何建模工具(或使用Standard Assets包中的CombineChildren脚本)的批处理效果。这是因为,Unity引擎的批处理操作是在物体的可视裁剪操作之后进行的。Unity先对每个物体进行裁剪,然后再进行批处理,这样可以使渲染的几何总量在批处理前后保持不变。但是,使用几何建模工具来拼合物体,会妨碍引擎对其进行有效的裁剪操作,从而导致引擎需要渲染更多的几何面片。
Materials 材质
Only objects sharing the same material can be batched together. Therefore, if you want to achieve good batching, you need to share as many materials among different objects as possible.
只有拥有相同材质的物体才可以进行批处理。因此,如果你想要得到良好的批处理效果,你需要在程序中尽可能地复用材质和物体。
If you have two identical materials which differ only in textures, you can combine those textures into a single big texture - a process often called [texture atlasing
. Once textures are in the same atlas, you can use single material instead.
如果你的两个材质仅仅是纹理不同,那么你可以通过纹理拼合操作来将这两张纹理拼合成一张大的纹理。一旦纹理拼合在一起,你就可以使用这个单一材质来替代之前的两个材质了。
If you need to access shared material properties from the scripts, then it is important to note that modifying [Renderer.material
will create a copy of the material. Instead, you should use [Renderer.sharedMaterial
to keep material shared.
如果你需要通过脚本来访问复用材质属性,那么值得注意的是改变Renderer.material 将会造成一份材质的拷贝。因此,你应该使用Renderer.sharedMaterial 来保证材质的共享状态。
Dynamic Batching 动态批处理
Unity can automatically batch moving objects into the same draw call if they share the same material.
如果动态物体共用着相同的材质,那么Unity会自动对这些物体进行批处理。
Dynamic batching is done automatically and does not require any additional effort on your side.
动态批处理操作是自动完成的,并不需要你进行额外的操作。
Tips: 提示:
Batching dynamic objects has certain overhead per vertex
, so batching is applied only to meshes containing less than 900
vertex attributes in total.批处理动态物体需要在每个顶点上进行一定的开销,所以动态批处理仅支持小于900顶点的网格物体。
If your shader is using Vertex Position, Normal and single UV, then you can batch up to 300 verts and if your shader is using Vertex Position, Normal, UV0, UV1 and Tangent, then only 180 verts. 如果你的着色器使用顶点位置,法线和UV值三种属性,那么你只能批处理300顶点以下的物体;如果你的着色器需要使用顶点位置,法线,UV0,UV1和切向量,那你只能批处理180顶点以下的物体。
Please note: attribute count limit might be changed in future
请注意:属性数量的限制可能会在将来进行改变。
Don't use scale. Objects with scale (1,1,1) and (2,2,2) won't batch. 不要使用缩放。分别拥有缩放大小(1,1,1) 和(2,2,2)的两个物体将不会进行批处理。
Uniformly scaled objects won't be batched with non-uniformly scaled ones.统一缩放的物体不会与非统一缩放的物体进行批处理。
Objects with scale (1,1,1) and (1,2,1) won't be batched. On the other hand (1,2,1) and (1,3,1) will be. 使用缩放尺度(1,1,1) 和 (1,2,1)的两个物体将不会进行批处理,但是使用缩放尺度(1,2,1) 和(1,3,1)的两个物体将可以进行批处理。
Using different material instances will cause batching to fail. 使用不同材质的实例化物体(instance)将会导致批处理失败。
Objects with lightmaps have additional (hidden) material parameter: offset/scale in lightmap, so lightmapped objects won't be batched (unless they point to same portions of lightmap) 拥有lightmap的物体含有额外(隐藏)的材质属性,比如:lightmap的偏移和缩放系数等。所以,拥有lightmap的物体将不会进行批处理(除非他们指向lightmap的同一部分)。
Multi-pass shaders will break batching. E.g. Almost all unity shaders supports several lights in forward rendering, effectively doing additional pass for them 多通道的shader会妨碍批处理操作。比如,几乎unity中所有的着色器在前向渲染中都支持多个光源,并为它们有效地开辟多个通道。
Using instances of a prefab automatically are using the same mesh and material. 预设体的实例会自动地使用相同的网格模型和材质。
Static Batching 静态批处理
Static batching, on the other hand, allows the engine to reduce draw calls for geometry of any size (provided it does not move and shares the same material). Static batching is significantly more efficient than dynamic batching. You should choose static batching as it will require less CPU power.
相对而言,静态批处理操作允许引擎对任意大小的几何物体进行批处理操作来降低描绘调用(只要这些物体不移动,并且拥有相同的材质)。因此,静态批处理比动态批处理更加有效,你应该尽量低使用它,因为它需要更少的CPU开销。
In order to take advantage of static batching, you need explicitly specify that certain objects are static and will not
move, rotate or scale in the game. To do so, you can mark objects as static using the Static checkbox in the Inspector:
为了更好地使用静态批处理,你需要明确指出哪些物体是静止的,并且在游戏中永远不会移动、旋转和缩放。想完成这一步,你只需要在检测器(Inspector)中将Static复选框打勾即可,如下图所示:
Using static batching will require additional memory for storing the combined geometry. If several objects shared the same geometry before static batching, then a copy of geometry will be created for each object, either in the Editor or at runtime. This might not always be a good idea - sometimes you will have to sacrifice rendering performance by avoiding static batching for some objects to keep a smaller memory footprint. For example, marking trees as static in a dense forest level can have serious memory impact.
使用静态批处理操作需要额外的内存开销来储存合并后的几何数据。在静态批处理之前,如果一些物体共用了同样的几何数据,那么引擎会在编辑以及运行状态对每个物体创建一个几何数据的备份。这并不总是一个好的想法,因为有时候,你将不得不牺牲一点渲染性能来防止一些物体的静态批处理,从而保持较少的内存开销。比如,将浓密森里中树设为Static,会导致严重的内存开销。
Static batching is only available in Unity iOS Advanced.
静态批处理目前只支持Unity iOS Advanced。
Further Reading 进一步阅读
Measuring performance with the Built-in Profiler
用内置分析器测试性能
Rendering Statistics
渲染数据统计窗口