More scenes are shadow casters for shadow volumes out-of-the-box, because of the auto-detection of 2-manifold scenes

Demo from Delphi Summit 2025, with shadows
Demo from Delphi Summit 2025, with shadows
Alpaca, bull, shadows and WholeSceneManifold
Throwing chickens demo

(Yes, it’s a 3rd news about Castle Game Engine in 3 days. More to come — we have a backlog of things to announce! Brace yourselves 🙂 )

We introduced an algorithm to detect 2-manifold scenes better, meaning that all scenes that are really 2-manifold (even if not all shapes inside are 2-manifold) are automatically shadow casters for shadow volumes.

This improves shadow volumes usage experience. You no longer have to mark such scenes with TCastleRenderOptions.WholeSceneManifold.

OK, I can see that the above description, while correct, may be confusing if you’re not familiar with how shadow volumes work. Let’s unpack this slowly 🙂

  • Shadow volumes is one of the algorithms to achieve shadows using Castle Game Engine. It’s right now the simplest one to use, you only need to have 2-manifold models and then flip the Shadows checkbox at the light source to true.
    • Note: The “simplest shadows algorithm to use” award will likely change to shadow maps in the future, once we implement a few improvements to it. See also recent news post about shadow maps plans.

    • But even then, both algorithms (shadow volumes and shadow maps) will remain useful and available and in our engine. They both have their advantages and disadvantages (how shadows look, performance and possible optimizations, what is valid shadow caster…).

  • For shadow volumes, only 3D objects that are 2-manifold can cast shadows. 2-manifold means that each edge has 2 neighbor faces. This is the most natural state for 3D models that represent real things, that have a volume and are watertight, though in practice many 3D models have only most edges with 2 neighbors. The shadow volumes algorithm strictly requires that all the edges of things that cast shadows have 2 neighbors.

  • We allowed already 2 ways to cope with 2-manifold requirement: either make all shapes 2-manifold, or use TCastleRenderOptions.WholeSceneManifold to treat whole scene (unchecked) as 2-manifold.

    • BTW, what is a “shape”? Shape is part of the scene, the simplest unit passed to the GPU.
      • In glTF, it’s a primitive.
      • n Blender, it’s a subset of Blender’s object with a single material.
      • In X3D, it’s literally the X3D Shape node, loaded to TShapeNode instance in our engine.

The new improvements means that you don’t need to touch TCastleRenderOptions.WholeSceneManifold if the scene is already 2-manifold.

Now, using the TCastleRenderOptions.WholeSceneManifold is only necessary if:

  • You want to force the scene to be shadow caster for shadow volumes, even if it was not detected as 2-manifold, Beware that rendering artifacts are possible in this case. However, we did find a number of cases when this forcing actually works properly (at least for the camera position/orientations that mattered in a given demo), despite scene not being a correct 2-manifold.

  • Or if you just want to speed up loading. Marking scene as TCastleRenderOptions.WholeSceneManifold avoids any automatic detection, the appropriate check “passes automatically”.

We took care to check that this auto-detection doesn’t cause any issues:

  • We checked it doesn’t cause unnecessary slowdown. We time it, showing in log if it would take more time > 0.01 sec (it never did in our tests).

  • We checked it doesn’t cause problems due to per-shape TCastleScene.DistanceCulling being disabled on scenes that are 2-manifold, but when shapes are not 2-manifold. The per-shape TCastleScene.DistanceCulling check is now really only done when shadow volumes are used, and scene is shadow caster, and whole scene is 2-manifold (but some shapes are not 2-manifold).

We have updated example on examples/viewport_and_scenes/shadow_volumes_whole_scene_manifold, along with README description and screenshots inside. Part of this demo now works “out of the box”, alpaca model is automatically a shadow caster.

We also updated documentation about shadow volumes. Many things have been upgraded, and naturally the section about 2-manifold objects (when they are detected, and when is RenderOptions.WholeSceneManifold useful) has been rewritten to reflect the current state.

We also updated the Castle Model Viewer menu “Help -> 2-Manifold Information (Shadow Volumes Casting)”. New colors of edges:

  • yellow: manifold edges in the same shape, so this edge connects 2 faces within the same shape.
  • white: manifold edges in the whole scene, so this edge connects 2 faces from different shapes.
  • blue: border edge that doesn’t have 2 face neighbors. If you have this, this scene cannot be (reliably) a shadow caster for shadow volumes, because it is not 2-manifold.

Testing shows that this detection makes sense in many cases (and avoids you having to toggle dangerous TCastleRenderOptions.WholeSceneManifold) but also it fails in many cases (so TCastleRenderOptions.WholeSceneManifold still has a use-case, there are often no noticeable artifacts despite model not being 2-manifold).

All in all, testing shows it’s a benefit, and doesn’t have any drawbacks 🙂

Sadly, it doesn’t mean we can get rid of TCastleRenderOptions.WholeSceneManifold (it would be nice to get rid of this dangerous checkbox, but it still makes sense).

Test it on your own projects and let us know (e.g. in the comments on the forum) how it works for you!

And if you like this work, please support us on Patreon. Thank you!

3 Likes

I would just force my terrain to manifold with WholeSceneManifold and never had issues. This sounds like a great update, but I gave up on volumetric shadows. Maybe they will be good for vehicles that move whenever I get back to them. I eagerly await the update for shadow maps.

1 Like