How to make drawing with VBO's faster

Started by Cornix, July 14, 2013, 08:33:15

Previous topic - Next topic

Cornix

Hi.

I am currently working on a 2D game. In a benchmark test I found out, that I can draw 60.000 triangles per frame with a frame rate of 25 -30 frames per second.
I was curious whether it was actually the drawing or the game logic behind, so I commented out the drawing part (binding the VBO's and calling glDrawElements) and the frame rate was a stable 30 frames per second for even much higher numbers of triangles. So I am quite sure the drawing is the bottleneck.

I use VBO's with vertex data and indices to draw; the code looks like this:
(This is the part of my code which made the performance difference in my tests by the way)
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, data_vbo_id);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, index_vbo_id);
		
		GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
		GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
		
		GL11.glVertexPointer(3, GL11.GL_FLOAT, vertex_stride, vertex_pointer);
		GL11.glTexCoordPointer(2, GL11.GL_FLOAT, tex_coord_stride, tex_coord_pointer);
		GL11.glDrawElements(GL11.GL_TRIANGLES, number_of_indices, GL11.GL_UNSIGNED_BYTE, first_index_id);
		
		GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
		GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
		
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);

The vertex array buffer has 5 elements per vertex: x, y, z, u, v and 4 vertices. (I draw quads, basically) The data is interleaved.
The element array buffer has 6 elements.

Is there something I am doing wrong with this?
Can I somehow speed this up or make it more efficient?

Thank you for the help.

quew8

Try putting several (as many as is possible / convenient) quads into the same vbo (and their indexes into the same ibo) so you only have to bind them once. Binding takes time, certainly in older hardware.

If you have them all in the same vbo, you can batch the drawing together into 1 (if you are sure to draw everything) or more (otherwise) call to glDrawArrays. Less calls to gl functions the better in general.

You only need to enable and disable the arrays if you are going to be doing some non-vbo rendering later on. Even if this is the case, you can put the glEnable/glDisable around the vbo drawing rather than in each individual draw. Otherwise you can enable it at the start and just leave it. Alternatively look into pushing and poping OpenGL state. Never seen this done with client states but I bet it is possible.

Even after implementing these suggestions, you are going to have to accept that drawing takes time. The simplest and best measure to get performance is to make sure you are only drawing what is necessary - frustum culling, hidden face removal etc.