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.
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.
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.
- Texture fillrate improved
- Texture loading (4x or more)
- Easy to load
- Not supported on all platforms
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.
- 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:
- How fast you can get the texture off disk and into system memory.
- How fast you can get the texture from system memory to the GPU (via glTexImage2D in your case).
- How much disk space and video RAM storage is in your budget.
- 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.
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.
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).