什么是批处理
为了将物体绘制到屏幕上,引擎必须向图像API(例如OpenGL、Direct3D)发送一个draw call指令。每一次draw call就可以大致理解为一个渲染批次(batch)。Draw call属于资源密集型的指令,图形API要为每个Draw call做大量的工作。造成CPU性能消耗的主要是渲染状态的切换导致的,例如切换到不同的材质,这会导致在图形驱动中产生密集的资源验证和切换。为了减少draw call的调用,Unity使用了两种技巧来优化这个问题:
- 动态批处理:对于足够小的mesh,动态批处理通过将他们的顶点整合到一个批次中进行绘制。
- 静态批处理:通过将不会移动的静态物体合并到更大的mesh中,以提升渲染速度。
与手动合并相比,内置的批处理方式最大的有点在于,每一个物体仍然可以被单独剔除。但是他们也有缺点,静态批处理会消耗更多的内存空间,动态批处理会产生CPU开销。
材质方面的要求
只有使用了相同材质的物体才能够实现批处理。如果两个不同的物体,使用的两个材质,只是纹理上的差别,那就把他们的纹理合并到一起,这样就可以使用同一个材质。脚本中使用Render.material属性时,会重新生成一个原来材质的拷贝,所以用Render.sharedMaterial可以保持材质的一致性(但是使用同一个材质的物体,都会被改变)。关于阴影,只要材质中使用的是相同的Shadow Pass,就可以实现批处理,即便他们不是同一个材质。
静态批处理
静态批处理因为不需要再CPU中进行顶点转换,所以要比动态批处理快的多,但是会占用更多内存。如果多个物体共享同一个材质,使用静态批处理时,会为每个几何体生成一份拷贝,不管是在编辑器还是运行时。所以在内存紧张的环境下,就需要损失一定的渲染性能来避免静态批带来的内存开销。
静态批处理比较简单,只需要将场景种不会动的静态物品设置Batching Static,剩下的就交给引擎了。
静态批处理的原理是将物体转换到世界空间,并为他们建立一个共享的顶点和索引缓存。在Player Setting中勾选了Opeimized Mesh Ddata以后,Unity在构建缓存时,会移除那些在所有shader变体中都没有被用到的顶点的elements(官