How can I improve my rendering? (VAO/VBO)

(First, sorry for my bad english, I’m brazilian :/)

Good afternoon,

Well, I’m learning OpenGL/LWJGL right now, and I’m developing a little 2d game:

http://puu.sh/8uVzJ.png

My problem is, even it’s a 2D game, with 12 entities on my map, I’m having only 30 FPS. Yes, it’s a crappy 2009’ notebook with Intel on-board graphics and a simple dual-core CPU, but the same way, 30 FPS is sooo little for a 2D game.

So I’ve been reading some tutorials, articles, topics and etc about Sprite Batching, VBOs and VAOs, but I couldn’t get it well. My rendering class right now is an edited Tessellator-class taken from Minecraft, used for testing and learning purposes only.

The class “Tessellator” right now:

http://www.java-gaming.org/?action=pastebin&id=909

Aand the “VertexObject” class used in Tessellator:

http://www.java-gaming.org/?action=pastebin&id=910

(Methods like hasColor(), getColor(), hasTexture(), getTextureUV(), etc, are all from sub-class Tessellator, but I’m sure they doesn’t matter here.)

So, how can this be improved? I know there’s a better solution for glXPointer, but even reading a lot I can’t put it on practice.

Thanks in advance.

If you are only using static images/tiles, you can use DisplayLists
Basically what it does is to pre-process your opengl vertices/normals etc.
So instead of letting opengl process everything realtime(every frame), DisplayLists computes it at startup.
BUT
If you have any animations, you should not use DisplayLists.
As DisplayLists only support static data.

You can also use VAO/VBO, but Display Lists are easier to setup.
And it can also be faster on older computers(at least in my experience)

TODO:

  • Create a Display list for every texture/tile
  • Use DisplayList instead of vertives (glBegin & glEnd)
  • Done! :smiley:

Take a look HERE or HERE for an example.
Or you can search google for Examples/Tutorials :slight_smile:

First things first, profile it. Run with -Xprof, let’s see the output.

Cas :slight_smile:

@orogamo:
Yes I’ve already seen the display lists, but the problem is: I have some animated tiles. But I’ll try it, like rendering all static tiles via display lists and after, draw animated tiles separated, but I still think that the problem isn’t the tiles itself, but yes the entities, and the entities are always in movement and changing sprites so display lists won’t work :confused: Anyway, thanks.

@princec:
Hey there, my -Xprof log result: http://www.java-gaming.org/?action=pastebin&id=911

As you can see, my org.shura.rpg.game.map.MapPhysics.detectTerrainIntersection is taking 15% of the time, but I still don’t think this is the main issue (yeah, today I’ll try to modify some things on it). GL.drawArrays is using 24%, and java.util.zip.Deflater.deflateBytes (wtf?) is using 13%.

There’s too much noise in that output… would you run it for maybe 5 minutes and then let’s see the output again. Any startup code will be pushed out of the way then and we’ll see what’s really going on. Though right now yes, glDrawArrays is definitely your bottleneck, followed by your collision algorithm.

Cas :slight_smile:

Hey there,
Just saying, probably tomorrow I’ll post it, because I upgraded from Win7 -> Win 8 and Intel haven’t published the drivers for my graphics board, so yea it’ll take some time 'til I be able to re-open my game.

New log (around 4 minutes of execution):
http://www.java-gaming.org/?action=pastebin&id=912

Right, that’s much more clear.

There are two areas you can optimise then: the first one is the number of calls you are making to glDrawArrays - why so many? And secondly that detectTerrainIntersection method is suspiciously slow.

So, what are you drawing with each call to glDrawArrays? You’re not drawing single sprites are you?

Cas :slight_smile:

Erm… hm… well… yeah, I’m drawing each sprite separately :// I’m very newbie on OpenGL, started learning like 1 month. I don’t know how to name it correctly, but the Tessellator class is something like “vertex array immediate mode”, isn’t it?

Btw, the detectTerrainIntersection was my fault, I was calling it for each entity, each tick. Now I’ve made some ‘cached collisions’ workaround and it’s working great, not even getting 4% on profilling.

So yeah, the problem is my stupid Tessellator class with immediate mode for every block and every entity on world, since I still am not that experienced to do something like Sprite Batching.

@Edit: Oh, and glBindTexture is taking 8%… another problem from immediate mode.

Well, there’s 3 things you need to do:

  1. Pack all your sprites into texture atlases. Plenty of information around about how to do this.
  2. Sort your sprites according to rendering state needed, eg. blend mode, texture binding
  3. Batch all your sprites up into groups with the same rendering state, writing indices out to an index array, and use glDrawElements to draw, say, 100 sprites in one go, rather than 100 calls to glDrawArrays.

Stop using that tesselator thing.

Cas :slight_smile:

Hello, and thanks for answering me, I know how boring this can be.

Well, I’ll follow your tips ^^. Just wondering, when you say writing indices out to an index array, it’s something like the method ‘addVertex’ here http://www.java-gaming.org/?action=pastebin&id=910? If yes, is it possible to configure more vertex properties, like brightness and etc using this array? (As I’ve seen, Minecraft have block brightness, and they are set on the arrays sent to glDrawArrays too.)

Well, you know how you’re doing glDrawArrays() and pointing it 4 vertices in a row each time?

Instead, write out all the vertex indices into a big int[] array:
{1,2,3,4,5,6,7,8,9,10…}

and then call glDrawElements() using that array. It joins up the vertices in order, each index points at a vertex. As yours are all conveniently in order (probably as quads, yes?) then your int array will indeed look like that example above, with 4 indices per quad.

Cas :slight_smile: