The main difference between a CCSpriteBatchNode
and a normal CCSprite
is the fact that a CCSpriteBatchNode
sends all the data of all the sprites at once to the GPU instead that doing it for each sprite.
A CCSprite
draw call works in the following way:
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Basically 3 calls are made to set the data of the sprite and then a call to glDrawArrays
is done. If you have 100 sprite this code is executed 100 times.
Now let's look at CCSpriteBatchNode
(I chose the implementation without VAO, which is another possible optimization):
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices));
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors));
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffersVBO_[1]);
glDrawElements(GL_TRIANGLE_STRIP, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(indices_[0])) );
Now this code sets all the data of all the sprites at once, since it's stored in contiguous memory. This call is the same for 1, 10, 100, whatever amount of sprites.
That's why it is more efficient, but at the same time, since the data is stored contiguosly in memory, when a child is removed or added or modifiyed, the array must be changed accordingly and updated in the GPU. That's where the cost of adding and removing comes from (or even the fact that a hidden CCSprite just skips the rendering phase while a hidden CCSprite in a batch node doesn't)
From personal experience I can tell you that the cost is usually negligible and you should always use a CCSpriteBatchNode
when you can (since they have their limits, like blending over the whole node and not on a per sprite basis and similar things) and when you are drawing more than a bunch of sprites of the same kind/reason.
Benchmarking it for your self should be easy though.