How to preload mesh/materials so that there isn't stutter when a model enters the camera view?

@bghgary should it not be the case with GLTF/GLB already ???

You can set this on the glTF loader and it will wait for the shader compilation to finish before returning.

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

1 Like

This change still seems to have the stutter when the object first enters the view.

It doesn’t for me. Maybe you can capture a performance profile and see what the stutter is?

The stutter is reduced from what it was previously (~5-6 frame loss), but there is still a consistent 1 frame loss right before the object comes on screen. I created a screen capture, and the frame drop can be noticed at frame 151, where the same frame is repeated twice. It’s such a quick drop that the FPS counter and the performance monitor don’t show any major issue. (7.5 KB)

If I manually call mesh.render on everything at the start, that seems to resolve the remaining 1 frame hiccup, although this feels hacky.

@sebavan Any ideas? I added some logging and it doesn’t appear to be compiling shaders when the stutter happens.

Can you try setting alwaysSelectAsActiveMesh to true on all the loaded meshes ?

This could also be related to Garbage Collection. Is it happening only in the playground ?

Can you try setting alwaysSelectAsActiveMesh to true on all the loaded meshes ?

This is more of a “passive” solution, as assigning alwaysSelectAsActiveMesh doesn’t immediately trigger the lag, it queues it up for later in the rendering process. Contrast this with the mesh.render hack I mentioned above, which occurs instantly. So it does seem to make the lag not happen later on, but I would prefer if it could be invoked immediately.

Additionally, the side effect of disabling frustum clipping test is probably not desirable in the general use case.

Is it happening only in the playground ?

Same thing happens on a local test webpage I set up using the same code.

Ok so the last step is doing a perf capture in Edge or Chrome during the loading so we could spot the delay and see where it is hanging as I can unfortunately not repro locally as well :frowning: would be great if you can try this ?

1 Like

I actually already tried a perf capture and it doesn’t seem to repro if the profiler is running. :frowning: Classic heisenbug.

Here is a capture, the spike seems to be at around 900ms, although it’s still unclear why, since it doesn’t exceed the frame time. (2.1 MB)

Are you seeing a stutter when capturing the profile? Looking at the screenshots in your profile, it doesn’t seem to stutter. I also don’t see the stutter when capturing on my machine. I can only repro when not profiling.

I do see the stutter when capturing, although you’re right that the capture doesn’t seem to reflect that there is an issue.

I was able to resolve my loading issues by tracing all calls to ThinEngine._compileRawShader to see what functions were incurring shader compilation, and then preloading materials by manually calling Mesh.isReady. Various mesh and material properties sometimes had to be adjusted to get the desired shader variant to compile.

That’s odd. I did something similar and didn’t see any shaders being compiled. This is a probably a bug if you have compileMaterials already set on the glTF loader.

I had several use cases where I would adjust material properties after loading the GLTFs which would trigger a shader recompilation, which I wanted to perform in advance. And I could do the same thing for creating meshes dynamically, for example via BABYLON.MeshBuilder.CreatePlane.

Ahh, if you modify the material after load, then that’s different. You may consider calling material.forceCompilationAsync instead of Mesh.isReady.

1 Like

Cross-linking another thread with some other info on this topic, in case anyone else stumbles onto this: