We are currently trying to optimize our project and encountered an issue: If materials with depth prepass are used in combination with scene.freezeActiveMeshes() they appear black.
Here is a playground showing the issue: https://www.babylonjs-playground.com/#1PLV5Z#28
Help would be very appreciated
Freezing meshes is not really compatible with the
That’s because this property render the same mesh two times in a row by changing some engine states in-between. When the mesh is frozen, the resetting of the states is not performed because it is done in a method which is not called anymore when the mesh is frozen. So the mesh is still rendered two times but with the “depth pre pass” engine state each time…
You can try to call the method that handles the state changes yourself after you have frozen the meshes:
Or you can unfreeze the meshes that are using
needDepthPrePass = true.
Thanks for the answer Evgeni_Popov!
Your solution definitely works. I do have one more question though: You mentioned that it is possible to unfreeze the meshes with needDepthPrePass. How can we do it? There is a hidden method _unFreeze that does not work however.
What we are trying to accomplish is quite simple: Fully remove the performance impact of mesh selection which can be quite heavy and unnecessary in scenes where meshes are always visible. We are also aware that with needDepthPrepass the meshes need to be rendered twice but we believe that the freezing logic is not specific enough. We thought that freezeActiveMeshes would avoid the cost of mesh selection (frustum check, LOD selection etc). Maybe a second function would be nice which removes the mesh selection process but still handles the needDepthPrePass state correctly.
You’re right, the
_unfreeze() methods are not meant to be called by the end user, but it’s still working for your use case (they are public). However,
freezeActiveMeshes is doing its work in a deferred callback (namely in
scene.executeWhenReady) so you should do the same thing else
_unFreeze will be called too early:
Frustum check can be avoided by setting
mesh.alwaysSelectAsActiveMesh = true on each mesh or simply by setting
scene.skipFrustumClipping = true at the scene level.
LOD selection does literally no time if the mesh has no LOD, there is a check at the start of the function that returns early.
Things are quite interleaved and so just making freeze + needsDepthPrePass work is not really possible.
What you can do that also work in your use case is to override the
_evaluateActiveMeshes function with en empty function:
Thank you! We have quite a few options now. From our performance tests so far explicitly calling isReadyForSubMesh yields the best results in our case