cocos2dx

cocos2dx的合批

cocos2dx 3.x跟当年我用的cocos2dx 2.x在熏染上做了很大的改动。已经默认使用了自动合批的方式,简单做了一个实验,在屏幕上绘制3000个精灵,并进行随机移动:

 

1)第一种方式是每一个sprite都源自一张独立的图片,不合批,代码和数据如下:

cocos2dx_batch_2 cocos2dx_batch_3

 

2)第二种方式,使用TexturePacker 将以上图片合并,代码和数据如下:

cocos2dx_batch_4 cocos2dx_batch_5

 

可以看到两者的Draw Call 和帧率差距比较大。这种变化正是cocos2dx合批带来的。我们知道一个批次(batch)是指一次GPU的绘制调用,CPU把顶点送入GPU,同时也会进行一次渲染管线的状态切换,这个过程是比较耗时的。因此需要尽量减少渲染过程中的批次,减少状态切换数量。cocos2dx的做法就是把相同材质的Sprite合并成一个批次。具体做法我们来看一下代码(cocos2dx 3.11):

当我们绘制一个Sprite时,在Sprite::draw函数中,会去初始化一个渲染命令(TriangleCommand):

而在初始化的过程中,会生成一个材质ID:

我们看到,这个材质ID,是由shader对象指针,贴图ID,混合选项参数,这几项哈希得来,也就是说,这些参数相同的Sprite,会生成相同的材质ID。

而在最后绘制的时候:

相同材质ID的三角形会被合并到一起,然后同时送入GPU,从而达到合批的目的。所以在上面的例子中,所有Sprite的shader和混合参数都是相同的,如果他们用同一张贴图,哪就会满足合批的条件,所以把所有精灵的贴图合成一张,就可以把3000个sprite合成一个批次。加速渲染。

在cocos2dx的实现中,有几个问题需要注意:

1)它只会把相邻的两个Sprite合并到一起,所以尽管在分散图片的例子中,有很多sprite使用了相同的贴图,但是它们的渲染次序没有相邻,所以也不会合批。所以每帧会有3000次draw call。

2)如果要渲染的Sprite使用了自定义的Shader,如果Shader存在Uniform参数,也不会进行合批。

2 thoughts on “cocos2dx的合批”

  1. 你好,
    我在網路上看到”用Shader绘制攻击范围的圆环”這篇文章,
    在使用了你提供的Shader卻達不到範例圖的效果,
    正確的說應該是繪製不出圓環的效果,
    想請問是否有什麼我應該注意卻沒注意到的問題?

发表评论