From d7b59cc148db47806dda4217fd72c3f88cd634fa Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Thu, 8 Feb 2024 11:47:18 +0000 Subject: [PATCH] MergeGroups initial docs --- tutorials/3d/img/bake_merge_group.webp | Bin 0 -> 8368 bytes tutorials/3d/index.rst | 1 + tutorials/3d/merge_groups.rst | 271 +++++++++++++++++++++++++ 3 files changed, 272 insertions(+) create mode 100644 tutorials/3d/img/bake_merge_group.webp create mode 100644 tutorials/3d/merge_groups.rst diff --git a/tutorials/3d/img/bake_merge_group.webp b/tutorials/3d/img/bake_merge_group.webp new file mode 100644 index 0000000000000000000000000000000000000000..1bcfdab35e4b0d7a241cdcdf2b30e6d2d8d6c9ae GIT binary patch literal 8368 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 literal 0 HcmV?d00001 diff --git a/tutorials/3d/index.rst b/tutorials/3d/index.rst index 542dee9bc..7ecc09e20 100644 --- a/tutorials/3d/index.rst +++ b/tutorials/3d/index.rst @@ -21,4 +21,5 @@ procedural_geometry/index occluders portals/index + merge_groups 3d_text diff --git a/tutorials/3d/merge_groups.rst b/tutorials/3d/merge_groups.rst new file mode 100644 index 000000000..9207e88fd --- /dev/null +++ b/tutorials/3d/merge_groups.rst @@ -0,0 +1,271 @@ +.. _doc_merge_groups: + +MergeGroups +=========== + +The ``MergeGroup`` node allows the user to merge similar meshes so that they can +be grouped into a smaller number of nodes, and render using a single draw call +(per :ref:`Material `). This can greatly increase performance when +used with care. + +Explanation +----------- + +Usually individual meshes in Godot are represented by their own +:ref:`VisualInstance ` in the +:ref:`SceneTree `, such as :ref:`MeshInstance `. +These: + +- Move independently +- Cull independently +- Render individually + +In terms of performance however, each ``VisualInstance`` adds a cost, both in +terms of management, and in terms of rendering. Each mesh (and each surface on a +``MeshInstance`` is rendered as an individual mesh) will require an expensive +draw call to the graphics API, and often incur expensive rendering state changes. + +If instead we can identify groups of meshes that could be potentially be +rendered together, and merge them ahead of time (either at design time, or +during level load), this can potentially lighten the load on the CPU and GPU, +and increase frame rates. + +The merging trade-off +^^^^^^^^^^^^^^^^^^^^^ + +Lowering draw calls and reducing state changes tends to increase performance. +However, merged meshes are culled as a unit, and therefore if any part of the +merged mesh is visible in the view frustum, the cost of rendering all parts of +the mesh are incurred. For this reason it is recommended that you evaluate +performance both before and after merging, in order to find the best balance in +each case. + +.. tip:: + Remember that the bottlenecks may be different on different hardware. + Be sure to test on the lowest-end platforms you're targeting for your + project, especially mobile devices and integrated graphics. + +Requirements +------------ + +There are some requirements for any group of meshes to be merged. + +The most important requirement is that the source meshes must not move in +relation to each other. They must be either be completely static (non-moving) +or move together only as a single unit. This is because once several meshes are +merged into one, the relative transforms of the source meshes cannot change, +the transforms are baked into the new geometry. + +The simplest candidate for merging is static level geometry, such as walls, +floors, tables etc. But groups of meshes that move "as one" are also good +candidates. Examples might be a pirate ship, or spacecraft. + +Using MergeGroups +----------------- + +After adding a ``MergeGroup`` node into your ``SceneTree``, move all the +VisualInstances you want to be merged so that they are parented by the +``MergeGroup`` (either as children, or grandchildren). By default, if you now +run the scene, the engine will automatically merge suitable meshes as the +``MergeGroup`` enters the ``SceneTree``. + +You can change the transform of the ``MergeGroup`` at runtime, and the whole +group will move as a unit (``MergeGroup`` is derived from +:ref:`Spatial `, so can be manipulated in all the regular ways, +such as changing transform or visibility). + +Mesh similarity +--------------- + +It is important to note that not all meshes (or more accurately, mesh surfaces, +because merging takes place at the level of mesh surfaces) can be merged +together. There are strict limitations for the mesh surfaces to match. + +All the following properties must match for merging to take place: + +- Material +- Shadow casting settings +- Visibility +- Layer mask +- Portal settings +- Cull margin +- Lightmap settings + +Usually this means only multiple instances of the same mesh will be merged (such +as a group of walls), but similar variations of mesh (e.g. different sized +tables) can sometimes be merged. Additionally, if you reuse materials (using +e.g. a "wood" material in several different meshes), these can often be merged. + +Exceptions +---------- + +When you place a hierarchy of nodes underneath a ``MergeGroup``, such as a +pirate ship, there may be exceptions - meshes that you *do not* want merged. +This may be because, for instance, you may want them to move independently of +the ``MergeGroup``. An example might be a steering wheel, or sail. + +Godot allows you fine control over exactly which nodes should be considered for +merging, via the ``merging_mode`` property which is present in the inspector +for every ``Spatial``, inside the ``Misc`` tab. + +Merging modes: + +- ``Inherit`` - Inherit the setting from the parent. The default for the scene root node is ``On``. +- ``On`` - Change the mode of the node (and any inheriting children) to allow merging. +- ``Off`` - Change the mode of the node (and any inheriting children) to disallow merging. + +This means that if you, e.g. set the mode of a steering wheel to ``Off``, it +will not be considered for merging, and neither will any children or +grandchildren of the steering wheel (unless one of them explicitly reactivates +merging with an ``On`` ``merge_mode``). + + +Ways to use MergeGroups +----------------------- + +There are three ways to use MergeGroups: + +AutoMerge +^^^^^^^^^ + +The ``MergeGroup`` will attempt to merge any descendent merges as it enters the +``SceneTree``. +This is the simplest method, and the best introduction to merging. + +Baking in the Editor +^^^^^^^^^^^^^^^^^^^^ + +When the ``MergeGroup`` is selected in the editor, a new ``bake`` button should +appear in the toolbar. This allows you to bake the entire merged scene out to a +file (.tscn (text scene) or .scn (binary scene)) at *design time* rather than at +*runtime*. This can be used creatively to build sensible composite objects which +are later used to compose a game level (this general approach is often known as +"kitbashing"). + +Additionally, baking in advance offers a great way to preview what will happen +when merging at runtime. It allows you to open the merged scene, and see which +meshes were successfully merged, and which were problematic. + +.. figure:: img/bake_merge_group.webp + :align: center + +Pros +~~~~ + +- Allows you easily see the results of merging +- Allows you to further build levels using these merged scenes +- No time is taken by the merging process at runtime + +Cons +~~~~ + +- Merged scenes typically require substantially more storage than the original meshes +- The size of your exported game will likely increase +- Larger merged scenes may take longer to load +- Larger merged scenes may take up more RAM at runtime, especially on the GPU + +If you merge, e.g. 10 boxes, the merged scene will have to store 10 times as +much geometry data, as the polygons are duplicated. More storage means your +exported game will be larger, the data will take longer to load, and consume +more RAM at runtime. For this reason, baking in advance tends to be more +practical with low poly meshes and art styles. + +.. tip:: + Due to the increased storage requirements, it is recommended that, wherever possible, + you bake scenes in binary format (``.scn``) rather than text (``.tscn``). + This is because binary scenes are much more compact in terms of storage, + while also being faster to load and save. + +Manually at runtime +^^^^^^^^^^^^^^^^^^^ + +If the ``automerge`` property of a ``MergeGroup`` is disabled, then the node +will do nothing at runtime until you call its ``merge_meshes()`` function. +Triggering merging manually in this way has two major use cases: + +1. Procedural levels. If you place objects (e.g. trees, boxes) at runtime using + script, rather than placing them at design time, then you want a way to *delay* + merging until after your placement is complete. Manually calling + ``merge_meshes()`` allows this. +2. Merging parameters. These can be set via the ``MergeGroup::set_param()`` and + ``MergeGroup::set_param_enabled()`` functions, prior to calling + ``merge_meshes()``. + +Merging parameters +------------------ + +Although the default operation of the ``MergeGroup`` works well in many +circumstances, there are a number of parameters which can be altered prior to +merging in order to access more advanced features. These can be set via the +``MergeGroup::set_param()`` functions, however the easiest way to visualize them +is via the ``bake`` method, which displays a dialog allowing you to modify +parameters. These are described in detail in the documentation for +``MergeGroup``. + +Merging by locality - grouping and splitting +-------------------------------------------- + +When merging large numbers of meshes across a large map, sometimes the merging +goes too far, and results in a huge mesh that is too difficult to cull (as part +is always in the view frustum). + +For example if you merge every tree in a forest, regardless of your viewpoint, +the whole forest will be rendered. Although rendering each tree individually +would be inefficient, rendering the whole forest in all cases is also +inefficient, but in a different way. + +You may think instead to create several ``MergeGroups`` spread across the +forest, and only merge the trees in the local area. This would create an ideal +balance between reduced drawcalls, but still allowing broad scale culling to +take effect. The downside is that this kind of thing could be extremely labour +intensive in terms of scene design. + +For this reason, ``MergeGroup`` has built in functionality for helping deal with +this problem automatically. + +.. note:: + Grouping and splitting is considered advanced, so is only available via the + manual method (setting parameters and calling ``merge_meshes()`` explicitly), + or via the bake method. + +Grouping +^^^^^^^^ + +One of the simplest ways to get the advantages of merging without the +disadvantages of loss of culling resolution is grouping. The ``group_size`` +parameter defaults to zero, which indicates that all suitable meshes be merged. +But if you set ``group_size`` to e.g. 2, then only the closest pairs of meshes +will be merged. + +If you have 10 trees, it will try to merge 5 pairs of trees, with each pair +being as close together as possible (so that they can be culled efficiently). +This same principle works even in a forest of 1,000 trees. + +Splitting +^^^^^^^^^ + +The alternative approach to grouping is splitting. Splitting takes place as a +post-step, *after* all the meshes have been merged. + +Following our forest example, if we assume our 1,000 tree forest has been merged +into 1 huge mesh, splitting allows us to specify a 3D grid (with a horizontal +number of splits and vertical number of splits) and the ``MergeGroup`` will +attempt to split the large mesh into smaller ones more suitable for culling. + +For example, with 5 horizontal splits and 1 vertical split we should get 25 +final meshes (5 x 5 x 1) which should give us enough resolution for some decent +culling for our forest. + +.. note:: + The reason for allowing separate horizontal and vertical splits is that + many games are based on flat ground, where horizontal splits may be more + important than vertical. Increasing vertical splits may be counter-productive. +.. tip:: + Splitting can make a lot of sense if you are building a world with voxels. + +Other functionality +^^^^^^^^^^^^^^^^^^^ + +Also via the ``MergeGroup`` parameters, ``CSG`` nodes (e.g. :ref:`CSGBox `) +and :ref:`GridMap ` nodes can optionally be converted to a regular +:ref:`MeshInstance `. This allows them to be merged like any other mesh.