Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Verwenden von ImmediateMesh

Das ImmediateMesh ist ein praktisches Werkzeug zur Erstellung dynamischer Geometrie unter Verwendung einer OpenGL 1.x-ähnlichen API. Das macht es sowohl einfach zu benutzen als auch effizient für Meshes, die in jedem Frame aktualisiert werden müssen.

Die Erzeugung komplexer Geometrien (mehrere Tausend Vertices) mit diesem Werkzeug ist ineffizient, selbst wenn sie nur einmal durchgeführt wird. Stattdessen ist es darauf ausgelegt, einfache Geometrie zu erzeugen, die sich bei jedem Bild ändert.

Zuerst müssen Sie eine MeshInstance3D erstellen und ihr im Inspektor ein ImmediateMesh hinzufügen.

Als nächstes fügen Sie ein Skript zu der MeshInstance3D hinzu. Der Code für das ImmediateMesh sollte in der _process() Funktion stehen, wenn Sie wollen, dass es bei jedem Frame aktualisiert wird, oder in der _ready() Funktion, wenn Sie das Mesh einmal erzeugen und nicht aktualisieren wollen. Wenn Sie eine Oberfläche nur einmal erzeugen, ist das ImmediateMesh genauso effizient wie jede andere Art von Mesh, da das erzeugte Mesh zwischengespeichert und wiederverwendet wird.

Um mit der Erzeugung von Geometrie zu beginnen, müssen Sie surface_begin() aufrufen. surface_begin() nimmt einen PrimitiveType als Argument. Der PrimitiveType weist die GPU an, wie sie das Primitive basierend auf den angegebenen Vertices anordnen soll, je nachdem ob es sich um Dreiecke, Linien, Punkte, etc. handelt. Eine vollständige Liste kann auf der Mesh-Klassenreferenzseite gefunden werden.

Sobald Sie surface_begin() aufgerufen haben, können Sie mit dem Hinzufügen von Vertices beginnen. Sie fügen Vertices einen nach dem anderen hinzu. Zuerst fügen Sie vertex-spezifische Attribute wie Normalen oder UVs mit surface_set_****() hinzu (z.B. surface_set_normal()). Dann rufen Sie surface_add_vertex() auf, um einen Vertex mit diesen Attributen hinzuzufügen. Zum Beispiel:

# Add a vertex with normal and uv.
surface_set_normal(Vector3(0, 1, 0))
surface_set_uv(Vector2(1, 1))
surface_add_vertex(Vector3(0, 0, 1))

Nur Attribute, die vor dem Aufruf von surface_add_vertex() hinzugefügt wurden, werden in diesen Vertex einbezogen. Wenn Sie ein Attribut zweimal hinzufügen, bevor Sie surface_add_vertex() aufrufen, wird nur der zweite Aufruf verwendet.

Wenn Sie alle Vertices hinzugefügt haben, rufen Sie surface_end() auf, um zu signalisieren, dass Sie die Erzeugung der Oberfläche beendet haben. Sie können surface_begin() und surface_end() mehrfach aufrufen, um mehrere Oberflächen für das Mesh zu erzeugen.

Der folgende Beispielcode zeichnet ein einzelnes Dreieck in der Funktion _ready().

extends MeshInstance3D

func _ready():
    # Begin draw.
    mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)

    # Prepare attributes for add_vertex.
    mesh.surface_set_normal(Vector3(0, 0, 1))
    mesh.surface_set_uv(Vector2(0, 0))
    # Call last for each vertex, adds the above attributes.
    mesh.surface_add_vertex(Vector3(-1, -1, 0))

    mesh.surface_set_normal(Vector3(0, 0, 1))
    mesh.surface_set_uv(Vector2(0, 1))
    mesh.surface_add_vertex(Vector3(-1, 1, 0))

    mesh.surface_set_normal(Vector3(0, 0, 1))
    mesh.surface_set_uv(Vector2(1, 1))
    mesh.surface_add_vertex(Vector3(1, 1, 0))

    # End drawing.
    mesh.surface_end()

Das ImmediateMesh kann auch frameübergreifend verwendet werden. Jedes Mal, wenn Sie surface_begin() und surface_end() aufrufen, fügen Sie eine neue Oberfläche zum ImmediateMesh hinzu. Wenn Sie das Mesh bei jedem Frame von Grund auf neu erstellen wollen, rufen Sie surface_clear() auf, bevor Sie surface_begin() aufrufen.

extends MeshInstance3D

func _process(delta):

    # Clean up before drawing.
    mesh.clear_surfaces()

    # Begin draw.
    mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)

    # Draw mesh.

    # End drawing.
    mesh.surface_end()

Der obige Code erstellt und zeichnet dynamisch eine einzelne Oberfläche pro Frame.