Draw call batching (绘制合批)-Dynamic batching (动态合批)

1,079 阅读3分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

作为一名优秀的开发者,对于技术的探求应该是永无止步的,如何让自己更进步,那就只有不停的学习,不停的充电.而这些都都是说起来容易做起来难,坚持才是难的地方 --蛙哈哈

和 GPU instancing 一样, draw call batching 也是为了提升渲染效率, 降低 draw calls 的功能, 那么 draw call batching 和 GPU instancing 有什么区别呢?

且听我一一道来!

Dynamic batching (动态合批)

在开启动态合批时, Unity 会检查视野范围内的非动画模型,筛选符合条件的模型进行合批操作,将他们的网格合并后与材质球一起传给GPU去绘制.

动态合批有以下限制条件:

  1. 批处理仅会应用于总共包含不超过 900 个顶点属性且不超过 300 个顶点的网格

  2. 如果着色器使用顶点位置、法线和单个 UV,最多可以批处理 300 个顶点

  3. 如果着色器使用顶点位置、法线、UV0、UV1 和切线,则只能批处理 180 个顶点

  4. 如果游戏对象在变换中包含镜像,则不会对这些对象进行批处理(例如,具有 +1 缩放的游戏对象 A 和具有 –1 缩放的游戏对象 B 无法一起接受批处理)

  5. 即使游戏对象基本相同,使用不同的材质实例也会导致游戏对象不能一起接受批处理。例外情况是阴影投射物渲染

  6. 带有光照贴图的游戏对象具有其他渲染器参数:光照贴图索引和光照贴图偏移/缩放。通常,动态光照贴图的游戏对象应指向要批处理的完全相同的光照贴图位置

  7. 多 pass 着色器会中断批处理

    • 几乎所有的 Unity 着色器都支持前向渲染中的多个光照,有效地为它们执行额外 pass。“其他每像素光照” 的绘制调用不进行批处理
    • 旧版延迟(光照 pre-pass)渲染路径会禁用动态批处理,因为它必须绘制两次游戏对象

为啥动态效果有这么多限制条件呢?

  1. 动态批处理的工作原理是将所有游戏对象顶点转换到 CPU 上的世界空间,就会增大 CPU 的性能消耗
  2. 在摄像机移动过程中每帧都会进行合并网格的消耗算力,这使得CPU算力消耗太大,相比减少的Drawcall数量,得不偿失

所以仅在该工作小于进行绘制调用的情况下才有优势, 绘制调用的资源需求取决于许多因素,主要是使用的图形 API。例如,对于游戏主机或诸如 Apple Metal 之类的现代 API,绘制调用的开销通常低得多,通常动态批处理根本没有优势。