Closed TobiasWehrum closed 1 year ago
Straight from the introduction:
The UASTC encoder has an optional Rate Distortion Optimization (RDO) encoding mode (implemented as a post-process over the encoded UASTC texture data), which conditions the output texture data in a way that results in better lossless compression when UASTC .basis files are compressed with Deflate/Zstd, etc. In UASTC mode, you must losslessly compress .basis files yourself. .KTX2 files have built-in lossless compression support using Zstandard, which is used by default on UASTC textures.
The key things here being
when UASTC .basis files are compressed with Deflate/Zstd, etc.
and
In UASTC mode, you must losslessly compress .basis files yourself.
because, AFAIR, BasisU doesn't provide built-in compression of the encoded data for UASTC, only for ETC1S. This means that you have to do an additional, manual compression pass when using .basis
containers. As stated above, going with KTX2 containers gives you the opportunity to have the contained data ZStandard-compressed. With the BasisU CLI, all your need to do is provide the -ktx2
option:
-ktx2: Write .KTX2 ETC1S/UASTC files instead of .basis files. By default, UASTC files will be compressed using Zstandard unless -ktx2_no_zstandard is specified.\n
When doing it programmatically with libKTX, you'd do
// assume 'tex' is a ktxTexture2* and '19 is the ZStandard compression level
ktxTexture2_DeflateZstd(tex, 19);
after compression to UASTC and application of RDO to that data. The resulting size of the KTX2 container will be smaller with RDO applied, unless RDO cannot actually optimize anthing further, ofc.
So, do some manual compression af the result you got from the CLI and see for yourself. It's worth to add some compression on your binaries anyway, depending on what your use-case is. For instance, for stuff transmitted over the web, all the additional lossless compression (like ZStd) you can get is worth it IMHO.
That makes sense, thanks!
Here is my thoughts after reading babisu_comp.cpp: when it comes to uastc, BabisU just pack the texture into many astc blocks, and save these blocks directly with the .basis file extension so that the GPU can decode them by the astc decompression format; but when it comes to .ktx2 file, GPU is unable to handle the decompression of Zstd-compression used in the ktx saving work. Did I miss something or up to now it works just like this?
ZStandard does not produce anything that GPUs can understand. It's used on top of the block compression to further reduce the size of the KTX payload and thus the file size. Since it's not directly consumable by a GPU, the payload has to first be decompressed and then u can use that clock compressed data with your API of choice.
Thank you, here comes my understanding after reading your comments: Btw, in my eye the low-level operation of RDO mode in uastc is just replacing a lot of blocks' texel weight data with some few blocks' texel weight data when they are measured to be similar, so that the same weight datas can be seen as one symbol then zstd can compress them more efficiently, right?
The readme says:
I tried both
basisu -uastc -uastc_level 2 x.png
andbasisu -uastc -uastc_level 2 -uastc_rdo_l .75 x.png
on Windows 10 using the current version on NPM (1.16.3), and both results have the exact same size.