Hi, we’ve recently converted our app from Three.js to Babylon, however there are some users who are saying that they get a lower FPS in the Babylon version. I’ve been optimizing various things, but there’s one piece that I can’t seem to sort out… It seems that Babylon’s render() function simply takes double as much CPU, sometimes more, than Three.js’ one… Is there a way to optimize this? I’ve already tried everything in the Optimize Your Scene page…
To test this at the most basic level, I created two examples which both simply create 5000 cubes (going overboard to make it more obvious) and then renders them. On my machine the Three.js version renders at a consistent 13ms per render(), while the Babylon version varies at around 22-34ms per render()…
I have also tried using freezeActiveMeshes() and it brings it down a lot, but not all the way to Three.js’ level, plus we wouldn’t be able to use that anyway since as I understand it, it turns off the detection of which objects are in the frustum for rendering…
Hi, the code for both examples is attached in the first post. I wanted to make a playground, but I don’t think I can wrap a timer around the render() function from inside a playground, the playground seems to call render() on it’s own outside the user’s code…
Ok! so first thanks a lot for the feedback! It helps a lot
So first comment: The test as it is right now is a bit misleading because all meshes have the same matrix and then there is no activity on the 3js front where we do not spend time optimizing for this very specific case. A more “fair” comparison would be to use random position to avoid having the same matrix for all meshes: box.position.set(Math.random(), Math.random(), Math.random())
Then, you are not really comparing apples to apples as our material has more features enabled (box.material.dissableLighting = true has a typo :)). I would recommend using material.freeze() to get a comparable material
With these updates you should get much closer to 3js.
But now we hit the elephant on the room 3js and babylonjs are very different engines with different goals and philosophies. Here you are seeing one difference: bjs has a lot of features available out of the box, easy to use but it comes with a price: a small perf hit
We introduced the scene.freezeActiveMeshes() feature for this specific need: turn off all the bells and whistles to focus on pure rendering.
But I think I don’t understand what an “active” mesh is, then… I thought active meshes were the ones that were in the frustum and so get rendered, but is it something else?
when you call freezeActiveMeshes you are forcing BJS to stop doing a lot of stuff In your case you may not want these things. The active meshes are the rendered meshes. They evolved constantly based on several options (instances, transparency, etc…)
To keep them as precise as possible costs us a lot per frame,hence why having this freezeActiveMeshes is a good option. THis way you are the driver: you decide which mesh is active and the list remains constant. You can force a mesh to be active by setting mesh.alwaysSelectAsActiveMesh = true and you can force it to be inactive with mesh.setEnabled(false) for instance
Hi @Deltakosh, I’ve tried to call unfreezeActiveMeshes();freezeActiveMeshes() every 1 second as a test and it really helps to reduce the CPU usage a lot, like to around ~50% usage. I do see the culling issue, but that’ll be fixed once your PR is on npm I guess…
My question is, is there anything bad about doing this? One issue I have noticed is that it seems to break animated models, is there a way for animations to continue working while it’s frozen? And is there anything else that would be an issue?