I have a test texture (zipped and attached), produced using the toktx utility. When I drag and drop it into sandbox.bablyonjs.com, I get a lovely smooth multi-channel texture which is what I want (screenshot of a single channel):
Any subsequent load results in the same banding, until the page is refreshed. I can reproduce this on Firefox 110, Chrome 110 and Chrome Canary 113 on macOS Ventura 13.1, but interestingly not in Safari 16.2. What is actually happening here? I.e. how is rendering this texture different on first vs subsequent loads?
I ask because I get the same extreme banding in the actual app that I’m using this texture in, and this Sandbox test case seems like it could reveal how to get to that smooth one
Nothing in the console, unfortunately. Could be a macOS thing then? I’m running this on a MacBook Air M2. I will try a few other devices tomorrow, to see if there are some commonalities.
I gathered some more data. The first load of that texture seems to go through the following steps:
babylon.ktx2Decoder.js
zstddec.wasm
uastc_rgba8_unorm_v2.wasm
While the second load goes through:
babylon.ktx2Decoder.js
zstddec.wasm
msc_basis_transcoder.wasm
msc_basis_transcoder.js
This happens on both Firefox and Chrome, whereas Safari loads:
babylon.ktx2Decoder.js
zstddec.wasm
uastc_astc.wasm
And not only does the banding appear on that second load, the image is also Y-flipped. I’ll dig a bit deeper into the KTX2 decoder. Using this playground to repro/debug: https://playground.babylonjs.com/#CUEMB6#10
Indeed, it is not normal for the MSC to be chosen on the second loading. This means that either the loading fails somehow and the data used by the transcoding decision tree is not the right one, or the transcoding decision tree (TDT) itself does not choose the right format for some reason. But I would lean towards the former explanation because the TDT code is quite simple and applies decisions based on the data extracted from the file.
Unfortunately, I can’t debug it myself because I don’t have a Mac…
Oh wow, setting up this to debug is no small feat!
I’m finally in, using latest commit from Babylon.js’ master, and replacing the jsDecoderModule: "http://preview.babylonjs.com/babylon.ktx2Decoder.js" with the localhost version, and now I can dig in a bit more.
First observation is that if I set numWorkers to 0, it will immediately produce that flipped image with banding.
Is it possible that we run out of workers? No, doesn’t look like it.
Update: Oooh I think know what it is!
On second run, that isDirty is no longer true, so those options do not get set here, but the worker gets created from scratch every time:
Update 2: Yes, that’s exactly what happens in the Playground repro.