Okay, so I am using C++ with OpenGL, and I am going to create a loader to load in textures for my 3D game. (But the textures are 2D). I want the option of transparency, even if I decide not to use it. I need decent quality, although it doesn't have to be top notch. What do you guys suggest for format (PNG, TGA, etc.). Also, maybe make it something that is easy to create a loader for (I'm not going to use an already created one.). And also, if you have any links/tips to help out with the loader, that would be appreciated.


7 Answers 7


I don't understand why you wouldn't want to use an off-the-shelf loader. PNG, for example, is a good choice for a format but is complex to write a general purpose loader for (and probably not worth the effort of writing one that only loads the specific subset of PNG formats you care about).

Given that somewhat unusual requirement, TGA is probably your best bet. TGA 2.0 has an alpha channel and is relatively simple compared to PNG.

  • 3
    \$\begingroup\$ +1 for TGA if OP wants to write his own. I wrote my own TGA loader once. So quick and painless. \$\endgroup\$ Jul 29, 2011 at 20:37
  • 4
    \$\begingroup\$ @Duck: Painless as long as you're doing simple TGAs without compression or any of the fancy features. If you want a fully compliant TGA loader I've found it's a bit of a pain. It's sort of a strange format. \$\endgroup\$
    – ZorbaTHut
    Jul 29, 2011 at 21:42
  • 1
    \$\begingroup\$ @Zorba, compressions easy enough. Its just whether you care for extensions or not. \$\endgroup\$ Sep 24, 2011 at 4:46

Image texture format is a performance choice too. I recommend you to use compressed textures as much as possible. On mobile platforms, it can improve greatly performance (40% or even more), memory usage and time loading.

Consider a texture 1024*1024:

  • RGB or RGBA (16bits): 2Mo (.5s to load on SGS)
  • RGBA (32bits): 4Mo (1s to load on SGS)
  • PVRT (4bpp): 512ko (.125s to load on SGS)
  • ETC1 + Alpha: 1.5Mo (.4s to load on SGS)

In our games, we have assets (textures) in many formats:

  • DDS format for DXTC textures (Desktop platforms: OS X, Linux, Windows & Tegra)
  • DDS format for ATC textures (Andreno GPUs)
  • PVR format for PVRT format (PowerVR GPUs)
  • PKM format for ETC1 texture (All OGLES 2.0 devices compatibles)

At Last, we use raw format for compatibility but that's for compatibility or GUI elements

  • PNG format for raw texture. It is for RGBA 16, 24 or 32bits textures (we use a MIT licensed loader). It is uncompressed textures.

ETC1 textures have no alpha channel so we use a special shader with two textures (rgb texture and alpha texture). Compressed format are very easy to load (100 or 200 loc).

On desktop, DXTC (S3TC) is present on many cards. So, you shoud use it.

Compressed Textures


  • Texture fillrate improved
  • Texture loading (4x or more)
  • Easy to load


  • Not supported on all platforms
  • artefacts
  • 7
    \$\begingroup\$ There's a big difference between textures that are compressed on the videocard (eg. DXTC) and textures that are only compressed while stored and must be decompressed during loading (eg. PNG). PNG will be slower to load than an uncompressed texture because it must be decompressed first. They are a smaller filesize, yes, but the amount of graphics memory consumed is the same. \$\endgroup\$
    – jhocking
    Sep 22, 2011 at 22:00

Textures are collections of one or more images. This means that a texture could be represented by a TGA or PNG, but neither format is capable of representing all possible features of textures. Why?

Because each one can only hold a single image. There are no mipmaps. There are no 3D textures possible. No array textures. No cubemaps. Each of those files is just a single 2D image. They can be part of a texture, but unless you're not using mipmapping (and I strongly advise against not using mipmaps unless you have specific needs), a single image file in these formats cannot be a texture.

They are fine image formats, but they make poor texture formats.

DDS is the front-runner of texture formats because it actually supports things textures needs. It supports mipmaps and cubemaps. It supports 3D textures. DDSv10 support array textures. You can package a single texture within a DDS in a way that you couldn't with PNG or TGA.

DDS supports uncompressed and compressed texture data. So long as the compressed texture format is one of the DXT/BC texture formats.

PKM is useful for packaging ETC1-compressed images, but like with PNG, it doesn't support actual texture features.

