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

bugfix: ETC1 is not supported with compressedTexSubImage2D() #27162

Merged
merged 1 commit into from
Nov 10, 2023

Conversation

makovkins
Copy link
Contributor

ETC1 is not supported with compressedTexSubImage2D() according to WEBGL_compressed_texture_etc1 extension
(see https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_compressed_texture_etc1)

…g to WEBGL_compressed_texture_etc1 extension
Copy link

github-actions bot commented Nov 9, 2023

📦 Bundle size

Full ESM build, minified and gzipped.

Filesize dev Filesize PR Diff
656.6 kB (162.7 kB) 656.6 kB (162.7 kB) +5 B

🌳 Bundle size after tree-shaking

Minimal build including a renderer, camera, empty scene, and dependencies.

Filesize dev Filesize PR Diff
449.1 kB (108.6 kB) 449.1 kB (108.6 kB) +11 B
@donmccurdy
Copy link
Collaborator

donmccurdy commented Nov 9, 2023

Diff for npm run make-screenshot webgl_loader_texture_ktx:

webgl_loader_texture_ktx

I'm not immediately sure why that demo renders as it does. One limitation of this fix will be that color management and sRGB decoding for ETC1 textures isn't possible without compressedTexSubImage2D. We avoid transcoding from KTX2 to ETC1 on WebGL 2 for that reason, and choose another transcode target instead.

Related:

@makovkins
Copy link
Contributor Author

makovkins commented Nov 9, 2023

compressedTexSubImage2D() with ETC1 format fails on Android devices, webgl outputs an error and doesn't load a texture! See the screenshot below:

image

Yes, I get a color managment problem with sRGB textures in ETC1 format and I have to convert them to linear space manually in a shader. However, the same issue with color management exists for PVRTC textures even without my bugfix. The previous versions of three.js had SRGBToLinear function call in a shader after fetching an srgb texture and everything was fine. In the latest version S3TC (DXT1/5) and ASTC are converted to linear space correctly when textures are loaded but ETC1 and PVRTC - no, they should be converted manually in a shader.

@donmccurdy
Copy link
Collaborator

It's mainly the test failure that I'm concerned about. But re-running the screenshot from the dev branch (without your PR) I also see the same change in the screenshot, so I'm not sure what's going on there.

The previous versions of three.js had SRGBToLinear function call in a shader after fetching an srgb texture and everything was fine...

Yes. Note that I don't expect three.js will bring inline sRGB decoding back, so you'd need to do this decoding manually in your shaders, after your PR. That isn't a blocker for this PR, in my opinion, but should perhaps be a consideration when deciding what texture formats to use.

@makovkins
Copy link
Contributor Author

makovkins commented Nov 9, 2023

I also see the same change in the screenshot, so I'm not sure what's going on there.

I was also surprised to see the change in screenshots!

Yes. Note that I don't expect three.js will bring inline sRGB decoding back, so you'd need to do this decoding manually in your shaders, after your PR. That isn't a blocker for this PR, in my opinion, but should perhaps be a consideration when deciding what texture formats to use.

Decoding manually in a shader is not a problem, I can do it. The problem is that the newer versions break functionality. When upgraded three.js I was very surprised that my content doesn't work at all on Android devices (ETC1) and have the wrong gamma on Apple (PVRTC). I have been developing my software product on three.js for past 4 years and I have a lot of legacy content that is encoded in ETC1 and PVRTC. Yes, three.js has the tests but it doesn't run them on android and ios. And, believe me, every new version breaks something on mobile devices.

@donmccurdy
Copy link
Collaborator

Agreed that we should merge this fix, once we know what's happening with the test failure. It may also be worth logging a warning about ETC1 textures when .colorSpace is SRGBColorSpace or DisplayP3ColorSpace, so users are aware of that limitation (not necessary in this PR).

@mrdoob mrdoob merged commit 147fbd5 into mrdoob:dev Nov 10, 2023
17 of 20 checks passed
@Mugen87
Copy link
Collaborator

Mugen87 commented Nov 10, 2023

I think at some point we should stop support for ETC1.

@donmccurdy
Copy link
Collaborator

donmccurdy commented Nov 10, 2023

Once WebGPU is available on mobile, do we know if ETC1 is expected to work fully (with sRGB support) there?

Repository owner deleted a comment from jabri62018 Nov 10, 2023
@mrdoob
Copy link
Owner

mrdoob commented Nov 14, 2023

@Kangz Any ideas?

@Kangz
Copy link

Kangz commented Nov 14, 2023 via email

@Mugen87
Copy link
Collaborator

Mugen87 commented Nov 14, 2023

That makes me even more confident to deprecate the ETC1 formats.

@donmccurdy
Copy link
Collaborator

Sorry I might be misunderstanding... but if ETC2 is a superset of ETC1, doesn't that mean WebGPU will support ETC1 just fine, and it would be premature for us to deprecate ETC1 support?

Or — and I hope I am not being very dense here 😰 — could ETC1 data be uploaded with ext.COMPRESSED_SRGB8_ETC2 in WebGL 2, so from the user's perspective we fully support ETC1, we just aren't using WEBGL_compressed_texture_etc1 any more?

@Mugen87
Copy link
Collaborator

Mugen87 commented Mar 28, 2024

I want to revisit this issue and give the idea of @donmccurdy a try. Meaning internally using RGB_ETC2_Format even if RGB_ETC1_Format is configured on app level. According to https://www.khronos.org/assets/uploads/developers/library/2012-siggraph-opengl-es-bof/Ericsson-ETC2-SIGGRAPH_Aug12.pdf, slide 10, that should work:

ETC2 is backward compatible with ETC1: If you have an old ETC1 texture, you can load it as an ETC2 texture and the hardware will decode it correctly.

My major motivation behind this change is to get rid of the gl.texImage2D() and gl.compressedTexImage2D() calls and always rely on tex storage. ETC1 is one obstacle here.

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