Reputation: 75
I'm doing a rewrite of a game I've been working on with LWJGL(the original engine was in pure java) and I'm wanting to know the most effective way of rendering the map to the screen. I'm going to make a Tiled map and have a layer each for walkable tiles, collision tiles and stationary objects. All of which I'll be reading into the game by parsing an XML file.
My question is should I do it like this and read each tile into the game individually and store the values into a 2d array, assign them to sprites and render each sprite onto the screen in its respective location? Or would it be less taxing on the CPU/GPU to make these layers their own single picture file and render the layers rather than tiles? I assume the second one would be more of a pain in the ass, but is it worth it?
Upvotes: 0
Views: 1207
Reputation:
It is better to combine the tiles together to form one big texture atlas. Assuming that you use 32x32 pixel tiles, a 2k texture can hold up to 4096 different tiles, potentially way more than enough for a game. The reason is that you can bind this texture once and do (almost) all rendering with it, avoiding the expensive texture switching operation. Do not use separate pictures for each tile. All textures and other rendering resources should uploaded up front, perferably at game load or level load.
As for the actual tiles and objects, you should build a vertex buffer which contains vertex attributes for all objects and upload it during level load too. This buffer will contain vertices positions, colors, texture coordinates... everything you need for drawing the tiles, and it can be splited into multiple buffer if one is not enough. For every frame, you use camera coordinates to find out which tiles are visible and which tiles are not, then issue a draw call with starting index of the first visible tile, and the count of visible tiles. Simple AABB check is pretty good here. Of course, in order to achieve this, your vertex buffer must be laid out in such a way that it only goes in one direction, e.g. left to right and top to bottom.
Alternatively, you can go more for more aggresive vertex count trimming at the cost of a few more draw calls: Splitting the world into chunks such that each chunk is big enough to cover the whole screen. Create vertex buffer for each chunk as described above. Then do the same camera check to find out which chunk is visible and draw them. In this case, you have at least 1 chunk visible and at most 4 chunks visible at any given time, which means 1 to 4 draw calls. This approach is a bit more advantagous than the previous because instead of having to loop over every single tile, you can loop over the chunks which means a lot less checks needed.
If done correctly, you probably won't need more than a handful of draw calls to render the world and be still able to draw a huge number of tiles. Apparently, this this only meant for static objects, you will need to draw dynamic objects differently. Keep it in mind that draw calls can context switching are expensive and should be avoided when possible.
Upvotes: 2