Hi Labris - thank you very much for your kind reply. It’s happening with all my glbs that have a 12288x12288 texture.
When I export from gltf.report, though, it keeps the high resolution. However, the texture isn’t converting to WebP in gltf.report - it’s staying as a jpeg texture.
I will have a look, probably there is some browser limitation for conversion.
Meahwhile you may do the same transforms in Node.js environment wiith the help of GLTF-Transform CLI which doesn’t depend on browser, may use lossless codec and shouldn’t have such limitations.
Also, be aware that such big textures may lead to crash on non-high-end machines.
I wasn’t able to reproduce this issue with PNG texture 12188x8122 resolution at https://glb.babylonpress.org/ - after optimization I have the same width and height of WEBP texture. How do you export your GLB from there - is it the main export button at the bottom menu bar or Inspector export button?
But I was able to reproduce this issue when exporting from Sandbox with the help of Inspector. In this case the texture becomes 7055x4702. @alexchuber , what do you think about it?
Here is my test file - Babylon.js Playground
To reproduce the Sandbox issue, open the Inspector
I am away right now, so I can’t double check this, but it might be because we use the default quality level (something like 1/2? 127/255?) when re-encoding the image. Check the parameters of ‘DumpData()’ for more info.
When exported from the Inspector, it reduces to 5760x5760.
Still, when exporting after conversion to WEBP at https://glb.babylonpress.org/, it has the same dimensions 12188x12188. @Christopher_East Did you solve your issue or there are any other related questions?
Let me assign to @alexchuber if not urgent so she can have a look when she ll be back next Monday as it sounds like a potential bug. I can have a look if it is urgent.
I don’t think it is urgent since it exists at least from Babylon 5
Still it is strange behavior which a user shouldn’t experience with default settings.
This looks like a hardware limitation related to the offscreen canvas used in DumpData. Even though we set the canvas size to 12188×12188, the actual gl.drawingBufferWidth is being limited to 5760×5760.
From the WebGL spec:
If the requested width or height cannot be satisfied, either when the drawing buffer is first created or when the width and height attributes of the HTMLCanvasElement or OffscreenCanvas are changed, a drawing buffer with smaller dimensions shall be created. The dimensions actually used are implementation dependent and there is no guarantee that a buffer with the same aspect ratio will be created. The actual drawing buffer size can be obtained from the drawingBufferWidth and drawingBufferHeight attributes.
So when exporting via the Sandbox Inspector, the texture gets resized to fit within some hardware limits, which explains the unexpected dimensions.
Now I’m curious, though – @labris how are you converting images to WebP in your app?
Texture resizing and format conversion in https://glb.babylonpress.org/ is performed at array level (without any offscreen canvas) and based on GLTF-Transform compressTexture function.
The actual underlying lib used for image r/w is ndarray-pixels, which uses sharp for node.js, and OffscreenCanvas for browsers.
ImageDecoder might worth a try since it does not define a size limit in spec.
// Create an ImageDecoder instance.
const decoder = new ImageDecoder({
data: file.stream(),
type: file.type,
});
// Make sure decoder tracks are ready.
await decoder.tracks.ready;
// Decode the first available image frame.
const frame = (await decoder.decode()).image;
// Set canvas dimensions based on the decoded image.
canvas.width = frame.displayWidth;
canvas.height = frame.displayHeight;
// Prepare an output buffer.
const pixelCount = frame.displayWidth * frame.displayHeight;
// RGBA pixels: each pixel uses 4 bytes.
const outputBuffer = new Uint8ClampedArray(pixelCount * 4);
// Use the copyTo() method to copy the frame's pixels into our output buffer.
// We specify the desired pixel format ("RGBA").
await frame.copyTo(outputBuffer, { format: "RGBA" });