In our project, we hide meshes that have a bounding sphere radius under a specific size. We check this using the onAfterWorldMatrixUpdate observable.
I’ve found that when this is in place, when playing an animation that includes meshes that are initially hidden because of this check, during the first time playing the animation, there seems to be a brief stutter or skip on the animation. Even in cases where the animation is reset and the meshes are hidden again, this does not reoccur, meaning it ONLY happens during the first time playing an animation.
Is this expected behavior, is something wrong with how Babylon is functioning, is there a better way to get this same functionality that I’m not seeing?
I think what’s happening is when the animation first starts, the hidden mesh becomes visible, which causes its material to trigger a shader compile.
I’m not sure what’s the best way to avoid it. I tried using mesh.visibility in https://playground.babylonjs.com/#MH5MCV#24 and it seemed to help on Edge and Chrome, but it made almost no difference on Firefox.
Was working with one of my friends, we came up with another solution that addresses what @docEdub brought up regarding shader compiling.
Ultimately, creating a new mesh with the material of a mesh that would be hidden and adding that to the scene so we could force the shader to be compiled no matter what.
There should not be any difference between isVisible = false and visibility = 0, because if any condition is true, the mesh won’t be considered as visible:
Instead of creating a mesh, at start time, you can call Material.forceCompilation or forceCompilationAsync and wait for the callback / promise to kick in before going on.
Note that visibility is not a boolean, it is a value between 0 and 1 and acts as an alpha value.
@Evgeni_Popov Using forceCompilation and forceCompilationAsync seems like a much better approach, thank you. Unfortunately, I am running into the following error while using it:
pbrBaseMaterial.ts:1885 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘hasThinInstances’)
This error means you are passing undefined for the first parameter of forceCompilation: you should pass the mesh for which the material must be compiled.
You should wait for the compilation to finish: you should pass a parameter for onCompiled and continue only when it has been called.
It’s probably easier to call forceCompilationAsync for all your materials and wait for all the promises to resolve by using await Promise.all(array_of_promises).
That’s not an easy one, because it uses the KHR material transmission extension, which triggers the creation of a render target texture under the hood…
You can do something like this to wait for this RTT to be ready for rendering:
However, this transmission helper uses a setTimeout call (with a 0 timeout) to setup the meshes for this RTT, and you will have to make sure these calls have been handled before calling opaqueTextureReady. The easiest way is to call setTimeout with a small timeout before doing await opaqueTextureReady():
We did successfully get that implemented and resolved the issue, but created another issue at the same time.
There are some instances where scene._transmissionHelper is undefined indefinitely, causing some of our models to never actually render. Any ideas on what could be happening there or how to work past it?