How does dynamic batching work?

Hello, I was just wondering how does dynamic batching work, and if it works only under certain scenarios? Because within the docs, it is said that two similar objects, with same shader (which is just a material basically right?) should be dynamically batched, thus decrease number of draw calls. But when I am trying to e.g., create a box in Blender, with just some color material and export it either as X3D or GLTF, add multiple instances to the editor, with batching turned on on the viewport, it does nothing. I also have tried creating multiple such boxes (each separate mesh) directly in Blender and export it as a group, which will produce just one 3D file and import it, but it does not work either. Is there something I have overlooked, or does the model need to be exported in a specific way or something else? Or is it available just for 2D images? Thanks.

Batching indeed works only under certain scenarios. We continue to extend these scenarios (e.g. in June 2023 it was extended to be possible in more cases, 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 ).

See the implementation in castle-engine/src/scene/castleinternalbatchshapes.pas at master · castle-engine/castle-engine · GitHub . We do not document elsewhere exactly what scenarios are handled by batching because it would be very complicated to specify it precisely – it would have to almost match the checks from implementation of TBatchShapes.Batch , castle-engine/src/scene/castleinternalbatchshapes.pas at master · castle-engine/castle-engine · GitHub . In short: models should use the same geometry type (all geometries exported from Blender will be just triangles, so you’re good) and same material and textures.

To observe whether batching works in your case, show MyViewport.Statistics on some label, and observe whether the number of rendered shapes drops when you toggle batching. You can also see the stats in CGE editor (press F8) and observe how they change when you change in editor the DynamicBatching property on the viewport.

Various 3D and 2D cases are covered, we definitely want this to cover more and more.

There is one GitHub issue now tracking 3 things that will be evnatually added for batching too : No batching by DynamicBatching when normalIndex, texCoordIndex, Normal node used · Issue #195 · castle-engine/castle-engine · GitHub .

To answer precisely why does the batching not “kick in” in your case, please send a testcase (model from Blender, or just glTF), I can take a look.

Oh, ok, so let’s say I do export just default cube from Blender, with no material as GLTF, or GLB (is there a difference whether it needs to be separate GLTF or binary GLB?) and I add it as a TCastleScene object in editor. If then, I make a copy by TCastleScene.Clone, or by creating new TCastleScene and sharing X3D Graph from the first node, then the batching should kick in or not? Because for example, I have tried export from Blender as X3D and it actually contains texCoordIndex field, so I am not sure than.

The engine can read glTF files with either .gltf or .glb extensions perfectly. They result in the same content for CPU and GPU – they encode the same things.

There may be a small difference in loading time.

  • The .glb file format makes sense only in scenarios when you really need everything (the 1. JSON data, e.g. materials, and 2. binary data, like vertex positions, and 3. any associated data, like textures) to be in single file. Sometimes single file is easier, e.g. to upload to online glTF viewers like https://gltf-viewer.donmccurdy.com/ (this is not made with CGE, just pointing it as an example of great glTF viewer in a browser).
  • For CGE usage, there’s no such requirement usually, your game data is likely already a set of multiple files, so there’s no need to use .glb.
  • And reading a file format in .gltf (which will be commonly accompanied with some binary files and textures in nearby directories) is a tiny bit faster (no need for base64 decoding in one place).

So in short, we recommend using .gltf in CGE, to have a tiny more loading speed, and also to allow sharing textures between a few 3D models. But we support both .gltf and .glb. And in many cases it will not really matter, the loading speed difference will likely be negligible. See our docs: Blender | Creating Game Data | Castle Game Engine .

As for the broader question:

I did a test. Not using the Blender->X3D exporter, which is unfortunately poor in functionality now, but using Blender->glTF exporter (on the CGE side, we still import glTF, and everything else, into X3D nodes).

By default, the glTF exporter adds the Normal node (which we don’t handle with batching), and also texture coordinates (which we handle with batching, but in this case we don’t, as glTF->X3D produces MultiTextureCoordinate node). Once you deactivate “UVs” and “Normals” in glTF export settings (see screenshot) then the cubes are batched.

However, this is not really a workable solution – without normals in glTF file, the cube has generated always smooth normals (so the cube looks with weird lighting on edges). That’s because in glTF, Blender cannot record the “Auto Smooth” value, there’s no equivalent property in glTF from what I know. (So Blender has “Auto Smooth”, and CGE supports “creaseAngle”, but in the middle glTF has no property to transfer this.)

Bottom line: Batching fails now to work correctly and out-of-the-box even for simplest cube exported from Blender. I know it sucks, let me see can I quickly add support :slight_smile: At least support for Normal node during batching would make this case workable.

So: Good point, I’ll get back to this thread, hopefully later this week. I’ll try to add the Normal handling at least.

P.S. Here’s my super-simple test.

To see if batching works, one can just open the design in CGE editor, press F8 to see stats, and then toggle the DynamicBatching. Of course batching will work equally at runtime, not only in editor.

test-batching-blender-gltf.zip (271.1 KB)

( I see I uploaded a version where I even tested with cube+sphere in one .blend. Doesn’t really matter, i.e. conclusions are the same from what I’ve seen, i.e. we can batch multiple meshes if (temporary limitation) they don’t have normals or UVs. If you want to experiment, replace that Blender file with whatever :slight_smile: )