Frustrum / occlusion culling


I would like to ask, are you implementing for large scenes with many entities any kind of culling for hidden objects?

Firstly frustrum culling for objects not in the camera window and secondly anything regarding occlusion culling, objects hidden by other objects?


Frustum Culling is already available, and is a simple tick on a camera.

Currently there is no culling API’s and it is very a case specific.
There are many options that could work here, and many things could be implemented.

For outdoors some depth based occlusion to check if something os fully behind something else could work.
For indoors there are many techniques, one of them is sectors+portals, which actually you can do yourself by making 2 level graph of rooms (boundingbox of a room) and all entities within that room.
Then you have to make portals between sectors and know the state of a portal (open/close) and position, so that you know which connected rooms has to be visible or hidden.

Or toy might go another options which there is vast variety of.

So because there are many different occlusion techniques and they all are case specific, we haven’t implemented any particular. We might implement better interface that will help altering culling states of things, and allow to access culling state from scripts, so that you can prevent some costly logic if it is not needed when entity is not seen.

Thank you Max, that was a comprehensive reply.

Looking forward as well for the script culling idea.

Best regards,

Hi @max,

Would a single FBX/json with 3 meshes consider the separate meshes for frustum culling?


  • BJörn


If you inspect the Model asset in Playcanvas editor, you can see how many meshInstances it consist of. Each pc.MeshInstance is individually frustum culled by default by the camera unless you explicitly specify them as _..cull=false by code. (see documentation)

You may perform your own manual frustum(/whatever) culling algorithm or avoid it altogether (instead of relying on Playcanvas engine’s default approach) by setting the meshInstance to _.cull=true;_.visible=false to flag visibility OFF or _.cull=false;_.visible=true to flag visibility ON (you normally do this with a layer.onPreCull hook if doing your own frustum culling, or you may simply alter visibilities whenever required depending on your game’s situation). This isn’t obvious from the documentation though, unless you observe the source code though: . From there, you are able to retrieve the camera’s frustum planes as well from the camera object reference, and translate it to any needed coordinate spaces if needed depending on how you handle culling.

From what i remembered (i might be wrong…) , Playcanvas’ default culling approach uses bounding spheres culling (which is simpler, with just 1 dot product per plane, compared to actual AABB check, though not necessarily very accruate either, without adopting plane masking) My favourite culling approach that I use (if needed) is conservative box+plane masking approach as described in : , but again, it largely depends on the needs/structure of your app. Sometimes, not having any culling calculations might simply be the best.

1 Like

Hi Max. How could I work out the depth based occlusion in playcanvas. I understand the concept but I have no idea of how to set it up. Thanks

You probably would need to read up online on publications on that topic.

Couldn’t you use raycast first for the outer and inner bounds of a camera, and whichever is hit it is enabled? Like make a hitbox collision entity for large meshes, and only enable them when in bounds of certain raycasts that extend around the diameter and inner part of the camera so that entities behind the big mesh are not rendered?

Or simplier, add collision cone mesh to match the FOV of camera but slightly bigger, then have a bounding box parent entity and its model child, when parent hitbox is inside of collision enable child other wise disable it?