I’ve implemented a particle engine for a game for iPad. On the iPad Simulator I get a very good framerate with >500 particles (way more than I need). On an iPad itself however, I get completely different results. With just 10 particles (I need a few more than that) I only get a very poor framerate…
As a basis I’ve taken this tutorial to implement my Particle Emitter class: http://www.71squared.com/en/article/806/iphone-game-programming-tutorial-8-particle-emitter
(uses OpenGL ES 1)
Because I use OpenGL ES 2.0, I wrote my own render method:
- (void) renderParticles:(RenderMode)renderMode ofParticleEmitter:(ParticleEmitter*)particleEmitter xOffset:(int)xoffset yOffset:(int)yoffset
{
PointSprite *vertices = [particleEmitter getVertices];
for (int p = 0; p < particleEmitter.particleCount; p++) {
CC3GLMatrix *modelView = [CC3GLMatrix matrix];
// Translate the Modelviewmatrix
[modelView populateFromTranslation:CC3VectorMake(_cameraX, _cameraY, -5.0)];
[modelView translateByX:vertices[p].x + xoffset];
[modelView translateByY:vertices[p].y + yoffset];
[modelView translateByZ:101.0];
[modelView scaleByX:2.0];
[modelView scaleByY:2.0];
glUniformMatrix4fv(_modelViewUniformT, 1, 0, modelView.glMatrix);
glBindTexture(GL_TEXTURE_2D, [particleEmitter getTexture]);
// Create and Bind a rectangular VBO
[self calcCharacterVBOwithCols:1 rows:1 currentCol:1 currentRow:1];
glVertexAttribPointer(_positionSlotT, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) 0);
glEnableVertexAttribArray(_positionSlotT);
// Fragment Shader value
float opacity = 1.0;
glUniform1f(_opacity, opacity);
// Normal render, add Texture coordinates
// Activate Texturing Pipeline and Bind Texture
glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));
glEnableVertexAttribArray(_texCoordSlot);
glDrawElements(GL_TRIANGLES, sizeof(IndicesLayer)/sizeof(IndicesLayer[0]), GL_UNSIGNED_BYTE, 0);
glDisableVertexAttribArray(_texCoordSlot);
glDisableVertexAttribArray(_positionSlotT);
[self destroyCharacterVBO];
}
}
Did I miss some essential point on particles? What can I do better to get a better framerate on the device?
The problem seems to have been assigning the particle texture again and again for every single particle even though they all use the same texture.
So by binding the texture
before looping over all the particles I get a much faster frame rate that is comparable to the simulator.