# Big renderer improvements: Correct and automatic blending sorting, more powerful batching (now cross-scene), easier and more reliable occlusion culling and occlusion sorting

**URL:** https://forum.castle-engine.io/t/big-renderer-improvements-correct-and-automatic-blending-sorting-more-powerful-batching-now-cross-scene-easier-and-more-reliable-occlusion-culling-and-occlusion-sorting/838
**Category:** News
**Created:** [June 30, 2023, 10:23pm UTC](https://forum.castle-engine.io/t/big-renderer-improvements-correct-and-automatic-blending-sorting-more-powerful-batching-now-cross-scene-easier-and-more-reliable-occlusion-culling-and-occlusion-sorting/838 "2023-06-30T22:23:25Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![michalis](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/michalis/32/3_2.png) [@michalis](https://forum.castle-engine.io/u/michalis)
#### Post date: [June 30, 2023, 10:23pm UTC](https://forum.castle-engine.io/t/big-renderer-improvements-correct-and-automatic-blending-sorting-more-powerful-batching-now-cross-scene-easier-and-more-reliable-occlusion-culling-and-occlusion-sorting/838/1 "2023-06-30T22:23:25Z")

</div>

| [![Blending in 2D from &quot;The Unholy Society&quot;](https://forum.castle-engine.io/uploads/default/original/2X/3/3aadc282e60dceaf2efe286724e22a08d024f6bd.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/Zrzut-ekranu-z-2023-06-29-14-48-45.png "Blending in 2D from &quot;The Unholy Society&quot;") |
| [![Blending in 2D from &quot;The Unholy Society&quot;](https://forum.castle-engine.io/uploads/default/original/2X/3/38c2da1a15b608be228d1ff7f3c85e9bac8c1ab1.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/Zrzut-ekranu-z-2023-06-29-14-48-02.png "Blending in 2D from &quot;The Unholy Society&quot;") |
| [![Blending in 2D from &quot;The Unholy Society&quot;](https://forum.castle-engine.io/uploads/default/original/2X/9/950319ea8273cbb8a554f378f12c31c21cab080f.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/Zrzut-ekranu-z-2023-06-29-14-47-21.png "Blending in 2D from &quot;The Unholy Society&quot;") |
| [![Blending in 2D from &quot;Escape from the Universe&quot;](https://forum.castle-engine.io/uploads/default/original/2X/c/caa43ebfcad1222a101dfb9fdb1b79d64ffbe3a3.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/Zrzut-ekranu-z-2023-06-29-14-56-37.png "Blending in 2D from &quot;Escape from the Universe&quot;") |
| [![Blending in 2D from &quot;Escape from the Universe&quot;](https://forum.castle-engine.io/uploads/default/original/2X/1/180b8166aa8e25f94cafa1f854aae316fb44209e.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/Zrzut-ekranu-z-2023-06-29-14-55-36.png "Blending in 2D from &quot;Escape from the Universe&quot;") |
| [![Blending in 2D from &quot;Escape from the Universe&quot;](https://forum.castle-engine.io/uploads/default/original/2X/5/523cb78b201adaf487b16f70c4fb6a488745e60a.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/Zrzut-ekranu-z-2023-06-29-14-55-43.png "Blending in 2D from &quot;Escape from the Universe&quot;") |
| [![FPS game example - solid wireframe](https://forum.castle-engine.io/uploads/default/original/2X/0/0a838a78a35114be3a3c95dd6e56e9623ba5db87.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/Zrzut-ekranu-z-2023-06-28-02-53-12.png "FPS game example - solid wireframe") |
| [![FPS game example](https://forum.castle-engine.io/uploads/default/original/2X/2/2f3885fcc7e071a5b583780780e61e15931e9e57.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/Zrzut-ekranu-z-2023-06-28-02-53-31.png "FPS game example") |
| [![Customized color channels](https://forum.castle-engine.io/uploads/default/original/2X/b/b3ca5651cc58bca7166982c924b1a56a44ea15c5.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/color_channels_box.png "Customized color channels") |
| [![isometric_game with batching](https://forum.castle-engine.io/uploads/default/original/2X/0/0e7ae8bead28cac5276c7ecd1e45b6c190e332ba.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/isometric_game_screenshot.png "isometric\_game with batching") |
| [![Solid wireframe](https://forum.castle-engine.io/uploads/default/original/2X/a/a972a5278d8e1780f1ef230fa9f5b10f892da1d6.png)](https://castle-engine.io/wp/wp-content/uploads/2023/06/Zrzut-ekranu-z-2023-06-28-02-51-51.png "Solid wireframe") |

It’s a pleasure to finally _close_ a big TODO from our [roadmap](https://castle-engine.io/roadmap). This refactor took 122 commits, and it reworks a core rendering code in the engine. This was hard to do but also was a lot of fun — I used this opportunity to do a lot of code simplifications. These simplifications also translate to some performance gains.

## New features / improvements

[Blending sorting](https://castle-engine.io/blending) is now much better:

- It can be controlled using simple `TCastleViewport.BlendingSort`.

- The default is `sortAuto`, which auto-detects and uses best blending sorting for 2D or 3D (depending on camera parameters). For many applications, you should no longer even need to touch this, [blending](https://castle-engine.io/blending) should “just work”. This was tested also with our bigger games [The Unholy Society](https://unholy-society.com/) and [Escape from the Universe](https://cat-astrophe-games.party/escape-universe/).

- The new algorithm sorts all shapes, from all scenes. So it can account for transparent objects transformed in any way (using any hierarchy of `TCastleTransform`) and even for cases when multiple scenes’ shapes may result in mixed order. E.g. some transparent objects on the big (level) `TCastleScene` may be in front, and some behind, transparent objects of some creature `TCastleTransform`.

- To address non-trivial cases we have new `TCastleViewport.OnCustomShapeSort` event. You can define sorting function, using any criteria you want. See `TShapeSortEvent` for details and example event implementation.

Batching is now more powerful and easier to use:

- Batching can be activated by `TCastleViewport.DynamicBatching`, and thus configurable from CGE editor too.

Remember you can invoke in CGE editor _“Edit -\> Show Statistics”_ (F8) to see the rendering statistics. They will reflect batching — the number of rendered shapes will drop.

- Batching now works cross-scenes. That is, shapes from one scene can be merged with shapes from another, unrelated scene, if their de-facto rendering settings (material, texture) match.

- The global variable `DynamicBatching` is deprecated. Prefer to use `TCastleViewport.DynamicBatching`.

[Occlusion culling](https://castle-engine.io/occlusion_culling) is now easier and more powerful:

- Just toggle `TCastleViewport.OcclusionCulling`. There is no per-scene configuration. It’s a trivial checkbox in a viewport, so you can easily test does it gain anything in your case.

It has been activated for [examples/fps\_game/](https://github.com/castle-engine/castle-engine/tree/master/examples/fps_game), our 3D impressive demo. It’s also showcased in [examples/viewport\_and\_scenes/occlusion\_culling](https://github.com/castle-engine/castle-engine/tree/master/examples/viewport_and_scenes/occlusion_culling).

- Fixed to not trust occlusion query when scene is instanced many times in viewport, e.g. using `TCastleTransformReference`.

- Fixed for background (skybox) – the 1-frame delay was too noticeable for the background quads, so we don’t use occlusion culling for skybox sides.

- New `TCastleViewport.OcclusionSort`, with the same options for sorting as [blending](https://castle-engine.io/blending) has. Allows to make occlusion culling even faster.

Others:

- New option `TCastleRenderOptions.InternalColorChannels` exists to limit which RGBA channels are written by rendering given model. Allows for some cool graphic tricks.

Also it was necessary to make tricks that require rendering something only to the depth buffer, without touching the color buffer. See the [fixed\_camera\_game](https://github.com/castle-engine/castle-engine/tree/master/examples/deprecated_to_upgrade/fixed_camera_game) example.

For now this property is “internal” — I’m unsure how much it will be actually useful, and we want to reserve the right to remove it if it will become too unconvenient to maintain. Admittedly it may work a little weird — it doesn’t write some RGBA channels, but it still writes the depth values, so it’s a little hard to control what is visible behind it. If you find it useful anyway, please [let me know about it](https://castle-engine.io/talk.php) 🙂

- OpenGL resources that are associated with X3D nodes are now stored in much more straightforward way, avoiding lookups using any dictionaries, and avoiding reinitialization when you move scene from one viewport to another. This makes accessing texture resources and screen effects’ shaders a simple and instant operation, instead of previous inefficient search.

## Backward compatibility

This is a [compatibility-breaking change](https://castle-engine.io/coding_conventions#backward_compatibility), no way around it. The old sorting method, that was only sorting inside a scene, was inherently incorrect. Trying to maintain it for backward compatibility would make code really complicated, and API too. So you just have to adjust — set the `TCastleViewport.BlendingSort` if needed.

As always, if you have questions about upgrading, [ask us](https://castle-engine.io/talk.php)!

What we did to address backward compatibility:

- 

- From code: `RenderOptions.BlendingSort` is just removed. Deliberately, there’s no way to sort only within scene now. We always sort within viewport.

- Default `BlendingSort = sortAuto` automatically adjusts to your camera.

## Special considerations for custom rendering

By _“custom rendering”_ I mean here things that override `TCastleTransform.LocalRender` to issue direct OpenGL(ES) commands. For example _Kagamma’s (Trung Le)_ projects:

- [Particle Emitter](https://github.com/Kagamma/cge-3d-particle-emitter), see [news](https://castle-engine.io/wp/2021/08/20/particle-system-updates-with-editing-integrated-inside-cge-editor-and-improvements-to-building-editor-with-custom-components/).
- [Effekseer Integration](https://github.com/Kagamma/cge-effekseer), see [news](https://castle-engine.io/wp/2021/08/22/effekseer-particle-effect-creation-and-runtime-integration/).
- [Spine Runtime for Castle Game Engine](https://github.com/Kagamma/spine-runtimes).

If you perform custom rendering, without using `TCastleScene` nodes, note that things are a bit different now. `TCastleScene.LocalRender` only schedules shapes to be rendered later. So your custom rendering will always happen before the CGE `TCastleScene` rendering, so objects with custom rendering are assumes to be _behind_ for blending. This shouldn’t really matter for rendering non-blending, but it may matter for rendering with blending.

I have a plan to play with it more, to make custom renderers more flexible. In the future, everything, including custom rendering, should make one _“collect stuff for rendering”_ phase, and then all collected things should be executed. Right now, we do more _“collect rendering”_ phases (once for opaque, once for blending) to also avoid breaking too many things for custom rendering algorithms. But it will change — so an optimization on top of existing work, and improvement for custom renderers, is coming.

## Support our work

This was hard, and fun, work 🙂 Like it? Please [support us on Patreon](https://www.patreon.com/castleengine)!
