Update performance optimization pages for Godot 4.x

This commit is contained in:
Hugo Locurcio
2023-07-12 00:43:12 +02:00
parent 3c2412dd8f
commit df9bf74ca1
5 changed files with 135 additions and 118 deletions

View File

@@ -1,5 +1,3 @@
:article_outdated: True
.. meta::
:keywords: optimization
@@ -9,7 +7,7 @@ Optimizing 3D performance
=========================
Culling
=======
-------
Godot will automatically perform view frustum culling in order to prevent
rendering objects that are outside the viewport. This works well for games that
@@ -17,7 +15,7 @@ take place in a small area, however things can quickly become problematic in
larger levels.
Occlusion culling
~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^
Walking around a town for example, you may only be able to see a few buildings
in the street you are in, as well as the sky and a few birds flying overhead. As
@@ -29,23 +27,14 @@ than what is visible.
Things aren't quite as bad as they seem, because the Z-buffer usually allows the
GPU to only fully shade the objects that are at the front. This is called *depth
prepass* and is enabled by default in Godot when using the GLES3 renderer.
However, unneeded objects are still reducing performance.
prepass* and is enabled by default in Godot when using the Forward+ or
Compatibility rendering methods. However, unneeded objects are still reducing
performance.
One way we can potentially reduce the amount to be rendered is to take advantage
of occlusion. As of Godot 3.2.2, there is no built in support for occlusion in
Godot. However, with careful design you can still get many of the advantages.
For instance, in our city street scenario, you may be able to work out in advance
that you can only see two other streets, ``B`` and ``C``, from street ``A``.
Streets ``D`` to ``Z`` are hidden. In order to take advantage of occlusion, all
you have to do is work out when your viewer is in street ``A`` (perhaps using
Godot Areas), then you can hide the other streets.
This is a manual version of what is known as a "potentially visible set". It is
a very powerful technique for speeding up rendering. You can also use it to
restrict physics or AI to the local area, and speed these up as well as
rendering.
One way we can potentially reduce the amount to be rendered is to **take advantage
of occlusion**. Godot 4.0 and later offers a new approach to occlusion culling
using occluder nodes. See :ref:`doc_occlusion_culling` for instructions on
setting up occlusion culling in your scene.
.. note::
@@ -54,15 +43,8 @@ rendering.
from seeing too far away, which would decrease performance due to the lost
opportunities for occlusion culling.
Other occlusion techniques
~~~~~~~~~~~~~~~~~~~~~~~~~~
There are other occlusion techniques such as portals, automatic PVS, and
raster-based occlusion culling. Some of these may be available through add-ons
and may be available in core Godot in the future.
Transparent objects
~~~~~~~~~~~~~~~~~~~
-------------------
Godot sorts objects by :ref:`Material <class_Material>` and :ref:`Shader
<class_Shader>` to improve performance. This, however, can not be done with
@@ -76,7 +58,7 @@ For more information, see the :ref:`GPU optimizations <doc_gpu_optimization>`
doc.
Level of detail (LOD)
=====================
---------------------
In some situations, particularly at a distance, it can be a good idea to
**replace complex geometry with simpler versions**. The end user will probably
@@ -85,13 +67,30 @@ in the far distance. There are several strategies for replacing models at
varying distance. You could use lower poly models, or use transparency to
simulate more complex geometry.
Godot 4 offers several ways to control level of detail:
- An automatic approach on mesh import using :ref:`doc_mesh_lod`.
- A manual approach configured in the 3D node using :ref:`doc_visibility_ranges`.
- :ref:`Decals <doc_using_decals>` and :ref:`lights <doc_lights_and_shadows>`
can also benefit from level of detail using their respective
**Distance Fade** properties.
While they can be used independently, these approaches are most effective when
used together. For example, you can set up visibility ranges to hide particle
effects that are too far away from the player to notice. At the same time, you
can rely on mesh LOD to make the particle effect's meshes rendered with less
detail at a distance.
Visibility ranges are also a good way to set up *impostors* for distant geometry
(see below).
Billboards and imposters
~~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^
The simplest version of using transparency to deal with LOD is billboards. For
example, you can use a single transparent quad to represent a tree at distance.
This can be very cheap to render, unless of course, there are many trees in
front of each other. In which case transparency may start eating into fill rate
front of each other. In this case, transparency may start eating into fill rate
(for more information on fill rate, see :ref:`doc_gpu_optimization`).
An alternative is to render not just one tree, but a number of trees together as
@@ -106,7 +105,7 @@ significantly. This can be complex to get working, but may be worth it depending
on the type of project you are making.
Use instancing (MultiMesh)
~~~~~~~~~~~~~~~~~~~~~~~~~~
^^^^^^^^^^^^^^^^^^^^^^^^^^
If several identical objects have to be drawn in the same place or nearby, try
using :ref:`MultiMesh <class_MultiMesh>` instead. MultiMesh allows the drawing
@@ -114,32 +113,46 @@ of many thousands of objects at very little performance cost, making it ideal
for flocks, grass, particles, and anything else where you have thousands of
identical objects.
Also see the :ref:`Using MultiMesh <doc_using_multimesh>` doc.
See also the :ref:`Using MultiMesh <doc_using_multimesh>` documentation.
Bake lighting
=============
-------------
Lighting objects is one of the most costly rendering operations. Realtime
lighting, shadows (especially multiple lights), and GI are especially expensive.
They may simply be too much for lower power mobile devices to handle.
lighting, shadows (especially multiple lights), and
:ref:`global illumination <doc_introduction_to_global_illumination>` are especially
expensive. They may simply be too much for lower power mobile devices to handle.
**Consider using baked lighting**, especially for mobile. This can look fantastic,
but has the downside that it will not be dynamic. Sometimes, this is a trade-off
but has the downside that it will not be dynamic. Sometimes, this is a tradeoff
worth making.
In general, if several lights need to affect a scene, it's best to use
:ref:`doc_using_lightmap_gi`. Baking can also improve the scene quality by adding
indirect light bounces.
See :ref:`doc_using_lightmap_gi` for instructions on using baked lightmaps. For
best performance, you should set lights' bake mode to **Static** as opposed to
the default **Dynamic**, as this will skip real-time lighting on meshes that
have baked lighting.
The downside of lights with the **Static** bake mode is that they can't cast
shadows onto meshes with baked lighting. This can make scenes with outdoor
environments and dynamic objects look flat. A good balance between performance
and quality is to keep **Dynamic** for the :ref:`class_DirectionalLight3D` node,
and use **Static** for most (if not all) omni and spot lights.
Animation and skinning
======================
----------------------
Animation and vertex animation such as skinning and morphing can be very
expensive on some platforms. You may need to lower the polycount considerably
for animated models or limit the number of them on screen at any one time.
for animated models, or limit the number of them on screen at any given time.
You can also reduce the animation rate for distant or occluded meshes, or pause
the animation entirely if the player is unlikely to notice the animation being
stopped.
The :ref:`class_VisibleOnScreenEnabler3D` and :ref:`class_VisibleOnScreenNotifier3D`
nodes can be useful for this purpose.
Large worlds
============
------------
If you are making large worlds, there are different considerations than what you
may be familiar with from smaller games.
@@ -149,6 +162,8 @@ move around the world. This can prevent memory use from getting out of hand, and
also limit the processing needed to the local area.
There may also be rendering and physics glitches due to floating point error in
large worlds. You may be able to use techniques such as orienting the world
around the player (rather than the other way around), or shifting the origin
periodically to keep things centred around ``Vector3(0, 0, 0)``.
large worlds. This can be resolved using :ref:`doc_large_world_coordinates`.
If using large world coordinates is an option, you may be able to use techniques
such as orienting the world around the player (rather than the other way
around), or shifting the origin periodically to keep things centred around
``Vector3(0, 0, 0)``.