KhronosGroup / KTX-Software

KTX (Khronos Texture) Library and Tools
Other
852 stars 225 forks source link

Provide mip-mapping capabilities in libKTX #464

Open thokra1 opened 3 years ago

thokra1 commented 3 years ago

Currently, there doesn't seem to be a way to let the BasisU encoder generate mip maps. There is a host of options one can pass to the latest BasisU CLI:

  "Mipmap generation options:\n"
  " -mipmap: Generate mipmaps for each source image\n"
  " -mip_srgb: Convert image to linear before filtering, then back to sRGB\n"
  " -mip_linear: Keep image in linear light during mipmap filtering (i.e. do not convert to/from sRGB for filtering purposes)\n"
  " -mip_scale X: Set mipmap filter kernel's scale, lower=sharper, higher=more blurry, default is 1.0\n"
  " -mip_filter X: Set mipmap filter kernel, default is kaiser, filters: box, tent, bell, blackman, catmullrom, mitchell, etc.\n"
  " -mip_renorm: Renormalize normal map to unit length vectors after filtering\n"
  " -mip_clamp: Use clamp addressing on borders, instead of wrapping\n"
  " -mip_fast: Use faster mipmap generation (resample from previous mip, not always first/largest mip level). The default (as of 1/2021)\n"
  " -mip_slow: Always resample each mipmap level starting from the largest mipmap. Higher quality, but slower. Opposite of -mip_fast. Was the prior default before 1/2021.\n"
  " -mip_smallest X: Set smallest pixel dimension for generated mipmaps, default is 1 pixel\n"

Currently, while using libKTX works well for most other encoding-related tasks, all of the above has to be implemented separately (in our case using STBI resize, which sadly lacks Kaiser window filtering, IIRC).

MarkCallow commented 3 years ago

Mipmap generation in toktx uses the same code as basisu. Use --genmipmap to invoke it. It automatically does -mip_srgb if the input images are srgb, as determined from the input image. Similarly -mip_linear is done if the input images are linear. You can override the image metadata with--{assign,convert}_oetf which will also change the mipmap generation. You can set the filter with --filter, the scale with --fscale and the clamp mode with --wmode. The only things missing are -mip_renormalize, -mip_fast and -mip_slow. I have a TODO for renormalize. toktx currently always does the same as -mip_slow. The resampling speed has never troubled me so I didn't have a TODO for fast & slow.

MarkCallow commented 3 years ago

Whoops! You want the mipmap generation functionality in libktx. If I add it, I'll make it work for any format not just when using the BasisU encoder. Like with toktx, mip_srgb and mip_linear will be chosen based on the texture format but it will be possible to override.

thokra1 commented 3 years ago

This would be highly appreciated. Alternatively, I could spare some time and give you a pull request, if you're interested.

MarkCallow commented 3 years ago

A PR would be great. The PR can access the resampler in the BasisU code in a similar way to how toktx does it. The genmipmap function should give KTX_INVALID_OPERATION if the texture is already in a block-compressed format or if it already has mipmaps.

MarkCallow commented 3 months ago

I was caused to re-read this report after which I have a few questions:

  1. The BasisU CLI mentioned only lets you apply the mipmap options when compressing a file and it only compresses from PNG/BMP/TGA/JPG inputs. This is exactly equivalent to what you can do with ktx create (except it does not support BMP and TGA inputs). So @thokra1 what exactly are you asking for?
  2. If, as I guessed, you want mipmap generation in libktx, how would you create the input .ktx2 files, if not with ktx create?

The BasisU tool can also unpack .basis files to "one of more .ktx/.png files". You could then read these back into the tool and use the mipmap generation. You can do exactly the same with the ktx tool suite: use ktx extract to create .png or .exr files then ktx create with mipmap generation options to create a new .ktx2 file. But I do not recommend doing this from source files that have been subject to lossy compression: .basis files or .ktx2 files with BasisU, BCn, ASTC, ETC, etc. format images because you will introduce further losses. For this reason, if we were to add mipmap generation support to libktx, we would make it a KTX_INVALID_OPERATION to generate mipmaps if the .ktx2 file has such a format.

The crux of deciding whether there is anything to proceed with here is the answer to question 2.

donmccurdy commented 3 months ago

@MarkCallow one significant use case would be tools like glTF-Compressor. To my understanding it uses libktx via JS/WASM to compress PNG/JPG images in glTF files; ktx create is not available in a browser environment. As a result, glTF files generated with glTF-Compressor currently lack mipmaps: