xref: /third_party/astc-encoder/Docs/Encoding.md (revision cc1dc7a3)
1cc1dc7a3Sopenharmony_ci# Effective ASTC Encoding
2cc1dc7a3Sopenharmony_ci
3cc1dc7a3Sopenharmony_ciMost texture compression schemes encode a single color format at single
4cc1dc7a3Sopenharmony_cibitrate, so there are relatively few configuration options available to content
5cc1dc7a3Sopenharmony_cicreators beyond selecting which compressed format to use.
6cc1dc7a3Sopenharmony_ci
7cc1dc7a3Sopenharmony_ciASTC on the other hand is an extremely flexible container format which can
8cc1dc7a3Sopenharmony_cicompress multiple color formats at multiple bit rates. Inevitably this
9cc1dc7a3Sopenharmony_ciflexibility gives rise to questions about how to best use ASTC to encode a
10cc1dc7a3Sopenharmony_cispecific color format, or what the equivalent settings are to get a close
11cc1dc7a3Sopenharmony_cimatch to another compression format.
12cc1dc7a3Sopenharmony_ci
13cc1dc7a3Sopenharmony_ciThis page aims to give some guidelines, but note that they are only guidelines
14cc1dc7a3Sopenharmony_ciand are not exhaustive so please deviate from them as needed.
15cc1dc7a3Sopenharmony_ci
16cc1dc7a3Sopenharmony_ci## Traditional format reference
17cc1dc7a3Sopenharmony_ci
18cc1dc7a3Sopenharmony_ciThe most commonly used non-ASTC compressed formats, their color format, and
19cc1dc7a3Sopenharmony_citheir compressed bitrate are shown in the table below.
20cc1dc7a3Sopenharmony_ci
21cc1dc7a3Sopenharmony_ci| Name     | Color Format | Bits/Pixel | Notes            |
22cc1dc7a3Sopenharmony_ci| -------- | ------------ | ---------- | ---------------- |
23cc1dc7a3Sopenharmony_ci| BC1      | RGB+A        | 4          | RGB565 + 1-bit A |
24cc1dc7a3Sopenharmony_ci| BC3      | RGB+A        | 8          | BC1 RGB + BC4 A  |
25cc1dc7a3Sopenharmony_ci| BC3nm    | G+R          | 8          | BC1 G   + BC4 R  |
26cc1dc7a3Sopenharmony_ci| BC4      | R            | 4          | L8               |
27cc1dc7a3Sopenharmony_ci| BC5      | R+G          | 8          | BC1 R + BC1 G    |
28cc1dc7a3Sopenharmony_ci| BC6H     | RGB (HDR)    | 8          |                  |
29cc1dc7a3Sopenharmony_ci| BC7      | RGB / RGBA   | 8          |                  |
30cc1dc7a3Sopenharmony_ci| EAC_R11  | R            | 4          | R11              |
31cc1dc7a3Sopenharmony_ci| EAC_RG11 | RG           | 8          | RG11             |
32cc1dc7a3Sopenharmony_ci| ETC1     | RGB          | 4          | RGB565           |
33cc1dc7a3Sopenharmony_ci| ETC2     | RGB+A        | 4          | RGB565 + 1-bit A |
34cc1dc7a3Sopenharmony_ci| ETC2+EAC | RGB+A        | 8          | RGB565 + EAC A   |
35cc1dc7a3Sopenharmony_ci| PVRTC    | RGBA         | 2 or 4     |                  |
36cc1dc7a3Sopenharmony_ci
37cc1dc7a3Sopenharmony_ci**Note:** BC2 (RGB+A) is not included in the table because it's rarely used in
38cc1dc7a3Sopenharmony_cipractice due to poor quality alpha encoding; BC3 is nearly always used instead.
39cc1dc7a3Sopenharmony_ci
40cc1dc7a3Sopenharmony_ci**Note:** Color representations shown with a `+` symbol indicate non-correlated
41cc1dc7a3Sopenharmony_cicompression groups; e.g. an `RGB + A` format compresses `RGB` and `A`
42cc1dc7a3Sopenharmony_ciindependently and does not assume the two signals are correlated. This can be
43cc1dc7a3Sopenharmony_cia strength (it improves quality when compressing non-correlated signals), but
44cc1dc7a3Sopenharmony_cialso a weakness (it reduces quality when compressing correlated signals).
45cc1dc7a3Sopenharmony_ci
46cc1dc7a3Sopenharmony_ci# ASTC Format Mapping
47cc1dc7a3Sopenharmony_ci
48cc1dc7a3Sopenharmony_ciThe main question which arises with the mapping of another format on to ASTC
49cc1dc7a3Sopenharmony_ciis how to handle cases where the input isn't a 4 component RGBA input. ASTC is
50cc1dc7a3Sopenharmony_cia container format which always decompresses in to a 4 component RGBA result.
51cc1dc7a3Sopenharmony_ciHowever, the internal compressed representation is very flexible and can store
52cc1dc7a3Sopenharmony_ci1-4 components as needed on a per-block basis.
53cc1dc7a3Sopenharmony_ci
54cc1dc7a3Sopenharmony_ciTo get the best quality for a given bitrate, or the lowest bitrate for a given
55cc1dc7a3Sopenharmony_ciquality, it is important that as few components as possible are stored in the
56cc1dc7a3Sopenharmony_ciinternal representation to avoid wasting coding space.
57cc1dc7a3Sopenharmony_ci
58cc1dc7a3Sopenharmony_ciSpecific optimizations in the ASTC coding scheme exist for:
59cc1dc7a3Sopenharmony_ci
60cc1dc7a3Sopenharmony_ci* Encoding the RGB components as a single luminance component, so only a single
61cc1dc7a3Sopenharmony_ci  value needs to be stored in the coding instead of three.
62cc1dc7a3Sopenharmony_ci* Encoding the A component as a constant 1.0 value, so the coding doesn't
63cc1dc7a3Sopenharmony_ci  actually need to store a per-pixel alpha value at all.
64cc1dc7a3Sopenharmony_ci
65cc1dc7a3Sopenharmony_ci... so mapping your inputs given to the compressor to hit these paths is
66cc1dc7a3Sopenharmony_cireally important if you want to get the best output quality for your chosen
67cc1dc7a3Sopenharmony_cibitrate.
68cc1dc7a3Sopenharmony_ci
69cc1dc7a3Sopenharmony_ci## Encoding 1-4 component data
70cc1dc7a3Sopenharmony_ci
71cc1dc7a3Sopenharmony_ciThe table below shows the recommended component usage for data with different
72cc1dc7a3Sopenharmony_cinumbers of color components present in the data.
73cc1dc7a3Sopenharmony_ci
74cc1dc7a3Sopenharmony_ciThe coding swizzle should be applied when compressing an image. This can be
75cc1dc7a3Sopenharmony_cihandled by the compressor when reading an uncompressed input image by
76cc1dc7a3Sopenharmony_cispecifying the swizzle using the `-esw` command line option.
77cc1dc7a3Sopenharmony_ci
78cc1dc7a3Sopenharmony_ciThe sampling swizzle is what your should use in your shader programs to read
79cc1dc7a3Sopenharmony_cithe data from the compressed texture, assuming no additional API-level
80cc1dc7a3Sopenharmony_cicomponent swizzling is specified by the application.
81cc1dc7a3Sopenharmony_ci
82cc1dc7a3Sopenharmony_ci| Input components |  ASTC Endpoint | Coding Swizzle | Sampling Swizzle   |
83cc1dc7a3Sopenharmony_ci| -------------- |  ------------- | -------------- | ------------------ |
84cc1dc7a3Sopenharmony_ci| 1              |  L + 1         | `rrr1`         | `.g` <sup>1</sup>  |
85cc1dc7a3Sopenharmony_ci| 2              |  L + A         | `rrrg`         | `.ga` <sup>1</sup> |
86cc1dc7a3Sopenharmony_ci| 3              |  RGB + 1       | `rgb1`         | `.rgb`             |
87cc1dc7a3Sopenharmony_ci| 4              |  RGB + A       | `rgba`         | `.rgba`            |
88cc1dc7a3Sopenharmony_ci
89cc1dc7a3Sopenharmony_ci**1:** Sampling from `g` is preferred to sampling from `r` because it allows a
90cc1dc7a3Sopenharmony_cisingle shader to be compatible with ASTC, BC1, or ETC formats. BC1 and ETC1
91cc1dc7a3Sopenharmony_cistore color endpoints as RGB565 data, so the `g` component will have higher
92cc1dc7a3Sopenharmony_ciprecision. For ASTC it doesn't actually make any difference; the same single
93cc1dc7a3Sopenharmony_cicomponent luminance will be returned for all three of the `.rgb` components.
94cc1dc7a3Sopenharmony_ci
95cc1dc7a3Sopenharmony_ci## Equivalence with other formats
96cc1dc7a3Sopenharmony_ci
97cc1dc7a3Sopenharmony_ciBased on these component encoding requirements we can now derive the the ASTC
98cc1dc7a3Sopenharmony_cicoding equivalents for most of the other texture compression formats in common
99cc1dc7a3Sopenharmony_ciuse today.
100cc1dc7a3Sopenharmony_ci
101cc1dc7a3Sopenharmony_ci| Formant  | ASTC Coding Swizzle | ASTC Sampling Swizzle | Notes            |
102cc1dc7a3Sopenharmony_ci| -------- | ------------------- | --------------------- | ---------------- |
103cc1dc7a3Sopenharmony_ci| BC1      | `rgba` <sup>1</sup> | `.rgba`               |                  |
104cc1dc7a3Sopenharmony_ci| BC3      | `rgba`              | `.rgba`               |                  |
105cc1dc7a3Sopenharmony_ci| BC3nm    | `gggr`              | `.ag`                 |                  |
106cc1dc7a3Sopenharmony_ci| BC4      | `rrr1`              | `.r`                  |                  |
107cc1dc7a3Sopenharmony_ci| BC5      | `rrrg`              | `.ra` <sup>2</sup>    |                  |
108cc1dc7a3Sopenharmony_ci| BC6H     | `rgb1`              | `.rgb` <sup>3</sup>   | HDR profile only |
109cc1dc7a3Sopenharmony_ci| BC7      | `rgba`              | `.rgba`               |                  |
110cc1dc7a3Sopenharmony_ci| EAC_R11  | `rrr1`              | `.r`                  |                  |
111cc1dc7a3Sopenharmony_ci| EAC_RG11 | `rrrg`              | `.ra` <sup>2</sup>    |                  |
112cc1dc7a3Sopenharmony_ci| ETC1     | `rgb1`              | `.rgb`                |                  |
113cc1dc7a3Sopenharmony_ci| ETC2     | `rgba` <sup>1</sup> | `.rgba`               |                  |
114cc1dc7a3Sopenharmony_ci| ETC2+EAC | `rgba`              | `.rgba`               |                  |
115cc1dc7a3Sopenharmony_ci| ETC2+EAC | `rgba`              | `.rgba`               |                  |
116cc1dc7a3Sopenharmony_ci
117cc1dc7a3Sopenharmony_ci**1:** ASTC has no equivalent of the 1-bit punch-through alpha encoding
118cc1dc7a3Sopenharmony_cisupported by BC1 or ETC2; if alpha is present it will be a full alpha
119cc1dc7a3Sopenharmony_cicomponent.
120cc1dc7a3Sopenharmony_ci
121cc1dc7a3Sopenharmony_ci**2:** ASTC relies on using the L+A color endpoint type for coding efficiency
122cc1dc7a3Sopenharmony_cifor two component data. It therefore has no direct equivalent of a two-plane
123cc1dc7a3Sopenharmony_ciformat sampled though the `.rg` components such as BC5 or EAC_RG11. This can
124cc1dc7a3Sopenharmony_cibe emulated by setting texture component swizzles in the runtime API - e.g. via
125cc1dc7a3Sopenharmony_ci`glTexParameteri()` for OpenGL ES - although it has been noted that API
126cc1dc7a3Sopenharmony_cicontrolled swizzles are not available in WebGL.
127cc1dc7a3Sopenharmony_ci
128cc1dc7a3Sopenharmony_ci**3:** ASTC can only store unsigned values, and has no equivalent of the BC6
129cc1dc7a3Sopenharmony_cisigned endpoint mode.
130cc1dc7a3Sopenharmony_ci
131cc1dc7a3Sopenharmony_ci# Other Considerations
132cc1dc7a3Sopenharmony_ci
133cc1dc7a3Sopenharmony_ciThis section outlines some of the other things to consider when encoding
134cc1dc7a3Sopenharmony_citextures using ASTC.
135cc1dc7a3Sopenharmony_ci
136cc1dc7a3Sopenharmony_ci## Decode mode extensions
137cc1dc7a3Sopenharmony_ci
138cc1dc7a3Sopenharmony_ciASTC is specified to decompress into a 16-bit per component RGBA output by
139cc1dc7a3Sopenharmony_cidefault, with the exception of the sRGB format which uses an 8-bit value for the
140cc1dc7a3Sopenharmony_ciRGB components.
141cc1dc7a3Sopenharmony_ci
142cc1dc7a3Sopenharmony_ciDecompressing in to a 16-bit per component output format is often higher than
143cc1dc7a3Sopenharmony_cimany use cases require, especially for LDR textures which originally came from
144cc1dc7a3Sopenharmony_cian 8-bit per component source image. Most implementations of ASTC support the
145cc1dc7a3Sopenharmony_cidecode mode extensions, which allow an application to opt-in to a lower
146cc1dc7a3Sopenharmony_ciprecision decompressed format (RGBA8 for LDR, RGB9E5 for HDR). Using these
147cc1dc7a3Sopenharmony_ciextensions can improve GPU texture cache efficiency, and even improve texturing
148cc1dc7a3Sopenharmony_cifiltering throughput, for use cases that do not need the higher precision.
149cc1dc7a3Sopenharmony_ci
150cc1dc7a3Sopenharmony_ciThe ASTC format uses different data rounding rules when the decode mode
151cc1dc7a3Sopenharmony_ciextensions are used. To ensure that the compressor chooses the best encodings
152cc1dc7a3Sopenharmony_cifor the RGBA8 rounding rules, you can specify `-decode_unorm8` when compressing
153cc1dc7a3Sopenharmony_citextures that will be decompressed into the RGBA8 intermediate. This gives a
154cc1dc7a3Sopenharmony_cismall image quality boost.
155cc1dc7a3Sopenharmony_ci
156cc1dc7a3Sopenharmony_ci**Note:** This mode is automatically enabled if you use the `astcenc`
157cc1dc7a3Sopenharmony_cidecompressor to write an 8-bit per component output image.
158cc1dc7a3Sopenharmony_ci
159cc1dc7a3Sopenharmony_ci## Encoding non-correlated components
160cc1dc7a3Sopenharmony_ci
161cc1dc7a3Sopenharmony_ciMost other texture compression formats have a static component assignment in
162cc1dc7a3Sopenharmony_citerms of the expected data correlation. For example, ETC2+EAC assumes that RGB
163cc1dc7a3Sopenharmony_ciare always correlated and that alpha is non-correlated. ASTC can automatically
164cc1dc7a3Sopenharmony_ciencode data as either fully correlated across all 4 components, or with any one
165cc1dc7a3Sopenharmony_cicomponent assigned to a separate non-correlated partition to the other three.
166cc1dc7a3Sopenharmony_ci
167cc1dc7a3Sopenharmony_ciThe non-correlated component can be changed on a block-by-block basis, so the
168cc1dc7a3Sopenharmony_cicompressor can dynamically adjust the coding based on the data present in the
169cc1dc7a3Sopenharmony_ciimage. This means that there is no need for non-correlated data to be stored
170cc1dc7a3Sopenharmony_ciin a specific component in the input image.
171cc1dc7a3Sopenharmony_ci
172cc1dc7a3Sopenharmony_ciIt is however worth noting that the alpha component is treated differently to
173cc1dc7a3Sopenharmony_cithe RGB color components in some circumstances:
174cc1dc7a3Sopenharmony_ci
175cc1dc7a3Sopenharmony_ci* When coding for sRGB the alpha component will always be stored in linear
176cc1dc7a3Sopenharmony_ci  space.
177cc1dc7a3Sopenharmony_ci* When coding for HDR the alpha component can optionally be kept as LDR data.
178cc1dc7a3Sopenharmony_ci
179cc1dc7a3Sopenharmony_ci## Encoding normal maps
180cc1dc7a3Sopenharmony_ci
181cc1dc7a3Sopenharmony_ciThe best way to store normal maps using ASTC is similar to the scheme used by
182cc1dc7a3Sopenharmony_ciBC5; store the X and Y components of a unit-length normal. The Z component of
183cc1dc7a3Sopenharmony_cithe normal can be reconstructed in shader code based on the knowledge that the
184cc1dc7a3Sopenharmony_civector is unit length.
185cc1dc7a3Sopenharmony_ci
186cc1dc7a3Sopenharmony_ciTo encode this we need to store only two input components in the compressed
187cc1dc7a3Sopenharmony_cidata, and therefore use the `rrrg` coding swizzle to align the data with the
188cc1dc7a3Sopenharmony_ciASTC luminance+alpha endpoint. We can sample this in shader code using the
189cc1dc7a3Sopenharmony_ci`.ga` sampling swizzle, and reconstruct the Z value with:
190cc1dc7a3Sopenharmony_ci
191cc1dc7a3Sopenharmony_ci    vec3 nml;
192cc1dc7a3Sopenharmony_ci    nml.xy = texture(...).ga;                // Load normals (range 0 to 1)
193cc1dc7a3Sopenharmony_ci    nml.xy = nml.xy * 2.0 - 1.0;             // Unpack normals (range -1 to +1)
194cc1dc7a3Sopenharmony_ci    nml.z = sqrt(1 - dot(nml.xy, nml.xy));   // Compute Z, given unit length
195cc1dc7a3Sopenharmony_ci
196cc1dc7a3Sopenharmony_ciThe encoding swizzle and appropriate component weighting is enabled by using
197cc1dc7a3Sopenharmony_cithe `-normal` command line option. If you wish to use a different pair of
198cc1dc7a3Sopenharmony_cicomponents you can specify a custom swizzle after setting the `-normal`
199cc1dc7a3Sopenharmony_ciparameter. For example, to match BC5n component ordering use
200cc1dc7a3Sopenharmony_ci`-normal -esw gggr` for compression and `-normal -dsw arz1` for decompression.
201cc1dc7a3Sopenharmony_ci
202cc1dc7a3Sopenharmony_ci## Encoding sRGB data
203cc1dc7a3Sopenharmony_ci
204cc1dc7a3Sopenharmony_ciThe ASTC LDR profile can compress sRGB encoded color, which is a more
205cc1dc7a3Sopenharmony_ciefficient use of bits than storing linear encoded color because the gamma
206cc1dc7a3Sopenharmony_cicorrected value distribution more closely matches human perception of
207cc1dc7a3Sopenharmony_ciluminance.
208cc1dc7a3Sopenharmony_ci
209cc1dc7a3Sopenharmony_ciFor color data it is nearly always a perceptual quality win to use sRGB input
210cc1dc7a3Sopenharmony_cisource textures that are then compressed using the ASTC sRGB compression mode
211cc1dc7a3Sopenharmony_ci(compress using the `-cs` command line option rather than the `-cl` command
212cc1dc7a3Sopenharmony_ciline option). Note that sRGB gamma correction is only applied to the RGB
213cc1dc7a3Sopenharmony_cicomponents during decode; the alpha component is always treated as linear
214cc1dc7a3Sopenharmony_ciencoded data.
215cc1dc7a3Sopenharmony_ci
216cc1dc7a3Sopenharmony_ci*Important:* The uncompressed input texture provided on the command line must
217cc1dc7a3Sopenharmony_cibe stored in the sRGB color space for `-cs` to function correctly.
218cc1dc7a3Sopenharmony_ci
219cc1dc7a3Sopenharmony_ci## Encoding HDR data
220cc1dc7a3Sopenharmony_ci
221cc1dc7a3Sopenharmony_ciHDR data can be encoded just like LDR data, but with some caveats around
222cc1dc7a3Sopenharmony_cihandling the alpha component.
223cc1dc7a3Sopenharmony_ci
224cc1dc7a3Sopenharmony_ciFor many use cases the alpha component is an actual alpha opacity component and
225cc1dc7a3Sopenharmony_ciis therefore used for storing an LDR value between 0 and 1. For these cases use
226cc1dc7a3Sopenharmony_cithe `-ch` compressor option which will treat the RGB components as HDR, but the
227cc1dc7a3Sopenharmony_ciA component as LDR.
228cc1dc7a3Sopenharmony_ci
229cc1dc7a3Sopenharmony_ciFor other use cases the alpha component is simply a fourth data component which
230cc1dc7a3Sopenharmony_ciis also storing an HDR value. For these cases use the `-cH` compressor option
231cc1dc7a3Sopenharmony_ciwhich will treat all components as HDR data.
232cc1dc7a3Sopenharmony_ci
233cc1dc7a3Sopenharmony_ci- - -
234cc1dc7a3Sopenharmony_ci
235cc1dc7a3Sopenharmony_ci_Copyright © 2019-2024, Arm Limited and contributors. All rights reserved._
236