Changing the GL state is expensive, and it is recommended to draw objects in batches (batch == TextureAtlas == SpriteSheet) to prevent changing the GL state.
Now, everytime you draw an Sprite/Label/SpriteSheet, these functions are called:
-(void) draw {
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
// ...
// drawing stuff
// ...
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
And the 4 glEnable() / glDisable() calls are executed once per sprite.
This 4 states are pretty common in OpenGL. If you want to draw a quad with texture and color, you will have to enable them (it is the most common state in 2D games).
Let's image that you have 50 sprites using the "normal" renderer (not the SpriteSheet). So, you will call 8 * 50 = 400 GL calls. Calling GL functions is expensive, and switching context is expensive too.
So, what I want to do is to use those 4 GL states as the default ones. According to some quick tests that I just did, the performance was increased up to %20 in "normal" sprites.
This change only improves the performance of "normal" sprites. Spritesheets won't be affected so much because the SpriteSheet batches everything in 1 call.
On the other hand, the drawing primitives will be a little bit slower:
- in v0.8 they use just 1 glEnable()/glDisable() and now they will have to use 3. Since they don't use TEXTURE_2D, COLOR_ARRAY and TEXTURE_COORD_ARRAY, these 3 states will have to be disabled before doing the draw, and re-enabled after doing the draw.
But I would like to mention that if your game is "DrawingPrimitives" intensive, then you should not use them... instead I suggest creating a sort of "SpriteSheet" for drawing the primitives.
So, for example, if your custom node only uses TEXTURE_COORD_ARRAY, VERTEX_ARRAY and TEXTURE_2D (like CCLabelAtlas), then you should do:
-(void) draw
{
// default context is:
// glEnableClientState(GL_VERTEX_ARRAY);
// glEnableClientState(GL_COLOR_ARRAY);
// glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// glEnable(GL_TEXTURE_2D);
// let's imagine that you don't need the COLOR_ARRAY. So...
glDiableClientState(GL_COLOR_ARRAY);
// draw your stuff here
glDrawArrays(vertexArray);
// restore the default state
glEnableClientState(GL_COLOR_ARRAY);
I was really impressed by the performance boost in the "normal" sprites, so I would like to apply these modifications.
What do you think ?