批渲染batches与DrawCall的关系

发表于2017-11-02
评论0 2.5k浏览

考虑到有些新手开发人员对批渲染batches与DrawCall不是很了解,不能很清楚的知道这两者的使用,为此,下面就给大家介绍下批渲染batches与DrawCall的关系。

批渲染(Batch

batch render 是大部分引擎提高渲染效率的方法,基本原理就是通过将一些渲染状态一致的物体合成一个大物体,一次提交给gpu进行绘制,如果不batch的话,就要提交给很多次,这可以显著的节省drawcall,实际上这主要节省了cpu的时间,cpu从提交多次到提交一次,对gpu来说也不用多次切换渲染状态。当然能batch的前提一定是渲染状态一致的一组物体。


Unity3d的批渲染分为两种,动态和静态

静态批

要求:必须使用同一张material,然后在编辑器里设置为static batching的。

特点:静态批是无法运动的。

所以一般制作流程上,对于场景这些静态的物体都采用静态批,美术会根据场景的规模,将相邻的一片物件的贴图合并到一张或几张1024512的大图上,这样这些物件可以使用同一个material,就可以静态批在一起,大幅节省dc

静态批的时候Unity3d会在运行时生成一个合并的大模型,并且为这个模型指定一张共同的贴图,所以这个批在一起的数量是有限的,如果批在一起的定点数过多,它就会自动分成两个批,一个静态批的上限我自测大约在60000多个顶点单元。

场景中不能移动的物件可以使用静态合并,它不受顶点数的限制,可以大幅减少DrawCall。但为了将元素合并到一个大模型中,这项技术需要额外的内存。主要的内存消耗在于共享多边形会在内存中重复创建。因此有时候需要牺牲渲染效率来避免静态合并,来保证内存够小。例如在茂密的树林中使用这项技术会导致大量的内存消耗。

 

动态批

动态批是对那些没有标记成static batching的物体在runtime unity自动将他们批在一起,这个是可以支持运动物体的,但是限制较为严格:

动态合并在满足以下条件时是自动完成的:

1.一个批次总顶点单元少于900 (模型总顶点数小于900

2.批在一起的所有的模型应用同样的缩放值(不包含镜像transform改变。不改变Scale

3.使用相同的材质

4.相同的一张lightmap(如果使用动态lightmap需要指定正确)

5.不能使用多passshader

6.不能接收阴影

由于需要在合并时通过CPU计算转为世界坐标,这项技术只在CPU消耗比DrawCall消耗便宜时才值得。这个衡量标准会根据平台产生差异,例如苹果平台上DrawCall的消耗便宜,就不应该使用这项技术。这个功能可以在Editor->Project Setting->Player中进行设置打开与关闭。

 

所以一般是小的运动的模型才比较容易动态批在一起,当然unity又说可能在后续版本放宽这个限制

 

NVIDIA GDC上曾提出 25k batch/sec的渲染量会使1GHzCPU达到100%的使用率,因此使用公式

25Kn(GHZ)Percentage/Framerate=Batch/Frame

可以推算出某些CPU可以抗多少Batch。例如红米手机CPU1.5GHz,假设分出20%资源供渲染,希望游戏跑到30帧。那么能抗多少DrawCall 25k * 1.5 * 0.2 / 30 = 250。因此从这方面也能看出,如果CPU不能分出更多的资源供渲染计算,能抗的DrawCall就会变少。

 

举例:

Unity5.0及以上,如果场景中有3个对象,且都用同一个shader(材质),这三个对象模型的总顶点数多于900个,则需要进行两次合批,每次合批都会调用三次DrawCall,但CPU的状态不会改变,既不用进行状态的检查(CPU的计算绝大多数时间花在了状态检查上),速度会快很多;(DrawCall数会多于batches数)

Unity5.0以下,每次合批,只会生成一个DrawCall

 

对于Unity5.0及以上,可以通过判断两个物体的shader(材质)是否相同,若相同,则使这两个物体具有相同的MeshRenderer组件,则可以达到合并DrawCall的目的,以减少DrawCall

 

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论