2D 渲染组件合批规则说明
合批条件说明
2D 渲染组件合批需要满足以下几点条件:
条件 | 说明 |
---|---|
节点的 Layer 相同 | 由于 Layer 与节点是否渲染相关,因此不同的 Layer 之间不能进行合批。 |
使用的材质相同 | 材质相同是合批的必要要求。 由于 Creator 使用的是 材质实例化 的机制,所以当用户在设置了材质的 uniform 之后,材质会进行实例化,实例化之后的材质是无法进行合批的。如果用户在自定义材质中设置了 uniform (对应组件无法进行合批),在 uniform 值使用完毕后想要该组件参与合批,那么可通过 CustomMaterial 接口将材质资源重新赋值给组件即可。 |
渲染组件上所添加的材质的 BlendState 和 DepthStencilState 属性设置相同 | DepthStencilState 属性用于控制组件的深度检测和模板缓冲,是由引擎自动控制(用于 Mask 的效果实现)的,一般来说用户不需关心该属性的设置。 |
渲染组件的顶点信息要在同一个 buffer 中上传(v3.4.1 新增) | 一般情况下顶点信息是由引擎统一进行分配和管理的,用户无需关心。若想要了解更多相关信息,请参考下文 MeshBuffer 合批说明 部分的内容。 |
贴图源以及贴图采样相同 | 一般情况下该条件是影响合批最主要的因素,尤其对于 Sprite 和 Label 来说,贴图很容易产生差别导致无法合批。Creator 提供了部分方法用于更好地实现合批,详情请参考下文 合批方法说明 部分的内容。 |
合批方法说明
结合以上的合批条件说明,我们可以通过一些方法来实现更好的合批方法。需要额外说明的是,2D 渲染组件的渲染数据采集使用的是基于 节点树 的渲染方式,而有部分组件无法合批,且会打断其他组件合批,需要用户进行分模块管理节点树布局,以达到更好的合批效果。无法合批的组件包括:
- 内置组件 Mask、Graphics 和 UIMeshRenderer 组件由于材质不同和数据组织方式的差异,无法与其他组件合批;
- TiledMap、Spine 和 DragonBones 这三个中间件组件则是遵循自己的内部合批机制。
对于 Sprite 和 Label 组件来说,因为贴图很容易产生差别,导致无法合批。因此我们提供了以下方法可以更好地实现合批,用户可以根据需要参考使用:
- 对于 Sprite 组件,我们提供了 静态合图 和 动态合图 两种合批方案,通过将图片纹理合并,即可在其他条件满足的情况下进行合批。
- 对于 Label 组件,我们提供了 Bitmap 的缓存方法,通过将 Label 的纹理合图,即可实现 Sprite 和 Label 组件的合批,但需要注意的是,使用 Bitmap 缓存方式的 Label 不可频繁变动文字内容。
一般来说,通过控制材质和节点树状态,然后配合合图方法,便能够达到较好的合批效果。
MeshBuffer 合批说明
由于合批要求渲染对象的顶点在同一个 MeshBuffer 中,而以下几种情况则会造成 MeshBuffer 切换。
v3.4.1 之前
场景中要绘制的顶点数量超过了 MeshBuffer 所能容纳的最大顶点数量(65535 个)。
v3.4.1 之后
由于我们在 v3.4.1 中采用了新的渲染数据提交设计,所以需要注意以下几点:
项目设置 -> Macro Configurations 面板中的 BATCHER2D_MEM_INCREMENT 的值会影响每个 MeshBuffer 可容纳的最大顶点数量,当这个值越大,同一个 MeshBuffer 可容纳的 2D 渲染对象也就越多。但与此同时,内存增加的幅度也会越大,请用户结合自身项目规模酌情设置大小。
BATCHER2D_MEM_INCREMENT 的单位为 KB,与可容纳的顶点数量之间的转换关系如下:
引擎内置标准的顶点格式为 vfmtPosUvColor,在引擎中的定义为:
export const vfmtPosUvColor = [
// RGB32F 表示 3 个 32 位的 float
new Attribute(AttributeName.ATTR_POSITION, Format.RGB32F),
// RG32F 表示 2 个 32 位的 float
new Attribute(AttributeName.ATTR_TEX_COORD, Format.RG32F),
// RGBA32F 表示 4 个 32 位的 float
new Attribute(AttributeName.ATTR_COLOR, Format.RGBA32F),
];
由此我们可以得到每个顶点占用 9 个
float
值,每个顶点占用的空间为:1 * 9 * 4 / 1024(KB)
,其中:1 表示顶点数;
9 表示
vfmtPosUvColor
条件下每个顶点占用的float
值;4 表示每个
float
占用的字节数;1024 表示字节与 KB 转换单位。
因此 BATCHER2D_MEM_INCREMENT 的默认值 144KB,表示可容纳
144 * 1024 / (9 * 4)= 4096
个标准格式的顶点。需要注意的是:同一 MeshBuffer 容纳的最大顶点数不可超过 65535 个,即 BATCHER2D_MEM_INCREMENT 的最大值不可大于65535 * 9 * 4 / 1024 ≈ 2303.96(KB)
。
目前 2D 渲染使用的核心为 static VB,其主要内容包括:
VB 固定 伴随着组件的整个生命周期而存在,而决定渲染顺序的 IB 则放弃缓存,每帧进行录制。由于组件的 VB 信息多而复杂,直接保存下来可针对组件的内存段进行操作,而且保存下来可以避免无用的更新。
IB 每帧填充。相对于 VB 来说,IB 的结构简单、数量较少,并且会直接决定渲染顺序,所以在每帧遍历时重新填充 IB 消耗较小,且无需管理复杂的缓存机制。
由于 VB 固定,所以在整个组件的生命周期中,VB 会在最开始就分配好,直到组件销毁,所以在组件加载时,便会向预先分配好的 MeshBuffer 中申请好想要使用的 VB,然后在销毁时归还。
当 MeshBuffer 已经无法分配出组件需要的 VB 时,系统便会新创建一个大小为 BATCHER2D_MEM_INCREMENT 的 MeshBuffer 来继续分配 VB。