Request for additional features around occlusion culling

Hi! Sorry again for delay in answering. I read this thread and also What is the overhead in the engine of dynamically adding and removing TCastleScenes? - #6 by DSK and I think I have an understanding what you’re doing. (Thanks for the detailed writeup!)

As for the 2 features you ask for: hm, admittedly neither of them are easy without significant changes to how the occlusion query works now. Read on for my thoughts and idea how to proceed:

Currently, we render this “box for occlusion query” in a somewhat special way, using once prepared TCastleRenderUnlitMesh , with once defined “topology” (RenderBox.SetIndexes(Indexes)). See castle-engine/src/scene/castleinternalocclusionculling.pas at master · castle-engine/castle-engine · GitHub . It is prepared in TOcclusionCullingUtilsRenderer.GLContextOpen there.

Then for each shape we want to query, we do TOcclusionCullingUtilsRenderer.DrawBox. This sets RenderBox.ModelViewProjection, sets vertexes using RenderBox.SetVertexes, renders using RenderBox.Render.

The TCastleRenderUnlitMesh is deliberately a very thin wrapper over a “mesh” concept on GPU. We use it in simple+efficient way (only updating box vertexes and reusing the same TCastleRenderUnlitMesh instance to draw many boxes), because the overhead of drawing “boxes for collision query” has to be minimal. To maximize gains from occlusion query.

So this request would mean you need to supply custom data (indexes and vertexes) and change how TOcclusionCullingUtilsRenderer.DrawBox behaves.

Note that we don’t query (right now) whether the bounding box of the object was visible, if the actual object was visible. When the object was visible, we don’t render the box – we render the actual object, and this will be tested to determine “what to do in next frame”. This can actually cause some noticeable “flapping” in whether we render the object or not – see Occlusion Culling | Manual | Castle Game Engine notes from

Sometimes object state flips between “visible” and “not visible”, making uneven frame render times. This happens when the proper shape is obscured, but its bounding box is not obscured. The issue can in general be ignored — user doesn’t see any “flipping”.

Your request would mean we need to render the “box” (or your custom replacement of it) always, from what I understand.

My overall hesitation here (why I hesitate to “just do it in the engine”) is not really how to solve the 2 details mentioned above, but it’s that we’d somewhat expose to public things that we wanted to keep private. The user should not worry how it works – I like that it’s a matter of flipping the boolean TCastleViewport.OcclusionCulling now. This also allows us to change the rendering code easily, and we’ve done it in the past. Last time when doing this: Big renderer improvements: Correct and automatic blending sorting, more powerful batching (now cross-scene), easier and more reliable occlusion culling and occlusion sorting – Castle Game Engine . Having to maintain additional features is then problematic – they are not used in majority of cases, and they make such renderer refactors much harder, due to having to pass data that is only sometimes actually used.

My proposed solution is to instead delegate this problem to you :slight_smile: That is, to be serious:

The advantages of this approach:

  • you are independent then from CGE features and how we expose occlusion culling.

  • You use TCastleRenderUnlitMesh, which is lean and fast, and you manage it yourself – having freedom to reuse it as much as it makes sense (e.g. if multiple queried object have the same shape).

  • You decide yourself when to query, and with what mesh to query.

Let me know if this makes sense :slight_smile:

1 Like