OpenGL Create atlas runtime?

So, I set up my framework in a neat little system to combine SDL, openGL and box2D together for a 2D game.

Now, how it works, I create an object of the GameObject class, set the "source PNG", and then automatically create the openGL texture and the box2d body with the same dimensions.

Now I'm worried about whether I'm starting to draw a lot of different textures on the screen.

Is it possible to load all sprite sheets at runtime and then group them together into a single texture? If so, how? And that would be a good way to implement it (so that I would not have to manually specify any parameters or something else).

The reason I want to do this at runtime, and not in advance, is that I can easily load together (or most) of tiles, enemies, etc. a certain level in this one texture, because each level will not have the same enemies. It will also facilitate the process of creating all art.

+4
source share
1 answer

There are probably some libraries that already exist for creating texture atlases (optimal packaging is a non-trivial problem) and converting old texture coordinates to new ones.

However, if you want to do this yourself, you would probably do something like this:

  • Download all textures from disk (your "source PNG") and extract the raw pixel data buffer,
  • If necessary, convert all the original textures to the same pixel format,
  • Create a new texture large enough to hold all existing textures together with the appropriate buffer for storing pixel data
  • "Blit" the pixel data from the source images to a new buffer with a given offset (see below).
  • Create the texture as usual using the new buffer data.
  • In this case, determine the mapping from the "old" texture coordinates to the "new" texture coordinates (it should be a simple matter for recording offsets for each element of the texture atlas and performing a quick conversion). It would probably also be fairly easy to do this inside the pixel shader, but it would take some profiling to see if the overhead of passing additional parameters is worth it.

Obviously, you also want to check to make sure that you are not doing something stupid, like loading the same texture into the atlas twice, but this is a concern that is outside of this procedure.


To "blit" (copy) from the source image to the target image, you would do something like this (assuming you copy the 128x128 texture to a 512x512 atlas texture, starting from (128, 0) on the target):

unsigned char* source = new unsigned char[ 128 * 128 * 4 ]; // in reality, comes from your texture loader unsigned char* target = new unsigned char[ 512 * 512 * 4 ]; int targetX = 128; int targetY = 0; for(int sourceY = 0; sourceY < 128; ++sourceY) { for(int sourceX = 0; sourceX < 128; ++sourceX) { int from = (sourceY * 128 * 4) + (sourceX * 4); // 4 bytes per pixel (assuming RGBA) int to = ((targetY + sourceY) * 512 * 4) + ((targetX + sourceX) * 4); // same format as source for(int channel = 0; channel < 4; ++channel) { target[to + channel] = source[from + channel]; } } } 

This is a very simple brute force implementation: there are much faster, more concise, and smarter ways to copy an array, but the idea is that you basically copy the contents of the original texture to the target texture for a given X and Y are offset. As a result, you will create a new texture containing the old textures in it.

If the math of indexing does not make sense to you, think about how the 2D array is actually indexed inside the 1st space (for example, in the computer's memory).

Please forgive any errors. This is not production code, but instead of what I wrote, without checking whether it compiles or runs.


Since you are using SDL, I have to mention that it has a nice function that can help you: SDL_BlitSurface , you can completely create SDL_Surface inside the SDL and just use SDL_BlitSurface to copy the original surfaces into it, then convert the atlas surface to a GL texture .

He will take care of all the maths and can also do the format conversion for you on the fly.

+5
source

Source: https://habr.com/ru/post/1403795/


All Articles