Skip to main content
GameDev.net gamedev.net
🔒 Locked

Rendering 2208 2D tiles - Optimization?

Started by Zomgbie Nov 17, 2010 at 5:27 PM 8 replies 4.7k views
Original Post
Zomgbie
Zomgbie
Hello you!

I've been growing more and more fond of game developing and have lately set my goal at creating my very own tile game. Oh, do note; I'm not trying to get an engine going, i just want a platform i can start experimenting with. Anyway!

So, i want 3 layers of tiles, with the size 32x32 at the playfield of 1028x768. That adds up to 2208 tiles that need to be rendered each frame. Currently that works just fine on my computer, but when i switch to something with a little less performance, my fps drop by 99%. This has made me realize that i need to optimize my drawing. Right now im drawing in immediate mode, which i've found out is not the best thing to do. I've been looking into Vertex Buffers aswell, but i'm not really sure what to use since im new at the openGL front.

My question to you is; How should i think when optimizing such a thing?
Omg, zombie! Zomgbie.
karwosts
karwosts
What's your general use case for your tiles? Do you need to move them all independently every frame, or are they relatively static (the terrain)?

You really shouldn't be using immediate mode in any case, but the greatest benefit you'll get from vertex buffer objects is when you don't have to move the tiles and can fire them all in one go.

For each one that needs to move you need to either move the whole buffer or change the vertices which can slow it down.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
dpadam450
dpadam450
Take the player position and divide it by the tile width, that gets you the current tile that the player is on in the x direction (left edge of screen tile). Add 1028/tile width to the left edge tile and you have your right edge tile. Now when you loop over all the tiles in your rendering, only draw if tile_X > left edge and tile_X < right edge (only render tiles you can see)
NBA2K, Madden, Maneater, Killing Floor, Sims 
Zomgbie
Zomgbie
Quote:
Original post by dpadam450
Take the player position and divide it by the tile width, that gets you the current tile that the player is on in the x direction (left edge of screen tile). Add 1028/tile width to the left edge tile and you have your right edge tile. Now when you loop over all the tiles in your rendering, only draw if tile_X > left edge and tile_X < right edge (only render tiles you can see)


Oh, but that's exactly what i do at the moment! :) But it still adds up to a lot of tiles. Seeing as i have 3 layers, each with 32x24 tiles.

Quote:
Original post by karwosts
What's your general use case for your tiles? Do you need to move them all independently every frame, or are they relatively static (the terrain)?

You really shouldn't be using immediate mode in any case, but the greatest benefit you'll get from vertex buffer objects is when you don't have to move the tiles and can fire them all in one go.

For each one that needs to move you need to either move the whole buffer or change the vertices which can slow it down.


The tiles have no need to move, at all, so these Vertex Buffers might be something for me. But i haven't fully grasped the idea behind them. Do i generate one Vertex Buffer for each tile, or just one big fat Vertex Buffer for all my tiles?

Thank you for your answers :)


Omg, zombie! Zomgbie.
TheAverageUser
TheAverageUser
You can use one vertex buffer for all tiles and inject all their vertex data at once. Also, you draw them all at once using a single drawcall. Assuming 10 immediate mode drawcalls per tile (Begin, 4 Vertices, 4 TexCoords, End), you're now going with 22080 drawcalls per frame that could be reduced to something around 3 - 6 using a dynamic VBO (re-filled each frame). Besides the pure function-call overhead you'll also handle the data more GPU-friendly as it comes in batched and doesn't need to be interpreted and optimized by the driver.

Not a VBO expert, though, I'm just switching to them myself. In 2D games, immediate mode still can get you very far, so i sticked to it for years.
Eskapade
Eskapade
Depending on which OpenGL version you use and whether you use shaders, you might want to look for the term "instancing".
It uses the same geometry with different parameters (e.g. transformation matrix), that could optimize your batch rendering aswell.

Some more obvious optimizations would be to sort by texture id (and shader id).
Say, you have 3 textures: grass, concrete, sand.
You will also have a container storing all tiles of a level, sort it by the texture id.
Draw all grass textured tiles first, then all concrete textured tiles, then all sand textured tiles. This saves you a lot of texture rebinding.
Depending on how much your upper layers cover, it could be useful to turn on depth testing and draw the upper layers first, then the lower layers. This could potentially save a lot of fragments (pixels) to be processed because depth testing sorts them out.
If that's not the case, you can turn off depth testing, draw the lower layers first, working your way upward (painter's algorithm).

Hope that helps!
Vilem Otte
Vilem Otte
Definitely use VBO - it is a need if you want good performance. It might also be best to draw them using GL_ARB_draw_instanced - this will though limit you to Shader Model 4 gpus, though most PCs do have them.

Here are specs of extension (part of core from GL 3.0 afaik) - GL_ARB_draw_instanced

It will though get a little more complicated and a little more tricky when you'll want to use different textures in same layer on different tiles.
dpadam450
dpadam450
If you can support VBO's then just put them all in one vbo and give them a 3D texture coordinate and a 3D texture of tiles.

Also, to reduce openGL calls and gpu speed, you can iterate over your objects and draw ones with a certain texture first, that way you don't have to continually send calls to the gpu and the gpu wont have to keep switching textures.
NBA2K, Madden, Maneater, Killing Floor, Sims 
karwosts
karwosts
Why would you use a 3d texture for this? You're not trying to interpolate between two textures.
[size=2]My Projects:
[size=2]Portfolio Map for Android - Free Visual Portfolio Tracker
[size=2]Electron Flux for Android - Free Puzzle/Logic Game
dpadam450
dpadam450
3D textures don't interpolate (it's not mip-mapping). This way you simply have a stack of tiles, and the uv-coord z value determines which sheet/tile of the texture to use (assuming all tiles are the same size).

You might be thinking of texture splatting when you have a separate alpha value and blend between different levels in the 3D texture.
NBA2K, Madden, Maneater, Killing Floor, Sims 

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.