为了账号安全,请及时绑定邮箱和手机立即绑定

游戏性能优化之 batching(合批)和instancing(实例化)

经常性会被问到如何优化DrawCall,或者DrawCall太多怎么办。

那么读完这篇文章你就能明白几种drawcall优化的方式。

通常引擎一般会提供3种合批的方式: 静态合并,动态合并,实例化

那么3种合批的方法到底有什么区别呢,我们需要在何时使用对应的方法?

这里我们首选从底层驱动来说起,以OpenGL为例,绘制元素的API一般为:


glDrawElements 或者 glDrawArrays

调用这些方法后,cpu会将顶点数据传入显存,之后由显卡进行绘制。

每次调用这些方法,我们称之为一个DrawCall

那么当多次调用这些方法时,会明显导致draw增多。

所以在优化游戏时,我们很多情况首先要做的就是进行DrawCall的优化。

为了解决DrawCall太多的问题,我们很容易想到的就是把相同材质的网格进行合并。

既然你的的材质是一样的,那么我合并网格后只要调用一次 glDrawElements 就只产生一个DrawCall,岂不美哉。

所以就有第一种合批的方法:

dynamic batching

动态合批是指在引擎的运行期,将同材质的模型合并为一个大的网格数据传输给显卡。

这种情况,需要耗费CPU来进行缓存的合并,对CPU是有一定影响的。而且由于数据较大,对带宽的要求也更好。

这就是为什么有的小伙伴合批和了半天,运行效率更低的原因。

因为一方面,CPU被拿去做合批运算耗费时间,另一方面带宽占用也变大了。

那么既然运行时合批会消耗CPU,那完全可以将在运行时不需要移动的物体进行离线合批嘛。

(离线合批:在非运行时进行合批。)

于是就引申出了第二种合批方式:

static batching

静态合批下,引擎会帮我们把选择好的网格(Mesh)合并成一个大的网格。

同理会帮我们将网格信息内的uv坐标,物体的纹理等进行重新计算和合并。

这种合并显而易见的好处是不占用运行时效率。

唯一的问题是,如果顶点过多,导致网格太大,那么传输效率就会降低,是一种比较影响带宽的做法。

Instancing

最后呢就是Instancing,既然我们怎么合批都会耗费cpu和带宽,那么我什么不把这些麻烦的事情交给gpu做呢?

毕竟gpu是擅长并行计算的,而绘制多个同样材质的物体本来就是一个并行的过程嘛。

因此驱动组织都提供了可以一次传输,多次绘制的方法,这种我们称为实例化(instancing)

instancing是底层驱动支持的一种特性,在OpenGl内方法一般为在绘制函数后面增加 Instanced

比如:


glDrawArrayInstanced

glDrawElementsInstanced

glDrawElementsInstanced为例可以明显看到他和glDrawElements 的区别


  

void glDrawElements( GLenum mode,

GLsizei count,

GLenum type,

const void * indices);

  

void glDrawElementsInstanced( GLenum mode,

GLsizei count,

GLenum type,

const void * indices,

GLsizei primcount);

可以看到instanced的函数比普通的函数多出一个叫做 primcount参数,这个参数的作用是通知显卡在绘制这些顶点时,重复绘制的次数。

在绘制的shader内,我们可以通过访问 gl_InstanceID 来查看到底绘制到第几个实例了,因为我们每个实例的位置旋转缩放和顶点颜色可能不一样。

当然intancing也不是没有限制的,毕竟驱动商是在迭代的过程中才发现这样的需求的,因此对于低于OpenGL3.0的设备是不支持实例化的。

当然现在低于OpenGL3.x的设备比较少见了,可以比较放心的去实例化方式绘制。

废话不多说我们来看看各种合批的结果吧

(软件为Render Doc)

场景

![没有合并批次](图片描述

没有合并批次的情况下,DrawCall达到了230个

![动态合并批次](图片描述

而在我们进动态合批以后,DC减少到了179个,可以说效果显著。

![实例化](图片描述

当我们可以实例化以后,Instancing减少到了160了! 可喜可贺。

所以从上面的例子中我们可以看出,在渲染同样材质的物体时,我们应该尽量开启实例化,而由于静态合批可以将不同材质的物体合并到一起,因此静态合批实际上是优先级最高的一种合批方式。

如果你的场景中有大量同类物品确不能静态合批,那么可以试试动态合批。

最后我们可以得到如下结论:

静态合批 > Instancing > 动态合批

如何在Cocos Creator中开启batching和合批。

我们只需要在材质内进行勾选就可以了。

开启Instancing

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
92
获赞与收藏
1

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消