On the receiving client, the scene doesn’t load and I get this error whenever the initial meshes imported on the client serializing the scene contains textures:
TypeError: Failed to execute 'texImage2D' on 'WebGL2RenderingContext':
Overload resolution failed.: Unable to load from data:[...serialized scene data]
… although we made sure to wrap our serializing function in a scene.executeWhenReady().
Any idea? Does it have to do with some sort of size limitation?
I think I’ve found the culprit (or part of it at least): for some reason the received serialized scene data is missing the texture’s b64 data, which would explain why it only occurs with textured models:
On the subject of giving you the model: this problem occurs with any model that contains a texture. They load perfectly fine on the client importing them, but the remote clients get the error when trying to load the faulty scene data.
Am I missing some executeWhenReady() somewhere along the process that could cause a data manipulation before the images are readily available?
For reference, here is where I logged the serialized scenes from:
On the sending client:
sceneLoaded(sceneFile: File, babylonScene: Scene) {
babylonScene.executeWhenReady(() => {
const serializedScene = SceneSerializer.Serialize(babylonScene);
const strScene = JSON.stringify(serializedScene);
console.log(serializedScene);
this.broadcastAsset(strScene);
this.setupScene(babylonScene); <-- scene setup includes meshes and materials manipulations, but this shouldn't matter to the sent serialized data-string as it is synchronous or am I mistaken?
});
}
Edit:
If I use console.log(JSON.Parse(strScene)) instead of console.log(serializedScene) on the sending client, I get an object that is similarly missing the texture data. It looks like the serialization happens before the images are loaded ?
Can you put a breakpoint (e.g., debugger;) in executeWhenReady on the sending client and check what’s in babylonScene.meshes and babylonScene.textures?
If you find serialization happens before images are loaded, my next step would be to check how the textures are loaded and if I can obtain the promise objects and do something like
sceneLoaded(sceneFile: File, babylonScene: Scene) {
babylonScene.executeWhenReady(() => Promise.all(listOfPromises).then(() =>
{
const serializedScene = SceneSerializer.Serialize(babylonScene);
const strScene = JSON.stringify(serializedScene);
console.log(serializedScene);
this.broadcastAsset(strScene);
this.setupScene(babylonScene); <-- scene setup includes meshes and materials manipulations, but this shouldn't matter to the sent serialized data-string as it is synchronous or am I mistaken?
}));
}
From looking at babylonScene (using debugger;), it looks like the meshes/images are loaded. I’m not really knowledgeable on the matter, but something that looks off to me is that the textures are still presented as files rather than b64 strings even though we initially set Texture.ForceSerializeBuffers = true;
It looks like a textures loaded from drag and drop might cause the issue, but I am not able to repro locally would be great if you could create a quick repro in the playground.
Should be as simple as a box with a material and a texture the same way you construct them in your code.
@aWeirdo, we are using 5.0.0-alpha.5, but while updating the repro I saw it was also occuring in 5.0.0-alpha.4 (I haven’t tested earlier versions since we need updates/fixes from alpha.4).
@emmbema
Is that with webgpu enabled?
If yes, can you try disabling it?
if possible, can you try with 4.2.0?
It will help pin-point if the issue comes from webgpu update, your setup / if executeWhenReady runs before texture is fully loaded and ready to be read.
Texture.ForceSerializeBuffers wont change the URL of the serialized texture (for easy removing the base64string /reverting to load from url again)
this is not a problem, on load, if base64string exists, url is ignored.
@emmbema could you create a smaller repro in the playground ? it saves the community who is trying to help a lot of time in general. Github repo should be kept only for setup/build issues where there there is no other choice (Else my internet provider would probably keep me out if I was cloning one repo per thread )
We were using the 4.2.0 and we never encountered this error, the textures were serialized and we were able to have them as a base64string in the serialized scene.
I managed to reproduce the error in babylonJS sandbox: https://sandbox.babylonjs.com/
The steps to reproduce are:
1 - import a model (you can use the model shared by @emmbema in his last answer
2 - use these commands in the console to serialize the scene
3 - Notice the empty base64string attribute for each imported texture
Cooool this works as a repro !!! I wonder if it comes from the readTexture being now async. @Evgeni_Popov to double check as I remember you already moved some of them ?
Have you tried stringifying the serialized scene? I too had the data if I just looked at the serialized result without stringifying it or without debugger; to stop the code running. Otherwise I think what you are looking at is the object of the serialized scene that is updated async
As @emmbema and @sebavan said, this is probably due to the fact that the readTexture is now async, Therefore as you can see in the image below, the base64string is now a promise
In the console object of the serialized scene, the promise is fulfilled and the base64string is displayed correctly but when we stringify the same object we don’t have the base64string anymore
Also @aWeirdo I’m not sure if it’s due to a different version of the browser you are using but in your image, the base64String is not labelled as a Promise. could that be the reason why it works even after you stringify it ?
if it must work here and now, (so you can continue your work) you can temporarily add a small delay before stringify… then it should work until it’s fixed
I think it’s my bad, only had a GLB file at hand so it’s handled slightly different, didn’t think about it at the time
I don’t think adding delay will solve this, I think the issue is in the way the JSON library stringify the serialized scene. Since the base64string is now a promise, the JSON library is not waiting for the promise to be resolved to append the base64 to the result (a string) instead it’s just assigning an empty object to the base64string (that’s why in the output we have empty brackets and not an empty string)
Since the texture is now a promise, the only solution I can think of right now is to have an in-built function in babylon to stringify the scene and this function will know that it should wait for the promise of each base64 texture to be resolved.
It happens because json stringify probably run before the promise is returned,
temporarily adding a delay after serializer and before stringify should make it work on your end until a fix is implemented in the core.
to stay backwards compat, i (sadly) think sceneSerializer will have to be updated to block the thread until promises are returned… but this is for the core team to decide
I tried in the sandbox to serialize the scene then wait for approx.1 minute before the stringify and still the same issue, as I said the JSON.stringify line is seeing the base64string attribute as an object and it doesn’t know it should wait for it to be resolved before appending the result of the promise. That’s why I said adding a delay won’t change anything. I’m trying to do it in our app right now but I’m pretty confident it won’t make any difference unfortunately