mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-03 05:48:42 +03:00
MergeGroups initial docs
This commit is contained in:
BIN
tutorials/3d/img/bake_merge_group.webp
Normal file
BIN
tutorials/3d/img/bake_merge_group.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
@@ -21,4 +21,5 @@
|
||||
procedural_geometry/index
|
||||
occluders
|
||||
portals/index
|
||||
merge_groups
|
||||
3d_text
|
||||
|
||||
271
tutorials/3d/merge_groups.rst
Normal file
271
tutorials/3d/merge_groups.rst
Normal file
@@ -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 <class_Material>`). This can greatly increase performance when
|
||||
used with care.
|
||||
|
||||
Explanation
|
||||
-----------
|
||||
|
||||
Usually individual meshes in Godot are represented by their own
|
||||
:ref:`VisualInstance <class_VisualInstance>` in the
|
||||
:ref:`SceneTree <class_SceneTree>`, such as :ref:`MeshInstance <class_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 <class_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 <class_CSGBox>`)
|
||||
and :ref:`GridMap <class_GridMap>` nodes can optionally be converted to a regular
|
||||
:ref:`MeshInstance <class_MeshInstance>`. This allows them to be merged like any other mesh.
|
||||
Reference in New Issue
Block a user