Skip to content

Commit d7b59cc

Browse files
committed
MergeGroups initial docs
1 parent 52a3ce1 commit d7b59cc

File tree

3 files changed

+272
-0
lines changed

3 files changed

+272
-0
lines changed
8.17 KB
Loading

tutorials/3d/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@
2121
procedural_geometry/index
2222
occluders
2323
portals/index
24+
merge_groups
2425
3d_text

tutorials/3d/merge_groups.rst

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
.. _doc_merge_groups:
2+
3+
MergeGroups
4+
===========
5+
6+
The ``MergeGroup`` node allows the user to merge similar meshes so that they can
7+
be grouped into a smaller number of nodes, and render using a single draw call
8+
(per :ref:`Material <class_Material>`). This can greatly increase performance when
9+
used with care.
10+
11+
Explanation
12+
-----------
13+
14+
Usually individual meshes in Godot are represented by their own
15+
:ref:`VisualInstance <class_VisualInstance>` in the
16+
:ref:`SceneTree <class_SceneTree>`, such as :ref:`MeshInstance <class_MeshInstance>`.
17+
These:
18+
19+
- Move independently
20+
- Cull independently
21+
- Render individually
22+
23+
In terms of performance however, each ``VisualInstance`` adds a cost, both in
24+
terms of management, and in terms of rendering. Each mesh (and each surface on a
25+
``MeshInstance`` is rendered as an individual mesh) will require an expensive
26+
draw call to the graphics API, and often incur expensive rendering state changes.
27+
28+
If instead we can identify groups of meshes that could be potentially be
29+
rendered together, and merge them ahead of time (either at design time, or
30+
during level load), this can potentially lighten the load on the CPU and GPU,
31+
and increase frame rates.
32+
33+
The merging trade-off
34+
^^^^^^^^^^^^^^^^^^^^^
35+
36+
Lowering draw calls and reducing state changes tends to increase performance.
37+
However, merged meshes are culled as a unit, and therefore if any part of the
38+
merged mesh is visible in the view frustum, the cost of rendering all parts of
39+
the mesh are incurred. For this reason it is recommended that you evaluate
40+
performance both before and after merging, in order to find the best balance in
41+
each case.
42+
43+
.. tip::
44+
Remember that the bottlenecks may be different on different hardware.
45+
Be sure to test on the lowest-end platforms you're targeting for your
46+
project, especially mobile devices and integrated graphics.
47+
48+
Requirements
49+
------------
50+
51+
There are some requirements for any group of meshes to be merged.
52+
53+
The most important requirement is that the source meshes must not move in
54+
relation to each other. They must be either be completely static (non-moving)
55+
or move together only as a single unit. This is because once several meshes are
56+
merged into one, the relative transforms of the source meshes cannot change,
57+
the transforms are baked into the new geometry.
58+
59+
The simplest candidate for merging is static level geometry, such as walls,
60+
floors, tables etc. But groups of meshes that move "as one" are also good
61+
candidates. Examples might be a pirate ship, or spacecraft.
62+
63+
Using MergeGroups
64+
-----------------
65+
66+
After adding a ``MergeGroup`` node into your ``SceneTree``, move all the
67+
VisualInstances you want to be merged so that they are parented by the
68+
``MergeGroup`` (either as children, or grandchildren). By default, if you now
69+
run the scene, the engine will automatically merge suitable meshes as the
70+
``MergeGroup`` enters the ``SceneTree``.
71+
72+
You can change the transform of the ``MergeGroup`` at runtime, and the whole
73+
group will move as a unit (``MergeGroup`` is derived from
74+
:ref:`Spatial <class_Spatial>`, so can be manipulated in all the regular ways,
75+
such as changing transform or visibility).
76+
77+
Mesh similarity
78+
---------------
79+
80+
It is important to note that not all meshes (or more accurately, mesh surfaces,
81+
because merging takes place at the level of mesh surfaces) can be merged
82+
together. There are strict limitations for the mesh surfaces to match.
83+
84+
All the following properties must match for merging to take place:
85+
86+
- Material
87+
- Shadow casting settings
88+
- Visibility
89+
- Layer mask
90+
- Portal settings
91+
- Cull margin
92+
- Lightmap settings
93+
94+
Usually this means only multiple instances of the same mesh will be merged (such
95+
as a group of walls), but similar variations of mesh (e.g. different sized
96+
tables) can sometimes be merged. Additionally, if you reuse materials (using
97+
e.g. a "wood" material in several different meshes), these can often be merged.
98+
99+
Exceptions
100+
----------
101+
102+
When you place a hierarchy of nodes underneath a ``MergeGroup``, such as a
103+
pirate ship, there may be exceptions - meshes that you *do not* want merged.
104+
This may be because, for instance, you may want them to move independently of
105+
the ``MergeGroup``. An example might be a steering wheel, or sail.
106+
107+
Godot allows you fine control over exactly which nodes should be considered for
108+
merging, via the ``merging_mode`` property which is present in the inspector
109+
for every ``Spatial``, inside the ``Misc`` tab.
110+
111+
Merging modes:
112+
113+
- ``Inherit`` - Inherit the setting from the parent. The default for the scene root node is ``On``.
114+
- ``On`` - Change the mode of the node (and any inheriting children) to allow merging.
115+
- ``Off`` - Change the mode of the node (and any inheriting children) to disallow merging.
116+
117+
This means that if you, e.g. set the mode of a steering wheel to ``Off``, it
118+
will not be considered for merging, and neither will any children or
119+
grandchildren of the steering wheel (unless one of them explicitly reactivates
120+
merging with an ``On`` ``merge_mode``).
121+
122+
123+
Ways to use MergeGroups
124+
-----------------------
125+
126+
There are three ways to use MergeGroups:
127+
128+
AutoMerge
129+
^^^^^^^^^
130+
131+
The ``MergeGroup`` will attempt to merge any descendent merges as it enters the
132+
``SceneTree``.
133+
This is the simplest method, and the best introduction to merging.
134+
135+
Baking in the Editor
136+
^^^^^^^^^^^^^^^^^^^^
137+
138+
When the ``MergeGroup`` is selected in the editor, a new ``bake`` button should
139+
appear in the toolbar. This allows you to bake the entire merged scene out to a
140+
file (.tscn (text scene) or .scn (binary scene)) at *design time* rather than at
141+
*runtime*. This can be used creatively to build sensible composite objects which
142+
are later used to compose a game level (this general approach is often known as
143+
"kitbashing").
144+
145+
Additionally, baking in advance offers a great way to preview what will happen
146+
when merging at runtime. It allows you to open the merged scene, and see which
147+
meshes were successfully merged, and which were problematic.
148+
149+
.. figure:: img/bake_merge_group.webp
150+
:align: center
151+
152+
Pros
153+
~~~~
154+
155+
- Allows you easily see the results of merging
156+
- Allows you to further build levels using these merged scenes
157+
- No time is taken by the merging process at runtime
158+
159+
Cons
160+
~~~~
161+
162+
- Merged scenes typically require substantially more storage than the original meshes
163+
- The size of your exported game will likely increase
164+
- Larger merged scenes may take longer to load
165+
- Larger merged scenes may take up more RAM at runtime, especially on the GPU
166+
167+
If you merge, e.g. 10 boxes, the merged scene will have to store 10 times as
168+
much geometry data, as the polygons are duplicated. More storage means your
169+
exported game will be larger, the data will take longer to load, and consume
170+
more RAM at runtime. For this reason, baking in advance tends to be more
171+
practical with low poly meshes and art styles.
172+
173+
.. tip::
174+
Due to the increased storage requirements, it is recommended that, wherever possible,
175+
you bake scenes in binary format (``.scn``) rather than text (``.tscn``).
176+
This is because binary scenes are much more compact in terms of storage,
177+
while also being faster to load and save.
178+
179+
Manually at runtime
180+
^^^^^^^^^^^^^^^^^^^
181+
182+
If the ``automerge`` property of a ``MergeGroup`` is disabled, then the node
183+
will do nothing at runtime until you call its ``merge_meshes()`` function.
184+
Triggering merging manually in this way has two major use cases:
185+
186+
1. Procedural levels. If you place objects (e.g. trees, boxes) at runtime using
187+
script, rather than placing them at design time, then you want a way to *delay*
188+
merging until after your placement is complete. Manually calling
189+
``merge_meshes()`` allows this.
190+
2. Merging parameters. These can be set via the ``MergeGroup::set_param()`` and
191+
``MergeGroup::set_param_enabled()`` functions, prior to calling
192+
``merge_meshes()``.
193+
194+
Merging parameters
195+
------------------
196+
197+
Although the default operation of the ``MergeGroup`` works well in many
198+
circumstances, there are a number of parameters which can be altered prior to
199+
merging in order to access more advanced features. These can be set via the
200+
``MergeGroup::set_param()`` functions, however the easiest way to visualize them
201+
is via the ``bake`` method, which displays a dialog allowing you to modify
202+
parameters. These are described in detail in the documentation for
203+
``MergeGroup``.
204+
205+
Merging by locality - grouping and splitting
206+
--------------------------------------------
207+
208+
When merging large numbers of meshes across a large map, sometimes the merging
209+
goes too far, and results in a huge mesh that is too difficult to cull (as part
210+
is always in the view frustum).
211+
212+
For example if you merge every tree in a forest, regardless of your viewpoint,
213+
the whole forest will be rendered. Although rendering each tree individually
214+
would be inefficient, rendering the whole forest in all cases is also
215+
inefficient, but in a different way.
216+
217+
You may think instead to create several ``MergeGroups`` spread across the
218+
forest, and only merge the trees in the local area. This would create an ideal
219+
balance between reduced drawcalls, but still allowing broad scale culling to
220+
take effect. The downside is that this kind of thing could be extremely labour
221+
intensive in terms of scene design.
222+
223+
For this reason, ``MergeGroup`` has built in functionality for helping deal with
224+
this problem automatically.
225+
226+
.. note::
227+
Grouping and splitting is considered advanced, so is only available via the
228+
manual method (setting parameters and calling ``merge_meshes()`` explicitly),
229+
or via the bake method.
230+
231+
Grouping
232+
^^^^^^^^
233+
234+
One of the simplest ways to get the advantages of merging without the
235+
disadvantages of loss of culling resolution is grouping. The ``group_size``
236+
parameter defaults to zero, which indicates that all suitable meshes be merged.
237+
But if you set ``group_size`` to e.g. 2, then only the closest pairs of meshes
238+
will be merged.
239+
240+
If you have 10 trees, it will try to merge 5 pairs of trees, with each pair
241+
being as close together as possible (so that they can be culled efficiently).
242+
This same principle works even in a forest of 1,000 trees.
243+
244+
Splitting
245+
^^^^^^^^^
246+
247+
The alternative approach to grouping is splitting. Splitting takes place as a
248+
post-step, *after* all the meshes have been merged.
249+
250+
Following our forest example, if we assume our 1,000 tree forest has been merged
251+
into 1 huge mesh, splitting allows us to specify a 3D grid (with a horizontal
252+
number of splits and vertical number of splits) and the ``MergeGroup`` will
253+
attempt to split the large mesh into smaller ones more suitable for culling.
254+
255+
For example, with 5 horizontal splits and 1 vertical split we should get 25
256+
final meshes (5 x 5 x 1) which should give us enough resolution for some decent
257+
culling for our forest.
258+
259+
.. note::
260+
The reason for allowing separate horizontal and vertical splits is that
261+
many games are based on flat ground, where horizontal splits may be more
262+
important than vertical. Increasing vertical splits may be counter-productive.
263+
.. tip::
264+
Splitting can make a lot of sense if you are building a world with voxels.
265+
266+
Other functionality
267+
^^^^^^^^^^^^^^^^^^^
268+
269+
Also via the ``MergeGroup`` parameters, ``CSG`` nodes (e.g. :ref:`CSGBox <class_CSGBox>`)
270+
and :ref:`GridMap <class_GridMap>` nodes can optionally be converted to a regular
271+
:ref:`MeshInstance <class_MeshInstance>`. This allows them to be merged like any other mesh.

0 commit comments

Comments
 (0)