user328517
user328517

Reputation: 111

Optimized 2D Tile Scrolling in OpenGL

I'm developing a 2D sidescrolling game and I need to optimize my tiling code to get a better frame rate. As of right now I'm using a texture atlas and 16x16 tiles for 480x320 screen resolution. The level scrolls in both directions, and is significantly larger than 1 screen (thousands of pixels). I use glTranslate for the actual scrolling.

So far I've tried:

Any advice is appreciated, but in particular I'm wondering:

Thanks :)

Upvotes: 11

Views: 7889

Answers (1)

elmattic
elmattic

Reputation: 12174

Here's how I would do for coding a fast 2D tile engine:

First I would make a clean separation between dynamic tiles (characters, items..) and static ones (level).

Static Tiles:

For drawing the static ones (tiles that build up the whole level), I would use a static buffer (stored in a buffer object) that contains each tile position (x, y, layer) and an index to the atlas texture data (i). Since your texture atlas contains fixed-size tiles of 16x16 pixels, you could easily compute in the vertex shader texture coordinates for each vertices.

For drawing the level I would use a single draw call (using instancing) of a triangle strip forming a quad, vertex data is stored in a static VBO (made of 4 vertices) and index data in a static IBO (made of 4 indices), using per instance values for computing vertices attribute in the vertex shader.

This would give you almost "free" tile culling done on the GPU, since clipping hardware is very fast. Even if you have big number of tiles in your level, let's say 30*20 (tiles/in a screen), and about ~50 screen/level, it would make 30,000 tiles. I think it's still acceptable (even on low-end GPUs. BTW, are you targetting iPhone/Android? If yes instancing/shaders are not available on OpenGL ES 1.0 and OpenGL ES 2.0 has no instancing support but can do shaders, so you will have to explode tiles instance data in a VBO/ IBO, and use GL_TRIANGLES. You can explode less data and spare GPU memory, computing vertices attributes in a shader).

In any case you'd better not to duplicate texture tiles data and keep a texture atlas and a VBO and IBO.

Dynamic Tiles:

I would use a dynamic VBO (and an static IBO representing GL_TRIANGLES so 0,1,2, 2,1,3, 0+4,1+4,2+4..,) representing tile positions, texture coords, layers and update it with visible dynamic tiles in a screen via glBufferSubData and draw thoses tiles via glDrawElements.

Of course this means that you have a maximum number of dynamic tiles that you can draw per glDrawElements, so if you bump into this limit you'll have to do a second update/draw of the VBO.

If your OpenGL implementation has no support for VBO/IBO (like in OpenGL ES 1.0) use VA instead. I don't recommand usage of DL or immediate mode (no support for it on OpenGL ES).

Finally, use glOrtho for moving your camera across the level, zoom in/ zoom out etc. Good luck!

Upvotes: 10

Related Questions