2
votes

Consider a 2D simulation with the following properties:

  • Entities fill the screen and move around, and sometimes die and disappear
  • Every entity has a unique, procedurally generated set of textures as its "sprite". Given the procedural nature, the textures are generated at runtime. The chance of any two entities having the same texture is extremely low
  • A maximum of 5,000 entities will ever exist at once on the screen (there is no max to the number of entities that can exist in any given playthrough - when they die, the memory is freed)
  • The sprites should be drawn back to front so foreground entities overlap entities "behind" them.
  • The sim is compatible with OpenGL 3.0
  • GL_MAX_TEXTURE_SIZE is 2048 for compatibility with older mobile devices
  • Textures have transparency, so a z-buffer would not work for draw order

If I am not mistaken, there are two general approaches to this problem:

  1. Dynamically update a texture atlas with each entity's newly generated texture at runtime. When an entity dies, remove its textures too leave blank space for new ones. The advantage here is that you only need 1 draw call. The disadvantage is that the texture atlas makes the system impossible. If you have a 2048x2048 atlas and your sprites are 64x64, you can only generate 1024 sprites before you run out of space. If each entity consists of 5 sprites for animation purposes, only around 200 entities could exist at any one time. You also have to continually update the texture at runtime.
  2. Create an individual texture object for each individual enemy and do a draw call for each one. The advantage here is that you can continually create new textures as much as you want (within memory limits). The disadvantage is obviously the potentially huge number of draw calls (up to 5,000 for the entities alone, not including background textures, etc.)

So #1 seems to be completely out of the question. Is #2 the only way to accomplish this, or is there a better method I haven't considered?

2
How about using texture arrays?Reto Koradi
With 256 max texture layers, texture arrays may actually work in conjunction with method #1. That's still a lot of writing to textures, but may not be that bad...I'll have to test before answering the question.Elden Abob

2 Answers

0
votes

You can just use several atlas and still draw in a single call by having an additional vertex attribute (or a 3D texture coordinate) that tells the shader which atlas to use.

There are several options :

  • Use Array Texture or 3D textures.
  • Bind them to different texture units (you get at least 16 IIRC from OpenGL 3.0)

Array Textures is probably the most elegant solution and it's core in 3.0.

0
votes

It is not obvious from your description why #1 is out of question. It is the usual way of drawing multiple small sprites. You are not limited to 1024 sprites, as you could create more than one atlas. Even when batching 200 entities at a time, you'll do a lot better than drawing them one by one. The mechanism by which you generate the sprites seems important, though. If you update the whole atlas each frame, you will probably want to do something else.