How to know when everything is done rendering

this has been an issue that has perplexed us off and on. We need to make a simple screenshot once everything is done rendering. What we currently do is await all of the loading of assets and configuration of models/materials/lights. We are using asset container tasks to load mesh/textures etc and are waiting for all assets to load before rendering anything. Also we make sure all materials are compiled.

once all this is done we run the render loop.
What we notice is assets "popping on " during the render loop. To debug this if we render once like this.
scene.render();
we see only a portion of the expected model rendered.

if we run it in the render loop
engine.runRenderLoop(() => instance.babylon.scene.render());
we see the entire model resolve and is a noticeable popping on

so what could be happening here. Obviously at the first iteration of the render loop, not everything is ready to be rendered. We’ve tried looking at the AbstractMesh.onReady() but this doesnt even fire.

Obviously, stuff is not ready on the first render() call. so how do we know what is not ready . Any tips to debug this. Tried running this through spectorjs to see if we could capture this progressive rendering of the scene but spectorjs does not seem to catch this.

if you load and add everything to scene before starting the renderLoop,
something like this might do the job…

scene.onReadyObservable.addOnce(() => {
    scene.onAfterRenderObservable.addOnce(() => {
        BABYLON.ScreenshotTools.CreateScreenshot(engine, camera, {width: 100, height: 100}, (data) => {
            console.log(data)
        });
    });
});

(base64 string in console, shift + click to view screenshot in new tab)

Difficult to tell the exact solution without a PG matching your setup :slight_smile:

5 Likes

thanks, I was hopeful but unfortunately that only results in a pic that is the first part of the model. the model continues to build after the screenshot has been taken and finishes a few seconds later. Any other thoughts? I dont see any shader compilation happening that could be creating a delay. Im at a loss.

why not relying on scene.executeWhenReady ? also a repro would greatly help :slight_smile:

1 Like

tired that. funny thing is scene.executeWhenReady fires right away even before the asset containers are done loading / adding assets to the scene. I’ll see about getting you guys something. stay tuned.

1 Like

sent PM

1 Like

i created a PG setup that sort of works the same as our system and sure enough i cannot repro the issue in the PG.(we are using bjs 5.21).
Things work properly in PG, onAfterRenderObservable fires correctly after the scene has rendered.
Where as in our build it fires too early.

We are using vue3/vite and i swear after moving to that we started to have the problem. Soooo… that is the next area of investigation for us if something with vue3 is screwing with the render thread.

1 Like

You can try doing

BABYLON.SceneLoader.OnPluginActivatedObservable.addOnce(function (loader) {
loader.compileMaterials = true;
});

There are some other suggestions in this thread How to preload mesh/materials so that there isn't stutter when a model enters the camera view? - #19 by kvbh

3 Likes

@jeremy-coleman thank you good sir your hints pointed me in the right direction. It turns out it shaders were still compiling. We do a lot of tweaking of material parameters on the fly. this makes the shaders want to recompile. Looping through the meshes and checking isReady state and then compiling the materials prior to running the render loop is the solution in our case. thank you all.

1 Like