-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
KTX2Loader: Offset overflows texture dimensions #25908
Comments
@donmccurdy Was able to reproduce this error on my system. Are you already working on this? If not, i can give it a try to fix this. |
I haven't had the chance to work on this, please feel free! Note that I'm unsure whether it is a bug in KTX2Loader, a bug in WebGLLoader, or a limitation of WebGL's mipmap size requirements. |
Sure, I'll have a look. From my initial observation, it seems like a limitation of WebGL's mipmap size requirements but I'll have to re-confirm by first looking at the loaders. The issue is reproducible on Firefox as well. Power of 2 sized compressed mipmapped textures work well (as in the original example). |
This code in KTX2Loader.js:
should be:
levelInfo.width/height represent the size of the mip level rounded up to 4x4 block boundary; I believe glCompressedTexImage2D/glCompressedTexSubImage2D arguments should instead use the original dimensions that have not been rounded. |
@zeux hm, we'd previously used that code, and updated it to "fix" an issue displaying this same error message. I'm a bit confused about how the original dimensions persist in a compressed image... 😕 Related: |
Well, 2118 isn't divisible by 4. Some APIs require top mip level size to have dimensions divisible by 4, so you won't be able to load a texture like this. The fix from that PR doesn't fully fix the problem - yes, you're going to be able to create the texture, but attempting to actually sample from it will use pixels that were never encoded, and the texture will be incorrectly sized. If we want to be conservative we could use width/height just for mip 0 as a workaround, while keeping the issue above in mind (which can lead to visual artifacts if the image is tiled for example). |
(the divisibility by 4 isn't always a problem but it sometimes is, it depends on the encoded format and the underlying API to a certain extent. It was discussed previously here KhronosGroup/KTX-Software#254) |
Actually, let me amend this - we should only apply this workaround when the texture doesn't have a mip chain. If the texture has mip levels, and it's of size 102x102, the mip chain should have sizes 51x51, 25x25, 12x12, 6x6, 3x3, 1x1. If you resize it to 104x104, the mip chain that GL will allocate will have sizes 52x52, 26x26, 13x13, 6x6, 3x3, 1x1. The mip that goes from 12x12 to 13x13 will not have the correct encoded expanded blocks in the file - the file will have encoded it as precisely 12x12 as these match block dimensions, but the renderer will expect 13x13 which is 1 extra row/column of 4x4 blocks... The only fully correct solution is to reject loading of textures with top mip level's width/height not being divisible by 4 if the extension being targeted by the format doesn't support arbitrary top level dimensions - see linked thread for some details on different extensions, I don't fully recall them OTOH. If we wanted to preserve the original fix, we should only apply it when there's only one mip level. |
Thank you! I suspect we should start logging a warning about non-multiple-of-four textures, as well. Opened a PR: |
Description
When loading the attached glTF containing KTX2 textures (which pass validation), we see broken mipmaps in the rendering and an error in the console:
The original texture has multiple-of-four dimensions, but is not using powers of two. I believe that should still be valid in WebGL2 contexts.
Reproduction steps
Code
Archive.zip
Header from
ktxinfo
–Live example
n/a
Screenshots
Preview:
Mipmaps:
Version
dev
Device
Desktop
Browser
Chrome
OS
MacOS
The text was updated successfully, but these errors were encountered: