1

I'm writing a client for a multiplayer tile-based game in libGDX (for Android and Desktop). The game world is composed of thousands of small 32x32 png images that are drawn into a large rectangular view area. The images are downloaded over the socket connection (network) as needed.

What is the best (fastest and most resource-efficient) way to store these images in "memory" so they can be drawn really fast onto the screen when needed?

So far, I have implemented a very naive algorithm that will load each and every 32x32 image into a Texture and keep that in memory indefinitly. (Pure coincidence my images got a size that is a power of two.) It seems to work, but I am worried that this is very inefficient and possible exceeds GPU resources on older devices or something.

I am aware of the TextureAtlas, but that seems to work only for static images that are packed and stored in the compiled android app. As I receive my images over the network dynamically, I believe this won't work for me.

I have found this libgdx SpriteBatch render to texture post that suggest rendering many small images into a FrameBuffer, then using this as a source of TextureRegions. This seems promising to me. Is this a good solution? Is there a better way?

I also wonder if drawing and storing my small images into a large Pixmap might be helpful. Is this possibly a better approach than drawing into a FrameBuffer, as described above? As I understand it from the docs, Pixmaps are purely memory-based. That might be an advantage as it probably doesn't need graphics resources, on the other hand might be slower as loading into a Texture is an expensive operation. Thoughts on this?

Community
  • 1
  • 1
Andreas Vogl
  • 1,776
  • 1
  • 14
  • 18

1 Answers1

1

Actually TextureAtlas is the best way to store many images (small or not) and fortunatelly the TextureAtlas instance do not have to be created in a static way.

Take a look at

    addRegion(java.lang.String name, Texture texture, int x, int y, int width, int height)

TextureAtlas'es method. It make it possible to create atlas dynamically.

So what you should do is to create empty atlas

    TextureAtlas atlas = new TextureAtlas();

then add your images in some kind of loop

    for(Texture texture : yourTexturesCollection)
        atlas.addRegion(...);

then you can use your atlas by using findRegion or another method (take a look at reference)


Notice that for android devices it is recommended to use not larger atlas than 2048 x 2048px.

For another kind of devices (like dekstop) this value can be another (usually bigger). It is not LibGDX limit but openGL's!

m.antkowicz
  • 13,268
  • 18
  • 37
  • Thank you for pointing this out. While using FrameBuffers seems to work reasonably well (already tested that), this looks like an easier solution. – Andreas Vogl Apr 07 '16 at 05:35
  • After looking at the source code of TextureAtlas, I believe it is doing nothing more than storing my thousands of small Textures in an array. This is just my naive implementation hidden behind a nice facade :-) I will continue to use my FrameBuffer implementation, because that does really reduces the amount of Texture objects drastically. – Andreas Vogl Apr 07 '16 at 18:48
  • Actually it is not :) the reason of using textureatlas is to use only one big texture - when you are rendering things the first thing you need to do is to send graphic to GPU what impacts performance. With textureatlas you are sending the texture only once. Google for SpriteBatch's `render calls` – m.antkowicz Apr 07 '16 at 19:15