unity 之Graphic 之Draw call batching

Draw call batching

在屏幕上显示一个GameObject, 引擎必须调用图形的API(如OpenGL或Direct3D)。Draw调用通常是资源密集型的,图形API为每个DrawCall做大量工作,导致CPU端的性能开销. 这主要是由drawcall之间的状态变化引起的(例如切换到不同的材质), 这会导致图形驱动程序中的资源密集型验证和转换步骤。

Unity使用了两种技术来解决这个问题:

  • Dynamic batching: 对于足够小的网格,这将转换它们在CPU上的顶点,将许多类似的顶点分组在一起,并一次性将它们全部绘制出来。
  • Static batching:将静态的(非移动的)游戏对象合并到大的网格中,并以更快的方式渲染它们。

与手工合并游戏对象相比,内建的批处理有几个优点,GameObjects仍然可以单独选择. 然而,它也有一些缺点;静态批处理会增加内存和存储开销,而动态批处理会增加一些CPU开销。

Material set-up for batching

只有共享相同材料的GameObjects才能被打包在一起. 因此,如果你想实现良好的批处理,你应该致力于在尽可能多的不同游戏对象之间共享素材。

如果你有两种完全相同的Material(比如都是standard材质球,或者其他的),只是贴图不同,你可以把它们合并成一个大的材质里面,比如图集 Texture atlasing (see the Wikipedia page on Texture atlases for more information).这样你就可以用一个material了

如果您需要从脚本中访问共享Material的属性,注意Renderer.material 创建材质的副本。相反Renderer.sharedMaterial 修改初始material

阴影通常可以在渲染的时候混合在一起,即使它们的Material不同.

Dynamic batching (Meshes):动态批处理

Unity可以自动批量移动游戏对象到同一个draw call,如果他们拥有共同的material和满足其他标准.动态批处理是自动完成的。

  • Batching dynamic GameObjects每个顶点都有一定的开销,所以Batching只适用于包含不超过900个顶点属性的网格,不超过300个顶点。
    • 如果你的着色器使用Vertex Position, Normal and single UV,那么你可以批处理300个顶点,而如果你的着色器使用Vertex Position, Normal, UV0, UV1 and Tangent那么只有180个顶点。
    • Note: attribute count limit might be changed in future.
  • 如果GameObject(游戏对象)在转换中包含镜像,则不进行批处理(例如,scale+1比例的GameObject A和scale-1比例的GameObject B不能批处理在一起)
  • 需要lightingmap批处理的GameObjects ,它们的lightmaps应该指向同一张,lightingmap内部有index和 offset/scale
  • Multi-pass Shaders break batching.
    • “additional per-pixel lights”不支持批处理
    • The Legacy Deferred (light pre-pass) rendering path
      has dynamic batching disabled, because it has to draw GameObjects twice.

动态批处理的工作原理是将所有的GameObject(游戏物体)顶点发送成CPU上的world space(世界空间),所以只有当这个工作量小于draw call时才有优势.

Dynamic batching (Particle Systems, Line Renderers, Trail Renderers)

对于具有Unity动态生成的几何图形的组件,动态批处理的工作方式与它在网格中的工作方式不同。

  • 对于每个兼容的渲染器类型,Unity将所有可批处理的内容构建到一个大的顶点缓冲区中
  • 渲染器设置批处理的材质状态。
  • Unity将顶点缓冲区绑定到图形设备。
  • 对于批处理中的每个渲染器,Unity将把偏移量更新到顶点缓冲区,然后提交一个新的draw调用。

 

Static batching

静态批处理允许引擎减少对任何尺寸的几何图形的绘制要求,只要它共享相同的材料,并且不移动. 它通常比动态批处理更有效(它不发送顶点到),但是它使用更多的内存。

使用静态批处理需要额外的内存来存储合并后的几何图形,如果多个GameObject(游戏物体)在静态批处理之前共享相同的几何图形,那么将在编辑器或运行时为每个GameObject(游戏物体)创建一个几何图形的副本。这可能并不总是一个好主意;有时你不得不牺牲渲染性能,避免一些游戏对象的静态批处理,以保持更小的内存占用。例如,在茂密的森林中将树标记为静态可能会对内存产生严重影响。

在内部,静态批处理是通过将静态游戏对象转换为世界空间,并为它们建立一个共享的顶点和索引缓冲区来实现的。如果你已经启用了优化的Mesh__ Data__(在播放器设置中),那么Unity会删除所有顶点元素,这些顶点元素在创建顶点缓冲区时不会被任何着色器变量使用.

Tips

Currently, only Mesh Renderers, Trail Renderers, Line Renderers, Particle Systemsand Sprite Renderers可以被批处理.  skinned Meshes, Cloth, 其它组件没有被批处理

Semi-transparent Shaders usually require GameObjects to be rendered in back-to-front order for transparency to work. Unity first orders GameObjects in this order, and then tries to batch them, but because the order must be strictly satisfied, this often means less batching can be achieved than with opaque GameObjects.

Manually combining GameObjects that are close to each other can be a very good alternative to draw call batching. For example, a static cupboard with lots of drawers often makes sense to just combine into a single Mesh, either in a 3D modeling application or using Mesh.CombineMeshes.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TO_ZRG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值