[Bug] GLTF: Handle URI shader
Krassnig opened this issue · comments
Hi,
this tileset from the city of Vienna contains shaders that are base64 Uri encoded. When you try to execute the code below it crashes:
Sadly you don't see the stack trace that caused the error, so I tried to debug it. In @loaders.gl\gltf\src\lib\extensions\deprecated\KHR_techniques_webgl.ts
in the function resolveTechniques()
(link) there is a TODO: handle URI shader
which is not yet implemented.
Here is a quick fix that happens to work on this specific scenario:
shaders.forEach(shader => {
if (Number.isFinite(shader.bufferView)) {
shader.code = textDecoder.decode(gltfScenegraph.getTypedArrayForBufferView(shader.bufferView));
} else if (typeof shader.uri === 'string' && shader.uri.startsWith('data:application/octet-stream;base64,')) {
const base64 = shader.uri.substring('data:application/octet-stream;base64,'.length);
shader.code = atob(base64);
} else {
throw new Error('KHR_techniques_webgl: no shader code');
}
});
This solution has some limitations as outlined in the MDN Base64.
Here is a minimal script to reproduce the error:
import { Tiles3DLoader } from "@loaders.gl/3d-tiles";
import { load } from "@loaders.gl/core";
import { Tileset3D } from "@loaders.gl/tiles";
import { WebMercatorViewport } from "@deck.gl/core/typed";
main();
async function main() {
// tilset of vienna
const tilesetJson = await load('https://www.wien.gv.at/stadtplan3d/datasource-data/5fd17961-5606-47c0-a955-e56deb6bf388/tileset.json', Tiles3DLoader);
const tileset3d = new Tileset3D(tilesetJson, {
onTileLoad: tile => {
console.info('tile loaded: ', tile);
},
onTileError: error => {
console.warn('tile erred: ', error);
}
});
// center of the city, Stephansdom
tileset3d.selectTiles(new WebMercatorViewport({
width: 1000,
height: 1000,
latitude: 48.20877518529593,
longitude: 16.372505487554207,
zoom: 18
}));
}
Note: For this script to work you need to first disable CORS.
Yes, we have decided to not support the KHR_techniques_webgl WebGL extension (that extension was never ratified and supporting it has many issues).
I realize that there is some vestigial code still in there, ideally it should be removed and a better error message produced, and docs could be clearer.