Hello everyone, how are you? I hope you are all well!
I’m trying to improve the performance of the game I’m developing with Babylon (It’s using WebGL at the moment, not WebGPU), and I’m having some problems with freezeActiveMeshes(). The game uses Babylonjs 8.9.0.
I’m currently using the following techniques:
-
All meshes are InstancedMeshes (from tiles to buildings). When I create a building, I create a new transformNode, then I get the meshes and create instances of them. This change had a good impact on performance, especially when I used it on tiles (around 2,700). However, I think I’ll use Thin Instances on tiles, since they are always on screen and only change the alpha value of the color (I haven’t seen if thin instances support alpha yet, but I’ll test it soon)
-
All materials are frozen right after creation, since I don’t need to modify them. I created an alpha and a non-alpha version of each color (currently around 20 materials, but I intend to reduce this to just 2 materials with textures. All meshes share these materials; they are never cloned.
-
All tiles have their world matrix frozen after creation. The world matrix of buildings is frozen as soon as the creation animations are executed.
-
I also made several reductions in post-processing effects, such as reducing everything to 2 samples. I decreased the shadow resolution to 256 (with poisson sampling on). Currently the glowLayer is causing a negative impact of about 10/20 fps when active, but I have disabled it for now. My focus is to get as much FPS as possible so that, when I activate it, this drop is not so problematic.
-
I enabled doNotSyncBoundingInfo for all meshes, since they are not needed in my game currently.
-
I also set scene.autoClear = false and scene.blockMaterialDirtyMechanism = true
There are still some techniques that I want to apply, such as reducing the complexity of the meshes, reducing materials, changing tiles to thin instances, etc. I also tried switching to WebGPU but I didn’t see much difference and I still don’t have enough experience using it, although I want to test it again soon in non-compatibility mode.
However, I noticed that when the city starts to grow (about 50 occupied tiles, for example), my FPS drops from 144 to 85, even if the scene is still and nothing is being updated (no mouse movement, no animations, no code running on update observer, etc).
I performed performance checks in the browser and eliminated everything that could be running and causing the FPS to drop at those times. As you can see below, only the BabylonJS render function is running per frame, and even so, the FPS dropped.
So I decided to test scene.freezeActiveMeshes, since from what I read in several places, this could free up a lot of CPU load. And really, the result is surprising. I gained around 20/30 FPS (it stays around 110/115) even with the city having around 50 buildings or more.
However, when using freezeActiveMeshes I have had several unwanted visual artifacts. Even though I mark all meshes and instances as alwaysSelectAsActiveMesh, there are always times when a mesh simply does not appear, for example when it is created by hovering over a tile, and then, if I hover over the same tile, it appears.
So I modified it to use scene.unfreezeActiveMeshes() before creating new mesh instances, and then freeze them again. Basically, I create all the base meshes, mark them as alwaysSelectAsActiveMesh = true, and use freezeActiveMeshes. Then, when I need to create a building preview or a building, I call unfreezeActiveMeshes, create the nodes and instances, mark alwaysSelectAsActiveMesh = true, and then call freezeActiveMeshes.
It worked in a way, but now it creates some strange artifacts, like ghosting of the buildings in some situations, wireframe mode, etc.
I have not been able to identify what is causing what may be happening here. This seems like an excellent technique for reducing FPS drops, but I think I’m missing something about how to use it correctly.
Could someone with experience in these techniques please give me some guidance? What other techniques would make sense to use in a game like this?
I thank you in advance for your attention. Have a great day!
NOTE: You may have noticed that the FPS drops a lot when I move the mouse. This is because I perform some complex calculations when the mouse passes over a tile, and I haven’t optimized that part yet. But I did several checks to make sure that nothing that happens when moving the mouse is harming the Garbage Collector and causing problems when the scene is static. In fact, even right after the biggest city is loaded, the FPS rate drops a lot, even with the mouse outside the tiles and nothing being executed (just the BabylonJS rendering code).