Hi there!
I am working on ipad app that renders hundreds of sprites (2d images) each frame. I am using modified drawing method taken from sdk's opengl template but problem is, I got only 3fps and I am not even rendering everything I need.
I tried simple optimization methods like using texture atlases, minimizing number of state changes, high level clipping and I even render sprites sorted by common attributes, like color or texture used but it didn't seem to help much. I can't use pvr compression because my images have fine edges and alpha channel that looks terrible when compressed (I use it only on few background images).
I am now trying to use VBOs but I am not sure if they are good for simple sprites (2 triangles). I always thought that they are good for models with larger amount of vertices. I am not even sure how to correctly implement them. I will probably need to save VBO index into my sprite class. Problem is I don't always use class to render sprite, sometimes I just calculate position, size and UV of sprite on the fly (e.g. text rendering). Any ideas if using VBOs with sprite rendering will give some performance boost?
here is my render function:
- (void)RenderTexture:(GLTexture*)tex InRect:(CGRect)dest WithUV:(CGRect)uv Color:(LSColor*)color Effect:(SpriteEffect)effect Rotation:(float)rot AroundPoint:(CGPoint)rotCenter {
if(tex.ID != mLastBoundTexture) {
[tex bind];
mLastBoundTexture = tex.ID;
}
mSquareVertices[2] = mSquareVertices[6] = dest.size.width;
mSquareVertices[5] = mSquareVertices[7] = dest.size.height;
mSquareUVs[0] = mSquareUVs[4] = uv.origin.x;
mSquareUVs[1] = mSquareUVs[3] = uv.origin.y;
mSquareUVs[2] = mSquareUVs[6] = uv.origin.x + uv.size.width;
mSquareUVs[5] = mSquareUVs[7] = uv.origin.y + uv.size.height;
mSquareColors[0] = mSquareColors[4] = mSquareColors[8] = mSquareColors[12] = color.red;
mSquareColors[1] = mSquareColors[5] = mSquareColors[9] = mSquareColors[13] = color.green;
mSquareColors[2] = mSquareColors[6] = mSquareColors[10] = mSquareColors[14] = color.blue;
mSquareColors[3] = mSquareColors[7] = mSquareColors[11] = mSquareColors[15] = color.alpha;
mat4f_LoadTranslation2f(rotCenter.x, rotCenter.y, mModelViewMatrix);
mat4f_LoadTranslation2f(dest.origin.x, dest.origin.y, mModelViewMatrix);
mat4f_MultiplyMat4f(mProjectionMatrix, mModelViewMatrix, mModelViewProjMatrix);
if(mLastUsedShader != effect) {
int program;
if(effect == SENormal) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
program = mShaderNormal;
}
else if(effect == SEMultiply) {
glBlendFunc(GL_DST_COLOR, GL_ZERO);
program = mShaderMultiply;
}
else {
NSLog(@"Implement SpriteEffect %i", effect);
}
glUseProgram(program);
mLastUsedShader = effect;
}
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEW_PROJECTION_MATRIX], 1, GL_FALSE, mModelViewProjMatrix);
// Update attribute values
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, mSquareVertices);
glVertexAttribPointer(ATTRIB_UV, 2, GL_FLOAT, 0, 0, mSquareUVs);
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, 1, 0, mSquareColors);
glUniform4fv(uniforms[UNIFORM_POSTPROCES_PARAMS], 4, mPostprocessParams);
// Draw
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
I think that color could be another area of improvement, because it doesn't change very often (few times per frame) but I don't how to set it for longer than just current render call.
Do you see any other areas where I can improve my framerate? I really need to get this at 30fps at least
EDIT: turns out I had way too complicated fragment shader. I feel stupid for not disabling it to test it. Looks like I will have to say goodbye to my desaturation feature. With default fragment shader I can easily get over 60 fps.