批处理

Batches和Saved by batching

Batches:批处理
批出理的核心就是CPU把使用相同材质球的物体的网格合并再一起,然后把这个合并后的网格扔给GPU渲染,而不是一个一个网格扔给GPU渲染。

Stats面板上的Batches的值(批处理次数)说白了就是Draw Call的次数,就是要渲染完整个场景,CPU要总共通知GPU多少次。

Batch影响因素
  1. 模型是否能够进行静态、动态批处理
  2. 灯光是否开启阴影
  3. 物体是否投射阴影

UGUI合批

UGUI控件本质上也是网格,渲染上和3D组件没有什么不同

UGUI的合批就是把某个Canvas下满足合批规则的UI控件的网格合并为一个大的网格,然后将这些网格合并在一起,调用一次Draw Call,然后提交个GPU进行绘制。

UGUI合批规则

总体规则

  1. 两个UI控件能合批的基本条件是这两个控件使用的材质球(Shader)和贴图要完全相同。
  2. 合批是以Canvas为单位的(Canvas嵌套不支持,不包含子Canvas,子Canvas会是另外一个批次)

规则细节

  1. 把所有Canvas给找出来,然后剔除掉不必渲染的Canvas
  2. 计算Canvas下各UI控件的深度值Depth(需要注意的是Image的属性里面也有个depth,两者不是同一个东西)
  3. 按照Hierarchy中从上往下的顺序依次遍历Canvas下所有UI元素,计算深度值 (这个后面会说)
  4. 各个UI的Depth计算完毕后,依次按照Depth、material ID、texture ID、RendererOrder(即UI层级队列顺序,即Hierarchy面板上的顺序)排序(条件的优先级依次递减,且均为从小到大排序)。然后剔除Depth = -1的UI元素,得到Batch前的UI 元素队列,这个队列被称之为VisiableList。
  5. 得到VisiableList之后,判断VisiableList中相邻的元素是否能够合批(相同的材质和贴图)。需要注意这里不再考虑Depth是否相同,只要两个元素相邻然后材质和贴图相同,即使两个元素的Depth不相同,这两个元素也能合批。然后一个批次一个批次的合并网格,提交GPU进行渲染。

深度值的计算规则
对于当前的UI元素CurrentUI
i. 如果CurrentUI不渲染,则Depth = -1
ii. 如果CurrentUI要渲染,但CurrentUI下面没有其他UI元素与其相交,则Depth = 0
iii. 如果CurrentUI要渲染,下面只有一个UI元素(LowerUI)与其相交,且CurrentUI与LowerUI可以合批(材质和贴图完全相同),则CurrentUI.Depth = LowerUI.Depth;如果两者不能合批,CurrentUI.Depth= LowerUI.Depth + 1
iv. 如果CurrentUI要渲染,下面有n个元素与其相交,则按照步骤iii,分别计算出n个Depth(Depth_1、Depth_2、Depth_3…),然后CurrentUI.Depth取其最大值,即CurrentUI.Depth = max(Depth_1, Depth_2, Depth_3,…)
上面步骤中的“下面”和“相交”要明确下意思,这两个概念很重要。

细节中的细节

  1. UI元素相交不是指Rect Transforms组件的相交,是被渲染出来的那些东西重叠了才能叫做相交
  2. 该Canvas下动态创建或删除UI元素都将导致该Canvas重新计算合批(需要注意的是仅仅会影响这一个Canvas,子Canvas或父Canvas以及其他Canvas不会重新计算)