美文网首页
3、渲染合批

3、渲染合批

作者: 雷尘子 | 来源:发表于2023-10-28 19:59 被阅读0次

    渲染合批

    批次合并的本质就是在每一帧的渲染过程中,保证连续节点的渲染状态一致,将尽可能多的节点数据合并一次性提交,从而减少绘图指令的调用次数,降低图形API调用带来的性能消耗,同时也避免GPU进行频繁的渲染状态切换。渲染状态包括:纹理状态、Blend模式(混合模式)、Stencil状态(模版测试)、Depth Test(深度测试)等。

    由于draw call带来CPU及GPU的渲染状态切换的消耗

    一次 Draw call 就代表一次图形绘制命令的调用

    CPU调用图形API,比如OpenGL,命令GPU进行图形绘制。

    draw command call 尽可能多地提交节点数据,

    合批的规则是节点的layer、使用的材质、渲染组件的blendState、DepthStencilState相同、贴图源以及贴图采样都相同才会进行合批。

    1.节点的layer:由于layer会涉及到渲染与否,所以不同的layer之间不能合批。

    2.材质:材质相同时合批的必然需求,由于我们使用的材质实例化的机制。所以用户设置了材质的uniform后,进行实例化,实例化后的材质是无法进行合批的。如果自定义材质进行了uniform设置之后导致此组件无法合批,之后uniform值使用完毕想要该组件参与合批,可以将材质资源重新赋值给组件即可(通过CustomMaterial)。

    3.BlendState状态:对于部分2D渲染组件可以设置混合模式,这个值不同无法进行合批。

    4.DepthStencilState状态:这个值控制着深度检测和模板缓冲,一般来说用户不需要关心这个值的设置,由引擎自动控制(用于Mask的效果实现)

    5.贴图源和贴图采样:一般来说,这个条件是影响合批的主要条件,尤其对于精灵和文本来说,贴图很容易产生差别导致无法合批。引擎提供了部分方法

    1.同一张图,相同的纹理状态

    2.相同的Blend混合模式

    3.同一个Shader(材质、Effect)

    Sprite组件 静态合图与动态合图

    Label组件 提供了BitMap的缓存方法,通过将Label的纹理合图,即可实现Sprite和Label的合批,但请注意,BitMap缓存模式的Label不可频繁变动文字内容

    一般来说,用户通过控制材质和节点树状态配合合图方法,能够达到较好的合图效果

    静态合图

    静态合图即为编辑器提供的自动图集功能,以及其他第三方图集打包工具如:TexturePacker 等。在资源层面进行散图合并,保证 UI 节点使用的都是同一张贴图,因为同一张图集的纹理状态都是一致的,所以能够达到渲染批次合并对纹理状态的要求。

    对于 Label 组件,为了保证所有的 Label 节点使用相同的纹理,通常会使用 BMFont (位图字体)将要使用的 UI 文字提前进行打包,并使用引擎的自动图集与散图一起合并进一张大的纹理,即可与其他相邻的 Sprite 节点进行批次合并。自动图集的创建与设置可以参考 自动图集资源,新建一个自动图集资源配置,然后把所有你希望进行合图的 UI 图片,BMFont 和艺术数字都拖到自动图集资源所在的目录即可。BMFont的文本制作可以通过 BMFont 字体制作工具(有插件bitmap-font),将常用的美术字或者文本制作生成一张字体图片及其字体映射文件(font.png && font.fnt)。然后直接拖入编辑器中即可使用。

    动态合图

    在运行时,引擎通过将散图添加到动态图集中,来保证节点使用的纹理一致。由于动态图集使用的是默认纹理状态,所以只有当散图的纹理状态与动态图集的状态一致,才可参与到引擎的动态合图中。

    Label 组件目前提供三种 Cache Mode:NONE、BITMAP 和 CHAR。

    NONE 模式即 Label 的整个文本内容会进行一次绘制,并进行提交,但是并不参与动态合图。

    BITMAP 模式即 Label 的整个文本内容会进行一次绘制,并加入到动态图集中,以便进行批次合并。

    CHAR 模式即 Label 会将文本内容进行拆分,单个字符进行绘制,并将字符缓存到一张单独的字符图集中,下次遇到相同字符不再重新绘制。

    动态合图的说明可以参考 动态合图说明

    动态合图的最佳实践

    目前引擎的动态图集主要有两种:

    一种是为散图及使用 BITMAP 模式的文本提供的动态图集,最大数量为 5 张,尺寸为 2048 * 2048。

    另外一种是为使用 CHAR 模式的文本提供的字符图集,单个场景只有一张,尺寸为 2048 * 2048。

    这两种动态图集在切换场景时会进行清理释放。由于动态图集空间有限,因此需要最佳化的利用。

    对于一些不常变化的静态文本,例如 UI 界面的标题,属性栏的固定文本,如果使用系统文本,可以设置为 BITMAP 模式,缓存到动态图集中,这样连续的 UI 节点即可进行动态合批。由于图片一般会打包为静态图集,而为了最大限度的把界面中的 Label 进行合批,可以将界面中的这些静态文本节点层级放在最上层,并保证这些 Label 节点连续即可避免 Label 节点打断批次,同时合并连续的 Label 节点降低 Draw call。

    对于一些频繁变化的文本,例如游戏中常用的倒计时,如果使用 BITMAP 模式,会导致大量的数值文本占用动态图集空间,但是其使用的字符数量有限,只有数字 0 - 9 这 10 个字符,为了避免频繁绘制,即可设置为 CHAR 模式,进行字符缓存,将单个字符文本添加到字符图集中,这样缓存一次之后,后续所有的数字组合都可以从已缓存的字符中获取,提高性能。如果连续的 Label 节点使用的都是 CHAR 模式,因为使用的是同一张字符图集,所以也可以保证这些节点能够进行批次合并。

    相关文章

      网友评论

          本文标题:3、渲染合批

          本文链接:https://www.haomeiwen.com/subject/qhaxidtx.html