Skip to content
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

Incorrect handling of textures with odd width/height #254

Closed
zeux opened this issue Jul 3, 2020 · 12 comments
Closed

Incorrect handling of textures with odd width/height #254

zeux opened this issue Jul 3, 2020 · 12 comments

Comments

@zeux
Copy link
Contributor

zeux commented Jul 3, 2020

KTX2 specification says:

Image dimensions must adhere to format-specific requirements, including:
width and height being multiples of 4 for BCn and ETC1/ETC2/EAC formats;
width, height, and depth being multiples of the corresponding block size dimensions for ASTC formats;
various restrictions for PVRTC formats (see [PVRTC], [PVRTC1_OES], and [PVRTC2_OES]).

My assumption is that for supercompressed textures - both using Basis ETC1S and UASTC - these requirements must hold as well, as ETC1S is a subset of ETC1, and UASTC is a subset of ASTC 4x4.

However, compressing a 211x211 texture with either --bcmp or --uastc produces a KTX2 file that has the size 211x211; this file additionally does not report any validation errors when ktx2check is ran, which I believe is a bug. The resulting texture can not be loaded using any WebGL implementation.

I believe the correct behavior here is to, a) rescale the texture during conversion to the closest divisible-by-4 value on all sides; b) fix ktx2check to report an error for oddly-sized textures.

@zeux zeux changed the title Incorrect handling of textures with width/height non-divisible by 4 Incorrect handling of textures with odd width/height Jul 3, 2020
@MarkCallow
Copy link
Collaborator

We're planning to remove that restriction. See KhronosGroup/KTX-Specification#123 (comment). WebGL is the only platform with such restrictions on image size and I think it is only for s3tc textures.

Scaling to closest divisible-by-4 doesn't always work if you are creating mipmaps because WebGL also insists that all mip levels except 1x1, and 2x2 be multiples of 4.

@lexaknyazev
Copy link
Member

@MarkCallow
Unfortunately, D3D11 also requires compressed textures to have multiple-of-4 dimensions but only for the mip level 0.

WebGL restrictions are being discussed atm, as there're some differences between specs and implementations.

@kenrussell
Copy link
Member

Work's being done in http://crbug.com/1100834 to refine the necessary WebGL restrictions in order to accommodate implementations on top of D3D11 - but please support WebGL's limitations in the KTX pipeline as @zeux suggests. People want to use KTX and supercompressed textures as a one-stop shop and don't want to have to become experts to understand the sizing limitations. Users are already feeding in arbitrarily sized textures to pipelines like basisu and expect them to work, when they can't trivially, due to D3D11 limitations that are reflected in the WebGL compressed texture specs. If for example a command line argument were added to indicate that WebGL will be a consumer of the supercompressed textures then the documentation could just say that if people intend to target the web, pass that flag, feed in textures of any size, and the tool will rescale as necessary before supercompression.

@MarkCallow
Copy link
Collaborator

I'm okay with adding a flag to make the top level size a multiple of 4. (Why D3D11 has such restrictions when the hardware doesn't is beyond me). However there is no reasonable way to support the additional restrictions WebGL places on s3tc textures.

@zeux
Copy link
Contributor Author

zeux commented Jul 14, 2020

However there is no reasonable way to support the additional restrictions WebGL places on s3tc textures.

There is - you need to resize textures to the next power of two. Having said that this feels unsatisfying, especially since BPTC textures don't have to be a power of two. I'm wondering if this is something that can be relaxed in WebGL, possibly through a new extension?

@MarkCallow
Copy link
Collaborator

There is - you need to resize textures to the next power of two

That doesn't meet my definition of reasonable. Do you distort the image, crop it or pad it? If the latter it has to be communicated to the rendering code somehow so it can adjust the texture coordinates.

I'm wondering if this is something that can be relaxed in WebGL, possibly through a new extension?

I'd like to see this happen. The restriction originated on some ancient hardware no longer relevant.

@lexaknyazev
Copy link
Member

Do you distort the image, crop it or pad it?

To retain existing UVs, linear scaling seems to be the only option.

The restriction originated on some ancient hardware no longer relevant.

Do we know the exact origin of this restriction?

@MarkCallow
Copy link
Collaborator

linear scaling

So if the texture is not square you will distort the image by scaling each dimension differently. Is that what you mean?

Do we know the exact origin of this restriction?

It’s because of ANGLE_texture_compression_dxt.txt. This spec. does not give any reason for the additional size restrictions. One of its authors says "which apparently surfaced some d3d9 restrictions, IIRC." There seems no good reason not to have an updated version of the extension without the restrictions.

@zeux
Copy link
Contributor Author

zeux commented Jul 14, 2020

That doesn't meet my definition of reasonable. Do you distort the image, crop it or pad it? If the latter it has to be communicated to the rendering code somehow so it can adjust the texture coordinates.

You scale the image ("distort"?). This changes the pixel aspect ratio of the image, but it doesn't change the rendered result (short of filtering artifacts) because the 0..1 UV space doesn't change. This is completely standard in the real-time rendering world (or was, until non-power-of-two textures became ubiquitous unless you need to target ES2 class hardware).

@kenrussell
Copy link
Member

I hadn't realized the consequences of the WebGL S3TC limitations - that it's forcing all textures processed by the Basis Universal and KTX supercompression pipelines to be power-of-two.

Filed https://bugs.chromium.org/p/angleproject/issues/detail?id=4841 about publishing a new extension which lifts the implicit power-of-two restrictions in ANGLE_texture_compression_dxt. As soon as that's published we'll expose it in WebGL implementations.

Note that it will take time for that to propagate through the ecosystem, and users will still need the option of targeting older systems that don't support it.

Could the KTX toolchain please offer a --webgl or similar command line option which will scale up input textures' widths and heights to the next greater power of two? It could be relaxed to something like --webgl-npot later.

@arpu
Copy link

arpu commented Aug 20, 2020

would be nice to get this in toktx, i hit this problem on a simple glb plane with a image

the optional -webgl command line would be optimal

@zeux
Copy link
Contributor Author

zeux commented Nov 23, 2021

gltfpack uses image scaling functionality to work around this so I'm going to close this as the caller has control over this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants