📜 ⬆️ ⬇️

Dxt compression in games

In this article I want to share my experience in developing a mobile game, since I’m a Windows Phone developer, I’ll talk about my experience with this system.

Memory and textures


If you are already engaged in the development of mobile games, then the main evil is not a lack of CPU / GPU resources, but a lack of memory. It is about the memory you need to think in the mobile development in the first place. In Windows Phone 7, the limit was 100 MB, in Window Phone 8 it became better, but not much:
Limit typeApplication TypePhones with a small amount of memory1Gb phones2 GB phones
DefaultXNA or native150 MB150 MB150 MB
DefaultXAML / .NET excluding XNA150 MB300 MB300 MB
HigherherAll app types180 MB380 MB570 MB

And if you are developing a game in which a fairly large number of sprites (laid, of course, in atlases) - then you will sooner or later think about the number of these same atlases and texture compression.
The standard atlas, with which all more or less self-respecting devices work, is 2048x2048 pixels. What in uncompressed form (32 bits per pixel) will take up as much as 2 * 2 * 4 = 16 MB of memory. Then texture compression formats come to the rescue, in our case it is DXT compression.
Compressed textures not only require significantly less video card memory, but also generally display faster than uncompressed textures, at the expense of reducing bandwidth requirements. But some image quality may be lost due to compression. However, reducing the amount of memory allows you to increase the resolution of the textures that will be used, which can actually give a significant gain in quality.

Dxt compression is already implemented in .XNA Frameworke, as well as in Monogame.
For clarity, let's take 256 images of size 128x128 pixels, one texture atlas of these textures of size 2048 * 2048, and compress this atlas.
It is rumored that textures that are multiples of powers of two are loaded faster, for the experiment we will change a little the original texture, cutting off one pixel, bringing it to 2048 * 2047 size.
To show the effectiveness of the methods described, we will make control measurements. We will conduct them on the Nokia Lumia 800 phone. For greater accuracy, we will do 10 measurements for each method.
We summarize the results in table 1 and summarize.

Table 1. Image download speed.
256 textures 128 * 128 each1 dxt 2048 * 20481 origin 2048 * 20481 origin 2048 * 2047
one00: 00: 00.646000000: 00: 00.033000000: 00: 00.151000000: 00: 00.1200000
200: 00: 00.644000000: 00: 00.033000000: 00: 00.151000000: 00: 00.1180000
300: 00: 00.647000000: 00: 00.041000000: 00: 00.187000000: 00: 00.1570000
four00: 00: 00.640000000: 00: 00.033000000: 00: 00.149000000: 00: 00.1190000
five00: 00: 00.642000000: 00: 00.033000000: 00: 00.150000000: 00: 00.120000
600: 00: 00.634000000: 00: 00.047000000: 00: 00.132000000: 00: 00.161000
700: 00: 00.634000000: 00: 00.050000000: 00: 00.159000000: 00: 00.179000
eight00: 00: 00.630000000: 00: 00.050000000: 00: 00.158000000: 00: 00.179000
900: 00: 00.633000000: 00: 00.048000000: 00: 00.158000000: 00: 00.179000
ten00: 00: 00.621000000: 00: 00.047000000: 00: 00.165000000: 00: 00.1820000
The average00: 00: 00.637100000: 00: 00.041200000: 00: 00.155800000: 00: 00.1514000

For clarity, the graph of the dependence of the various methods of loading from time (Fig. 1.)
')

Figure 1. A graph of the dependence of various methods of loading on time.

Table 2. Image sizes
MethodsSizes, MB
oneSize 256 textures 128 * 128 eachsixteen
2Texture size 2048 * 2048 without compressionsixteen
3Texture size 2048 * 2048 with compressionfour

As we see from the presented experiments Dxt compression is very effective. Consider it in more detail.
DXT compression (also sometimes known as S3 compression) is actually very simple. Here's how it works:

This simple scheme, it turns out, works surprisingly well for many real world images.

There are five options for DXT compression:

The DXT1 uses 64 bits on a 4x4 block. Compared to a 32-bit uncompressed texture, this is an 8x multiple of compression. The DXT2-5 uses 128 bits in a 4x4 block, which gives 4x compression ratio.

And now the bad news: DXT compression is lossy compression. Sometimes they can be very large. In fact, it works very well for some images and is not at all suitable for others.
So, when you want to use Dxt compression, say in XNA, when you set the texture property of the Texture format, the DxtCompressed, Content Pipeline parameter automatically selects between DXT1 and DXT5, depending on whether your texture has an alpha channel. If it does not contain an alpha channel or contains a uniform alpha channel, it will use DXT1 to get the best compression ratio, but if the texture contains fractional alpha values, it will select DXT5 instead.

Let us consider in more detail each of the methods of compression:
DXT1

The DXT1 format is intended for decompression in real time by the hardware on the video card during rendering. DXT1 is a lossy compression format with a fixed 8: 1 compression ratio. DXT1 compression is a form of truncated block coding (BTC), where the image is divided into disjoint blocks, and the pixels in each block are quantized into a limited number of values. Color values ​​of pixels in a 4x4 pixel block are approximated from equidistant points on a line passing through the RGB color space. This line is defined by two endpoints, and for each pixel in a 4x4 block, a 2-bit index is stored in one of the equidistant points on the line. The ends of the line passing through the color space are encoded in a 16-bit 5: 6: 5 RGB format and one or two intermediate points are generated by interpolation. The format allows you to store a 1-bit alpha channel, by switching to another mode, based on the order of the end points, where only one intermediate point is created and one additional color output indicates that it is black and fully transparent.

Let's look at Figure 2 below:
The left image is the original. The right one illustrates compression in DXT1 format.


Figure 2. Example of Dxt1 compression.

Visually compressed image does not differ from the original, which makes the results of compression acceptable for most users. Compression, however, significantly reduces the size of the texture.
In this case, from 256 KB to 32 KB.

However, things are not so rosy with this texture (Figure 3):


Figure 3. Example of Dxt1 compression.

The main problem is the appearance of noise inside the text, as well as distinct bands on the background of the gradient.


Figure 4. Noise inside the text.

Figure 5 shows how compression affects color. On the left, you see 16 shades of red, from pure red to pure black. On the right, you see four colors that came out of DXT compression, out of these 16 shades.


Figure 5. The effect of compression on color.

Figure 6 shows what happens when different colors are not on the same line in the color space. In this case, all the extremes of the RGB palette (red, green and blue) were used. Obviously, as a result, the interpolated colors do not match the originals. Usually in the 4x4 pixel area there is not such a wide choice of colors, but it shows that textures with different colors suffer more.


Figure 6. The effect of compression on color.

DXT1 compression usually works well for noisy textures and is not so good for clean images as well as gradients. The trick is to use it wherever it is possible and not to use it only on those textures where compression artifacts are too undesirable.

DXT5

The DXT5 format differs from the DXT3 format, in that it stores information about the alpha channel, just like how to store color information.
For alpha channel information, it uses a palette similar to how digital information is stored. This palette contains the minimum and maximum values ​​of the alpha channel. There are two options with 6 and 4 reference points.
6 other alpha values ​​interpolate between this minimum and maximum. Thus, it allows for more gradual changes in the alpha value.
The second option makes interpolation only for 4 other alpha channel values ​​between the minimum and maximum values, but also adds alpha values ​​of 0 and 1 (for fully transparent and non-transparent). For some textures this may give better results.


Figure 7. Example of Dxt5 compression.

As you can see, the edges are not well processed in some parts.


Figure 8. Torn edges when using Dxt5 compression.

The size of the texture at the same time decreased from 256 KB to 64 KB.
The loss of quality on real images is not so significant and they can be neglected for most images.
Using Dxt compression allows you to:

In my project, after creating the texture atlas, I get the output .jpg / .png / .bmp and the description of the atlas in .xml / .txt / .json. Since I use XNA / Monogame for compression in .xnb, I use XNA 4.0 Content Compiler as a whole, this is a very clear and simple solution, only to use Dxt compression you need to add another property to ContentBuilder when creating buildProject:
buildProject.SetProperty(“XnaCompressContent“, “True”); 

Sources:
S3 Texture Compression
DXT compression explained
DXT Compression Techniques
Real-Time YCoCg-DXT Compression

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


All Articles