cocos2d-x 3 batch drawing explained

I have read [this page][1] to understand batch drawing details, but I still have questions. I know that in order to reduce draw call number we need to use batch drawing. I use it like this:

auto spritebatch = SpriteBatchNode::create(“ingame.png”);
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(“ingame.plist”);

And now I need to create a Sprite I have to do this:

auto backgroundSprite = Sprite::createWithSpriteFrameName(“back_gradient.png”);
    spritebatch->addChild(backgroundSprite);

But I don’t understand the following things:

1. What if my game has several spritesheets. For example I have HUD spritesheet and ingame spritesheet. Now if I want to show ingame screen with HUD then I need to create 2 SpriteBatchNode? and add them into ingame layer?
 2. What if the same spritesheet should be used in different Scenes. Should I do the following again?

auto spritebatch = SpriteBatchNode::create(“ingame.png”);
    SpriteFrameCache::getInstance()->addSpriteFramesWithFile(“ingame.plist”);

3. What if I use sprites with Button, TextEdit, Label and other UI elements.
     - First of all can I initialize Button state images from spritesheet?
     - As I know I cannot add UI element as a child to SpriteBatchNode. In this case how to combile UI elements and sprite in the same view/scene?

Sorry for lots of questions. But the fact is that I could not find any resource that contains the explanations to this questions. While they are all related. If you don’t know answers to these questions, you don’t know how to use SpriteBatchNode.

[1]: http://www.cocos2d-x.org/wiki/Texture_Cache

1 Like

with v3 I don’t think you need to really use SpriteBatchNode anymore. When Sprites are first created if they aren’t in the cache they are added at that point. If you call for a sprite and it is in the cache then it gets read from there.

1 Like

Hi @slackmoehrle,
Saying about Sprite will be cached automatically in Cocos2d-x v3. I have a question about a custom sprite such as A subclass of Sprite with a cocos2d::Label as it’s child. If I have a hundred of that sprite on screen, are they cached or re-alloc for each?

1 Like

@slackmoehrle You can reduce draw calls. If you have 7 different images, on the screen as sprite then you have 7 draw calls, whereas, if you use a spritsheet you have only one draw call for 7 different images. You don’t need only if you draw the same image multiple times, because after the first time it is in the cache already.

Also if you don’t use spritesheet how you should do the frame by frame animations? I have seen that it is done using spritesheets only in cocos2d-x.

While spriteBatchNodes are still supported, v3 introduces automatic quad batching through a unique render command called QuadCommand.

To clarify what this batching mainly achieves:

  • all quads in one VBO so binding of mesh data happens only once for a batch
  • sorting into material groups to minimise texture/shader binding (big performance gains by minimising pushing the same texture to the GPU multiple times per frame)

To further understand the new render pipeline:
http://www.cocos2d-x.org/wiki/Renderer
http://www.cocos2d-x.org/wiki/Cocos2d_v30_renderer_pipeline_roadmap
There are also numerous posts on this forum regarding it’s design.

You can find out if a cocos2d-x type supports this caching method by looking at it’s draw() implementation and what command it pushes onto the render queue.

In v2 this batching achieved by intercepting the draw call for sprites under a batchnode but would seriously limit the structure of your scene hierarchy.

If you are for some reason wanting to continue using v2:

  1. yes you will need a separate SpriteBatchNode for each texture/shader combination

  2. while you may need to create new SpriteBatchNodes for each scene, unless explicitly released, resources in SpriteFrameCache and TextureCache will not require reloading, although it’s usually a good idea to call addSpriteFramesWithFile just incase. If the frames are already loaded in the cache it will not load them again.

  3. Since Widget does not derive from Sprite it cannot be added to a SpriteBatchNode. If you wanted objects to transform together either sacrifice batching or have one match the transform of the other in the same space.

While documentation for cocos2d-x is somewhat messy it is worth reading through the wiki
http://www.cocos2d-x.org/wiki/
And the code itself is usually commented well, not to mention being open source mean you can ultimately read exactly how anything works line by line.

Hope this helps

My conclusion about this is as follows: I should use spritesheets to cache whole set of images and also for creating animations, but I don’t need to use batch node. Batching is being done automatically. Correct?

I’d say correct!

Well, By examining the renderer source code, I have found that the renderer use a lot of branching to sort the right combinations of texture/material before rendering each batch with one draw call, a SpriteBachNode even in cocos2d-x3 will be a lot more efficient, and by profiling a simple demo I reached the same conclusion…
So my recommendation is to continue using SpriteBatchNode… I have modified my implementation of cocos2d-x SpriteBatchNode to make it even more faster and more direct…

Really, how many % SpriteBatchNode better?

If you’ve modified SpriteBatchNode for better, you should submit a pull request to help improve the engine

@Packora you should either submit a pull request or submit an issue so that developers could understand what you have done. It seems you have done a great job, and we don’t wont to lost the hours you have invested on that problem. Let it be useful for the community. BTW not it is especially important cause I have read that Cocos2d-x v4 should have a new rendering mechanism. You can help them make the new one really-really better. v4 should be out at this summer so go ahead and communicate with cocos2d-x devs.

2 Likes

I have profiled using the “CCProfiling” utility 45 moving sprites, each one of them has a size of 150x150, and the results was the following :

Automatic batching:
visit -> 410u;
render -> 196u;

VS

SpriteBatchNode:
visit -> 380u; (7.3% faster)
render -> 145u; (26% faster)

Profiling took 2 minutes, I used cocos2d-x v3.3, and the standard SprieBatchNode, the test was done on a android tablet…

3 Likes