3
\$\begingroup\$

What's the best way to organize small textures in OpenGL—having them all in a big texture and selecting them with texture coordinates, or using individual OpenGL textures?

Until recently, I used to have all textures in a big pixmap and load that into a single texture. This worked well, but in some situations, I had bright pixels from a neighboring texture leak into the edges of a dark texture, so I decided to split the textures up and load them separately. However, since I now had to switch textures quite often, this significantly increased the frame render time.

So I have basically two options:

  • Go with one big texture and find a way to avoid pixel leakage.

  • Go with many small textures and try to avoid texture switches as much as possible (which will put some more load onto the CPU) or to speed them up significantly.

Do you have any suggestions how to achieve this?


Edit: I'm currently using the following texture parameters:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

As far as I can tell, these are already the optimal parameters for what I'm trying to do. However, if there is there anything which I can still improve, I'd be glad for a hint.

\$\endgroup\$
6
\$\begingroup\$

If the textures are the same general "shape" (dimensions, mip levels, etc.) then use texture arrays. You can pack differently "shaped" textures into different arrays if you have any regularity, which you should.

This approach gives you all the advantages of individual textures (e.g., no bleeding) plus all the advantages of a texture atlas (e.g. fewer state changes, bigger batches).

This is how NVIDIA recommends to do pretty much all texturing in modern OpenGL; see the Approaching Zero Driver Overhead GDC talk, particularly the section titled "Packing Textures into Arrays." This is also pretty similar to what Microsoft has recommended for Direct3D programming for years.

Texture arrays are as close as you can get in OpenGL to the descriptor heap/table design of the modern graphics APIs like Mantle or Vulkan or Direct3D 12. If you build your graphics wrapper around the idea of an abstracted texture array storage for all your textures it'll be somewhat easier to port to the new APIs - and actually get moderate efficiency gains from them - when they're out.

\$\endgroup\$
0
\$\begingroup\$

Profiling is always the best choice... But I've liked the combined texture approach the most it makes it easier to deal with trying to minimize swaps because you don't have to :)

You may also want to look at some of the sampling options you selected they could reduce the issue of the neighbor pixels bleeding into other textures.

\$\endgroup\$
0
\$\begingroup\$

Use big texture, it's better.

Avoiding pixel leakage is no that hard: If you can, use GL_NEAREST, else add small empty lines between textures.

\$\endgroup\$
  • \$\begingroup\$ I'm already using GL_NEAREST for GL_TEXTURE_(MAG|MIN)_FILTER, but in certain situations (e.g. when drawing a tile in an isometric perspective), I still get leaking pixels. I'd rather avoid adding empty lines if possible (it looks a bit hack-ish, and other programs seem to get away without it). \$\endgroup\$ – user3426575 Apr 26 '15 at 15:59
  • \$\begingroup\$ @user3426575 Seems strange to me. I only had pixel leakage when I incorrectly computed texture coordinates. \$\endgroup\$ – HolyBlackCat Apr 26 '15 at 17:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.