0
\$\begingroup\$

I have done my research on DDS/DXT compression, and the information is kind of "everywhere." It is rather difficult to even find good, organized, sensible information on color depth. However, it is apparent that DXT5 changes the image to... RGB565?

Alright, so I am restricted to 16 bit color and RGB565. Makes sense. I also read that converting it yourself, choosing the colors in the image, can stop or even entirely prevent loss of detail.

Nvidia's Photoshop plugin seems to degrade the quality to something much worse than other programs are capable of when converting an image to RGB565.

In particular, I use an absolutely wonderful tool which allows me to choose the colors. I altered my image to actually only include 128 colors. This is less than the 256 allowed by RGB565.

However, Nvidia's Photoshop plugin seems to ignore those colors, and chooses its own- as if I never changed the image in the first place. It's identical to what it was if I convert it to DDS from 24 bit Truecolor.

Why is Nvidia's tool not keeping my color table? Why is it still lossy, and significantly worse at Nvidia's 256 colors, when my 128 color version is so superior and loses no quality or detail?

Currently, I am using "COLOR QUANTIZER", which is the best tool I have found to lower the number of colors without losing image quality.

I might be a little confused, as apparently TexturePacker's RGBA5555 is 20 bit and unsupported in a lot of frameworks, which confused me thinking RGB565 and RGBA5555 were both 16 bit. (Dur! The non-existence of RGBA5555 in google threw me off bigtime.) However, I assume I could easily achieve RGBA4444 (16 bit with alpha) because my colors can degrade in COLOR QUANTIZER to 128 colors, and RGBA4444 supports 256 colors. When I use TEXTUREPACKER or other programs, it is worse quality than in COLOR QUANTIZER. This program is simply superior in my experience, and I have been obsessive with all tools available to find the best one.

My images: PNG with pre-multiplied alpha. Can degrade to 128 colors, in COLOR QUANTIZER, before losing any quality. Alpha is a very big requirement, so RGB565 and DXT1 are out of the question. These are small sprites, which are smaller than 100x200.

My Goal: Low memory consumption and compression. Obviously, the best way to handle this would be DDS/DXT5 so I can keep the textures compressed in memory. Although I could handle RGBA4444, it is only a 2:1 compression, while DXT5 is 4:1. I would much prefer to use the DDS format.

\$\endgroup\$
  • \$\begingroup\$ I have now read that DX10 supports BC5, which is even better for normal maps. I am not opposed to switching to DirectX10 instead of OpenGL, if it means higher quality images and better compression. \$\endgroup\$ – Carter81 Sep 15 '13 at 14:27
  • \$\begingroup\$ Have you considered using multitexturing, keeping your color and alpha channels in separately compressed textures, with this method you could theoretically pack a normal map into the other 2 channels of the "alpha" texture and use DXT for both, or just use a smaller image format with only one channel for alpha \$\endgroup\$ – MickLH Sep 15 '13 at 15:30
  • \$\begingroup\$ How would I go about that? I have never heard of this technique before. \$\endgroup\$ – Carter81 Sep 15 '13 at 15:51
  • 1
    \$\begingroup\$ RGB565 is not 256 colors. it's 2^(5+6+5) = 2^16 colors (256 is just 2^8) \$\endgroup\$ – Sarge Borsch Jan 13 '16 at 12:54
1
\$\begingroup\$

It may sound like DXT5 uses RGB565 palette, but in fact this is a bit more complicated. Image is being split into small blocks and in each block DXT picks 2 colors to be stored in RGB565 format, also 2 colors are interpolated and these ones can be RGB888 (if you take two neighbor 565 colors and 2 in between).

It looks like COLOR QUANTIZER that you mention picks best 128 colors, so the quality loss is not noticeable. DXT on the other hand has one major limitation - it can pick only 2 colors per block of 4x4 pixels. That mean that if you e.g. have a small rainbow and R G B colors in one block, only two colors will be preserved and third will be dropped. Example I could find, original is on left, notice how due to bad colors the right image has blocks of red chipped:

enter image description here

Usually that does not happen with large images, because they tend to have less colors transitions in small areas, but if you use pixel-art it damages it a lot.

There is another issue (at least it was true in 2008) with nvidia compression tool. It picked unoptimal pair of RGB565 colors for the block of pixels. E.g. if I compressed a logo on pure almost white background (254,254,253) even when there were blocks of solid color they all were replaced with a different greenish tint (250,254,249). So you might look for a different compression tool if quality "almost" satisfies you.

The fact is however, that you need to test the options you have and pick the one that suits your situation best. It may be DXT, or it could be S3TC or something else. Just see what options SFML offers you and start trying them out!

\$\endgroup\$
  • \$\begingroup\$ S3TC and DXT are the same format. In particular S3TC is DXT1. \$\endgroup\$ – Mokosha Feb 17 '16 at 22:24
2
\$\begingroup\$

Err, you've got confused somewhere. Both RGB565 and RGBA4444 support exactly 65536 colours, and there's no colour palette used. If you ignore alpha then RGB4444 only stores 4096 colours, which generally isn't very useful.

DXT1 supports more colours than that because it can interpolate between two 565 colours. However in any 4x4 block it only supports four different colours (two 565 ones, and two interpolated ones). That can cause nasty compression artefacts on small detailed images, but will generally work well on a texture for a 3D object.

DXT5 does the same thing with the colour channel as DXT1, but also supports an alpha channel on top, which has better precision than the colour channel. It's also double the size of a DXT1 image.

It might be helpful if you posted an example of a problematic image, before and after compression.

If you want to store a palletized image, then you'll need to store the image data in an 8-bit texture format, and the palette separately as an RGBA image. You can then combine them in the fragment shader.

\$\endgroup\$
1
\$\begingroup\$

Step 1: Load your color and alpha images into two different OpenGL textures.

Step 2: Use glActiveTexture to switch to between and bind both color and alpha to GL_TEXTURE0 and GL_TEXTURE1.

Step 3: In your fragment shader, define texture samplers for color and alpha, and use the right one to get the right channels in your shader.

Step 4: Set "color" and "alpha" uniform variables using glUniform1i to 0 and 1, for textures 0 and 1.

This will let you pick different memory layouts for color and alpha, and should still save memory over a standard 32-bit, while providing perfect alpha gradients.

\$\endgroup\$

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.