PVR files seem to be the mobile equivalent of DDS (though why they couldn't just use DDS's, I don't know). They support various compression techniques, but they lack advanced DDSv10 features like array textures, as well as 3D texture support.

So DDS wins in terms of comprehensive texture support.

  • 2
    \$\begingroup\$ Speaking purely for features, TIFF supports all the things DDS does and more. Want a texture with far-IR, near-IR, R, G, B and UV channels in addition to Alpha? In 64 bit IEEE floating-point per channel? Compressed by any of a number of algorithms (including JPEG and JPEG2000) as suitable for the channel? With multiple images per file and rich metadata for every single one of them? It can do all of this, and more. It's also the "native" format of Photoshop since some time. Now, as for writing a loader for it ... \$\endgroup\$ Jul 30, 2011 at 10:13
  • \$\begingroup\$ Allow me to add more info about requirement of using only DXT/BC texture format under DDS container; seems it's not the case. I've seen Compressonator using various compression formats and output as .dds for all (can see this hint from help output when execute its cli) and [this](answer) on SO saying that you can use any compression format (setting different FourCC then handle ourselves). \$\endgroup\$
    – haxpor
    Apr 3, 2019 at 10:58
  • 1
    \$\begingroup\$ @haxpor: You can shove whatever you want in a file and call it DDS. The question is, will an application that can read normal DDS files be able to read yours, or will it have to be specially coded to do so? The DDS format only specifies the DXT/BC compression formats (and I suppose ASTC nowadays). What happens if you use another format is between the program writing it and the program reading it. But that's true of pretty much any image format. \$\endgroup\$ Apr 3, 2019 at 13:20
  • \$\begingroup\$ @NicolBolas Thank you for summing it up. I think this is it. \$\endgroup\$
    – haxpor
    Apr 3, 2019 at 13:26

The Khronos Group recommend KTX file format for storing textures for OpenGL and OpenGL ES applications. You can use libktx for working with this format.


  • Instantiate an OpenGL texture from a KTX file
  • Decompress an ETC1 compressed texture image when the hardware does not have ETC1 support.
  • Construct a hash table of key-value pairs from the KTX file as the texture is loaded
  • Write a KTX file from a array of source images and an optional hash table of key-value pairs.
  • Construct and populate a hash table of key-value pairs.

There are a number of considerations here:

  1. How fast you can get the texture off disk and into system memory.
  2. How fast you can get the texture from system memory to the GPU (via glTexImage2D in your case).
  3. How much disk space and video RAM storage is in your budget.
  4. Performance and quality.

TGA is a good choice because in the 24 and 32 bit uncompressed cases you can read the data in one single fread/whatever and send the result directly through glTexImage2D without further processing. It's a bad choice because it can have the largest file size and if disk I/O is a bottleneck then your reads will be slow.

PNG is a good choice because it preserves quality of images with a reasonably small file size. It's a bad choice because PNGs can be slow to decompress - if that's your bottleneck then - well, you know.

JPG is a good choice because it generally has the smallest file size and will come off disk really fast (doubly good if you need to send the file over a network). It's a bad choice because of intermediate software decompression steps and quality loss (although you can tune the quality settings to mitigate this). No alpha channel either.

DDS (or other compressed formats) are good choices because of the smaller file size and the ability to include a prebuilt mipmap chain. If it's a format that's natively supported in hardware (and DDS is natively supported on most consumer PC hardware - has been for a long time too) you get the same benefit as TGA - one fread, a bit of poking in the header to figure out some image properties, then send the data straight through without intermediate steps. Compressed textures will also make your program run faster and use less video RAM. They're bad choices because they use lossy compression (which can sometimes be really noticeable) and may not be supported on all hardware.

If it was me I'd build support for all 4 of these formats (TGA and DDS are quite trivial to write loaders for, with JPG and PNG I'd use an image library) so that content creators can choose the most suitable format on a per-texture basis.

  • 1
    \$\begingroup\$ "DDS is natively supported on most consumer PC hardware" DDS is a container for different formats. You don't pass a DDS file to a GPU, but its contents! \$\endgroup\$
    – Tara
    Mar 18, 2015 at 4:07

It seems like DDS (DirectDraw Surface) is the most popular choice for textures at the moment. Is has different pixel formats, transparency, and compression. It is supported in OpenGL through the GL_ARB_texture_compression extension.

For example, there is an OpenGL loader here.

  • \$\begingroup\$ Your answer is worded a bit confusingly. It makes no sense to say that DDS is supported in OpenGL. OpenGL does not deal with image formats. \$\endgroup\$
    – rdb
    Jul 14, 2016 at 20:24

And of course you can always go with the old 32 bits BMP which is really easy to load (especially if the size is a power of 2 (actually, a multiple of 8 bytes IIRC)).

Otherwise it seems weird that you want only one format, jpg is really cool for nice real-world hi res textures (jpeg does marvels with diskspace and (down)load-times), png for transparency and the occasionnal 32bits BMP for controle-textures (easy to create from a script or a 'quick and dirty' tool).


Not the answer you're looking for? Browse other questions tagged .