Add support for KTX2
see https://github.com/KhronosGroup/KTX-Software/tree/ktx2
Hi, I'm currently rewriting the core engine to support easier unit testing and a console interface. I'll take a look at ktx2 files afterwards. It would also be helpful if you could provide some sample code how to load/export ktx2 files since I can't find it in the readme.
Maybe a good start: https://github.com/ux3d/glTF-IBL-Sampler/blob/master/lib/source/ktxImage.cpp
The link does not work for me. Maybe because it is a private project?
Yes, you are right. Here is the public one: https://github.com/KhronosGroup/glTF-IBL-Sampler/blob/master/lib/source/ktxImage.cpp
We also started to work on it, but did not have time to finish: https://github.com/ux3d/ImageViewer
I figured out how to load ktx2 files with the ktx.h header. However I still have unresolved dependencies for the ktxTexture2_CreateFromNamedFile function. Do you know which of the ktx projects I have to build to resolve those dependencies? You can check out the ktx2 branch to try this yourself as well. See ktx_interface.h in DxImageLoader.
@MarkCallow Can you please help on this?
You need the libktx project from the ktx2 branch of the KTX-Software repo. See BUILDING.md for build instructions.
There are examples in the documentation but unfortunately until I move the ktx2 work to master I don't know how to make the Doxygen built documentation available via GitHub. In the meantime you can look at the loadtest programs. The simplest OpenGL {,ES} 3 one is DrawTexture.cpp. This also shows transcoding. There's an equivalent Vulkan load test as well.
Be aware that the transcode target format enums shown in the examples will be changing when the latest update from Basis is integrated. There'll be more of them and the names will change. That work is in progress.
I added some experimental support for loading ktx2 files on the ktx2 branch. Most of the images from the KTX-Software test folder can be loaded. However, there are some issues with DXT-compressed formats and files that don't have a vkFormat specified. Let me know if you need support for specific file formats that don't work at the moment. If it works for the files you work with I can add an export for ktx2 as well
However, there are some issues with DXT-compressed formats
Is this a problem in libktx or are you not using that?
and files that don't have a vkFormat specified
Is this referring to textures supercompressed with BasisU or something kind of file with a vkFormat?
Is this a problem in libktx or are you not using that?
I am using libktx to load the ktx2 file. However, I convert it to RGBA8 using Compressonator because the image viewer only uses RGBA8 and RGBA32 internally to make some stuff easier. I don't have problems loading bc2 (DXT3) files from .ktx or .dds though. When I load "cubemap_yokohama_bc3_unorm.ktx2" the alpha channel is 255 for every 4th channel and 0 for the other 3/4 channels. If I overwrite all alpha values with 255, everything looks correct.
^ This is what it looks like zoomed in (the checkerboard means alpha = 0)
Is this referring to textures supercompressed with BasisU or something kind of file with a vkFormat?
Oh, your right, it's actually supercompressed with BasisU
The may be a problem with vkFormat in cubemap_yokohama_bc3_unorm.ktx2. The original .ktx file has a glInternalformat of 0x83F3 which is GL_COMPRESSED_RGBA_S3TC_DXT5_EXT . DXT5 is now known as BC3.
In the conversion to .ktx2 vkFormat has been set to VK_FORMAT_BC2_UNORM_BLOCK. The difference between BC2 and BC3 is the way alpha is handled so the mislabelling may be the cause of the issue you are seeing. I will need to fix the conversion table and respin the .ktx2 file.
I do not see any issue with the texture in my test program. My program's reflection shader only uses rgb. The skybox shader passes all 4 components as its output color but there is no background to see through to, so possibly I just missed the problem. Also I have nothing to compare my result to.
Apologies for the problem.
Oh, your right, it's actually supercompressed with BasisU
What is "it" referring to? cubemap_yokohama_bc3_unorm.ktx2 is not BasisU compressed. I need to create an uncompressed version of the texture first and I haven't yet had time, though I do have the original images now.
The latest BasisU transcoder support in libktx lets you transcode to RGBA8.
I have created PR #138 in KTX-Software which fixes the affected testimages. The conversion table had been fixed but the test images had not been respun.
Hi, the mipmap padding has been updated https://github.com/KhronosGroup/KTX-Software/pull/171 and some ktx files might not be compatible anymore. Could you please update the viewer to use the lastest version libktx?
Thank you for maintaining this viewer :)
I updated the ktx submodule and the libktx binaries. Additionally, I added support for KTX_SUPERCOMPRESSION_BASIS files.
All the ktx2 software is in KTX-Software master now. This also means the generated documentation is available at https://github.khronos.org/KTX-Software/. See https://github.khronos.org/KTX-Software/libktx/index.html#overview for a concise summary of how to use the library.
Hello, I finally had some time to adjust my ktx2 loader to the latest version. The viewer is now able to load all ktx2 files from the ktx/tests/testimages directory. Do you need an export option for ktx2 files from within the viewer? If so, I can try to do that in the future.
Great, looking forward to it. Will revisit to download the binary as soon as ready.
I have a question for @MarkCallow
What are the full requirements for ktxTexture2_CompressBasis() to work?
The docs say that:
- the texture should not be supercompressed
- the texture format should not be in a block compressed format
- the texture dimension should be 2D
However, I tried to compress a small 3x3 image with VK_FORMAT_R32G32B32A32_SFLOAT and I got a KTX_INVALID_OPERATION as well. Is this limited to specific formats? Or does the image size also play a role? (For example: must be multiples of 4 or 8 in each dimension)
There are 2 other conditions which I will add to the documentation. Sorry for the omission.
- @exception KTX_INVALID_OPERATION The texture image's format is a packed format (e.g. RGB565).
- @exception KTX_INVALID_OPERATION The texture image format's component size is not 8-bits.
This case is failing because the image format is 32-bit SFLOAT.
You can try supercompressing it with zstd (--zcmp option in toktx). If you do, I'd like to know how effective it is. I don't have many float textures available for testing.
I started developing the export for ktx2 files and the export for non-basis-compressed should be finished. However, I still have some questions about the compression. First of all, I can compress the texture in either etc or astc format. In which cases should etc or astc be preferred?
Second thing is, I am not really sure how to properly import those textures again. I am not sure how to select the best format for the Transcode Basis function. Right now I use KTX_TTF_ASTC_4x4_RGBA for all cases. Another problem with transcoded texture is, that I don't know how to get the information about the original texture format before the transcoding (since vkFormat is zero before transcoding). I would like to display that information in the viewer if possible.
Last thing I noticed: when I compress an RG8 texture and import it afterwards, I get an RA8 texture.
I would appreciate if you can give me a few pointers @MarkCallow
Please see the Developer and Artist Guides for your questions about when to choose UASTC vs ETC1S and for choosing transcode targets.
You cannot get information about the original VK_FORMAT before transcoding. It's not very useful. You can find out how many components were in the original image from the channel names in the DFD. This can be useful for choosing the transcode target. The other important information is the transfer function also available in the DFD.
Which version of the KTX-Software are you using? The latest version of toktx treats a 2-component import as luminance alpha (because that is what the PNG spec. says it is) so you get actually an RRRA texture. You can override this using the new --target_type option. If you specify RG and are encoding to UASTC you will get an RG01 UASTC texture. If encoding to ETC1S you get an RRRG ETC1S texture for better compression results. The transcoder can transcode this to a BC5 2 channel texture.
so you get actually an RRRA texture
I was referring to UASTC and ETC1S encoding here. If you create a texture in an uncompressed format you indeed get an RA texture but it has swizzle metadata set that indicates you should apply an rrra swizzle for correct rendering. I did not want to nearly triple the size of the texture by doing the swizzle on input.
The image viewer should now be able to export all supported .ktx2 texture formats.
Formats that also support supercompression have a "quality" settings, which allows the user to select the quality of the supercompression, or disable supercompression:
As you can see, they will be informed that quality below 100 results in compression.
For exports to any SRGB format, the compression defaults to ETC1S w/ BasisLZ.
For exports to UNORM formats, the compression defaults to UASTC w/ Zstandard.
As far as I could tell, those compressions only work on UNORM or SRBG file formats. So I disabled this setting for SNORM formats (and the other formats that do not fit the requirements as discussed in previous comments).
Currently there is no option to export SRGB formats with an UASTC compression. Some other specific options, like the "normalMap" param, are also not selectable.
Is there a need to add one of those options? Or does it sound good as it is? I need to do some testing before I will publish the next release. But I will inform you as soon as this is done.
Sounds great. I'll take a look as soon as I have time.
"Quality" is the wrong term for supercompression (i.e. zstd) as it is lossless. The parameters basically determine how long compression takes vs the size of the result. It is fine for UASTC and ETC1S. The BasisLZ supercompression is tightly coupled with the ETC1S encoder so what you show in the dialog is fine for that case. For UASTC there are basically 3 knobs to twiddle: UASTC compression parameters, RDO parameters for conditioning the UASTC data for better LZ compression and the zstd parameters. The last is what I referred to above. If you ever add an option for applying zstd to existing data, that is when to avoid "quality".
UASTC is fully capable of handling sRGB. Users should be able to choose UASTC for sRGB inputs.
Is there a need to add one of those options?
Which options? If this includes sRGB/UASTC I've just answered. If this includes normalMap, since you don't have explicit settings for the RDO parameters and you are using RDO at some "quality setting" then yes you need to option so that RDO can be disabled.
Okay, so my plan is the following:
For SRGB exports: By default ETC1S w/ BasisLZ is used. There will be an additional checkbox: "Use UASTC for compression", that will be disabled by default (because I think ETC gives much better results especially regarding the small file size).
For UNorm exports: There will be an additional checkbox: "Normal Map", that will disable the RDO.
The Code in the backend then looks like this:
ktxBasisParams params = {};
params.structSize = sizeof(params);
params.threadCount = std::thread::hardware_concurrency();
params.compressionLevel = KTX_ETC1S_DEFAULT_COMPRESSION_LEVEL;
params.qualityLevel = std::max((quality * 254) / 99 + 1, 1); // scale quality [0, 99] between [1, 255]
params.normalMap = KTX_FALSE;
if (!gli::is_srgb(format)) // only valid for linear textures
params.normalMap = get_global_parameter_i("normalmap") ? KTX_TRUE : KTX_FALSE;
// select uastc for everything that is not color (here: for everyhing that is not SRGB)
// unless the "uastc srgb" flag is set => then use usastc as well
if(!gli::is_srgb(format) || get_global_parameter_i("uastc srgb"))
{
params.uastc = KTX_TRUE;
params.uastcFlags = KTX_PACK_UASTC_MAX_LEVEL; // maximum supported quality
params.uastcRDO = params.normalMap ? KTX_FALSE : KTX_TRUE;
}
Does that sound good enough?
First of all, thank you very much for this application. It's the only viewer I have been able to use to load KTX2, although I tried others that claim to support it and failed.
Is support for orientation (https://github.khronos.org/KTX-Specification/#_ktxorientation) planned? I am setting it up and down, but I see the same result, so I guess it's not there yet.
Thanks again.
Hello, I thought that I did already implement the up and down support for ktx2. It would be easiest if you could attach the file, so that I can debug it. Support for left, right, inward, outward was not planned yet. Do you need that as well? If there are other issues with the ktx2 support, please report them. I rarely use that format.
I'm sorry, I checked and rechecked and still the problem was in my test. Thank you for your fast answer that stopped me wasting more time and sorry again for wasting yours. I don't think I'll need other orientations and haven't found any other issues, but I'll report them if I do.
Thanks again, great app :)
I will close this issue for now. Support for ktx2 should be stable. I tested against the files in the ktx repository. If anything does not work, feel free to reopen the issue