Work in progress

The content of this page was not yet updated for Godot 4.2 and may be outdated. If you know how to improve this page or you can confirm that it's up to date, feel free to open a pull request.

Optimisation à l’aide de MultiMeshes

Pour un grand nombre d'instances (en milliers), qui doivent être traitées en permanence (et qui nécessitent un certain contrôle), utiliser directement les serveurs est l'optimisation recommandée.

Quand la quantité d'objets atteint des centaines de milliers ou même des millions, aucune de ces approches ne reste efficace. Il reste cependant, en fonction des besoins, une optimisation supplémentaire possible.

MultiMeshes

Un MultiMesh est une primitive de dessin unique qui peut dessiner jusqu'à des millions d'objets en une seule fois. Elle est extrêmement efficace car elle utilise le hardware du GPU pour le faire (dans OpenGL ES 2.0, elle est moins efficace car il n'y a pas de support hardware pour elle, cependant).

Le seul inconvénient est qu'il n'y a pas de screen ou frustum culling possible pour les instances individuels. Cela signifie que des millions d'objets seront toujours ou jamais dessinés, en fonction de la visibilité de l'ensemble du MultiMesh. Il est possible de leur fournir un rectangle de visibilité personnalisé, mais il s'agira toujours d'une visibilité tout ou rien.

Si les objets sont suffisamment simples (juste quelques sommets), cela ne pose généralement pas de problème car la plupart des GPU modernes sont optimisés pour ce cas d'utilisation. Une solution de contournement consiste à créer plusieurs MultiMeshes pour différentes régions du monde.

Il est également possible d'exécuter une logique à l'intérieur du shader de sommet (en utilisant les constantes intégrées INSTANCE_ID ou INSTANCE_CUSTOM). Pour un exemple d'animation de milliers d'objets dans un MultiMesh, voir le tutoriel Animation de milliers de poissons. Les informations pour le shader peuvent être fournies par des textures (il existe des formats en virgule flottante Image qui sont idéaux pour cela).

Another alternative is to use a GDExtension and C++, which should be extremely efficient (it's possible to set the entire state for all objects using linear memory via the RenderingServer.multimesh_set_buffer() function). This way, the array can be created with multiple threads, then set in one call, providing high cache efficiency.

Enfin, il n'est pas nécessaire que toutes les instances MultiMesh soient visibles. Le nombre d'instances visibles peut être contrôlé avec la propriété MultiMesh.visible_instance_count. Le flux de travail typique consiste à allouer le nombre maximal d'instances qui seront utilisées, puis de modifier la quantité visible en fonction de combien sont actuellement nécessaire.

Exemple Multimesh

Voici un exemple d'utilisation d'un MultiMesh depuis du code. Les langages autres que GDScript peuvent être plus efficaces pour des millions d'objets, mais pour quelques milliers, GDScript devrait convenir.

extends MultiMeshInstance3D


func _ready():
    # Create the multimesh.
    multimesh = MultiMesh.new()
    # Set the format first.
    multimesh.transform_format = MultiMesh.TRANSFORM_3D
    # Then resize (otherwise, changing the format is not allowed).
    multimesh.instance_count = 10000
    # Maybe not all of them should be visible at first.
    multimesh.visible_instance_count = 1000

    # Set the transform of the instances.
    for i in multimesh.visible_instance_count:
        multimesh.set_instance_transform(i, Transform3D(Basis(), Vector3(i * 20, 0, 0)))