We’ve been getting into performance and found out that one of the key optimization we can do is reducing draw calls.
Reading into the documentation, we found that Babylon does provide occlusion queries.
As I understood it, occlusion queries help us know if a mesh is occluded or not. But does it also automatically hide the mesh that is occluded (therefore reducing draw calls)? If not, then what would be the proper way to hide meshes?
I’ve created a playground where there are 2 meshes. One that is high on draw calls and another to as hide it.
Important thing: the meshes that must be occlusion queried must be displayed after the meshes that can (potentially) occlude them! The PG in the doc is working because the wall is created before the sphere, so will be displayed before it. In your PG, you should load the wall before the buggy for it to work (or set a renderingGroupId on the buggy meshes which is greater than the renderingGroupId of the wall).
In your case, your buggy is made of a lot of small meshes (250+), so creating an occlusion query for each one will be sub-optimal. I think you should instead create a fake mesh and set its bounding info = bounding info of the buggy and apply the occlusion query on this mesh alone. If the mesh is occluded, call setEnabled(false) on the Buggy root node. Something like:
In this PG, the clear color is green when the buggy is hidden, blue else.
You can use the Mesh.renderingGroupId: set it to 1 for all meshes that must be occlusion queried. As the default value is 0, all other meshes will be displayed before them. Also, don’t forget to call scene.setRenderingAutoClearDepthStencil(1, false, false, false) so that the zbuffer is not cleared between the rendering groups.
Just to clarify I can set all 250 meshes occlusion queries as long as I set their renderingGroupId to 1 correct?
Also, I’ve tried with using the mesh (boundingbox) to set occlusion queries option. But it seems when I go inside a bounding mesh, It is being counted as occluded. (Will try to create a playground) An example of this is If I have a mesh of a room, it would seem that being inside the room counts as occluded therefore hiding the whole mesh.
Yeah basically one of the use case is I should be able to load any model (that can have one or more meshes) and through occlusion culling, only see what is in front of me (In case I’m looking at a wall, it should hide it/not make any draw calls). But then as you mention the tricky part is to determine and make sure that they should be the last one to be rendered. I’ll try to first implement based on our discussion (occluders first, before the occluded mesh) and get back to you
@Evgeni_Popov I tried applying the suggestion you provided (making a fake mesh and applying occlusion query on it) but it seemed that it resulted to look like this:
There seems to be a box in the middle of meshes. I didn’t do any changes (other than setting the position of the fake mesh) but I’m also uncertain which change cause the box to appear. I tried setting the fake meshes visibility to 0 and also its material’s alpha to 0 but that seems to hide the meshes as well.
Would you happen to know if it is possible to remove/hide this sort of box and still have the occlusion query applied to it?
Have you set boxMat.disableColorWrite = true;? Also, you should set boxMat.disableDepthWrite = true; so that the invisible box does not write to the zbuffer.
I have another problem (really sorry to keep having new ones) but I was able to make a playground of it. It seems that the occulsion doesn’t behave in this context. Would you happen to know why?
Link to the playground: https://playground.babylonjs.com/#MQBXQ1#9
It’s a timing problem: the “then” function for the buggy will be called after the one for the wall because the file is bigger, so the buggy will be created before the wall which is wrong: the buggy should be created after the wall so that it is rendered after. Or you can use the renderingGroupId property to overcome the problem:
I’ll try to recreate a playground of it on Monday(Will take a look on the position but I just used the same position from the mesh itself). Thank you so much for the support! Have a nice weekend!
@Evgeni_Popov
I was able to replicate it!. It would seem you are right that it might have something to do with the positions.
Here is the playground https://playground.babylonjs.com/#MQBXQ1#11
The reason why I added the position and the parent is because without it, it would look like this: