KhronosGroup / KTX-Software

KTX (Khronos Texture) Library and Tools
Other
863 stars 226 forks source link

Basis Universal Transcoding with Mip-Map Levels seems to not work #176

Closed atteneder closed 4 years ago

atteneder commented 4 years ago

Hi,

I tried loading basisu supercompressed KTX2 files with mip-map levels in my Unity package (dev branch). It produces a visually broken texture:

ktx_levels

When transcoding an identical .basis file, it seems to work:

basisu_levels

The basis file is transcoded like this: All levels are subsequential in memory, starting with the biggest level (0) down to the 1x1 level (10). There's no padding considered, but in this case it's no problem.

Here are the test files textures.zip

Would be great to get fixed!

MarkCallow commented 4 years ago

Here is what I see using libktx to load it:

Screen Shot 2020-02-26 at 21 09 01

The two smallest levels are possibly questionable though given the orange color of the trout arguably okay. Are these what you are complaining about? According the the file, it was created with toktx which means you must have supplied the mip level images. Are you suggesting that the libktx loader is responsible for introducing the 2 orange colored lower levels. (Mip sizes go down as you go up the stack.) If what you are seeing here is okay, then maybe the problem is in your loader.

atteneder commented 4 years ago

True, colors of the lowest 2 levels are strange, but that's indeed a content problem.

If you look at the first frame of the first GIF, you notice that the texture is somewhat misplaced (scaled down and repeated).

ktx_level_0

In the second frame it's distorted and every other pixel row is completely different.

grafik

It seems like my manual transcoding of .basis files and the transcoding via ktxTexture2_TranscodeBasis produce different results / memory layouts.

Mine works with Unity's Texture2D.LoadRawTextureData and ktxTexture2_TranscodeBasis works in the KTX Loader Test app you tested (assuming that's how you use it).

If you don't have a clue or hint for me, I'll have to find out the differences myself.

Thanks!

MarkCallow commented 4 years ago

KTX 2 files have the smallest mip level first in the data. You should use the levelIndex to retrieve the offsets of each level in the file.

atteneder commented 4 years ago

Hi Mark,

thanks for this hint. I've got it correct now! :) I'll commit the necessary changes into my cmake(unity) branch soon.

Indeed Unity needs the mip chain in reverse order. Currently I'm allocating an additional buffer and copy the levels in reverse order via memcpy.

As optimization idea, this step could be avoided if libktx provides a transcoding function with an external buffer destination like:

ktxTexture2_TranscodeBasis_external(ktxTexture2* This,
                           ktx_transcode_fmt_e outputFormat,
                           ktx_transcode_flags transcodeFlags,
                           ktx_uint8_t* destination,
                           ktx_size_t destinationLength
)

What's your opinion on something like this?

Thanks!

atteneder commented 4 years ago

original issue is not an issue => closing