Использование ImmediateMesh
ImmediateMesh — удобный инструмент для создания динамической геометрии с использованием API в стиле OpenGL 1.x. Что делает его доступным в использовании и эффективным для сеток, которые необходимо обновлять в каждом кадре.
Генерация сложной геометрии (несколько тысяч вершин) с помощью этого инструмента неэффективна, даже если выполняется только один раз. Вместо этого он предназначен для создания простой геометрии, которая меняется каждый кадр.
Сначала вам нужно создать MeshInstance3D и добавить к нему ImmediateMesh в Инспекторе.
Затем добавьте скрипт в MeshInstance3D. Код для ImmediateMesh должен быть в функции _process(), если вы хотите, чтобы он обновлял каждый кадр, или в функции _ready(), если вы хотите создать сетку один раз и не обновлять ее. Если вы генерируете поверхность только один раз, ImmediateMesh так же эффективен, как и любой другой тип сетки, поскольку сгенерированная сетка кэшируется и используется повторно.
Чтобы начать создание геометрии, необходимо вызвать surface_begin(). surface_begin() принимает аргумент PrimitiveType. PrimitiveType указывает GPU, как расположить примитив на основе переданных вершин (будь то треугольники, линии, точки и т.д.). Полный список можно найти в документации класса Mesh.
После вызова surface_begin() можно начинать добавлять вершины. Вершины добавляются по одной. Сначала задаются атрибуты конкретной вершины, такие как нормали или UV-координаты, с помощью surface_set_****() (например, surface_set_normal()). Затем вызывается surface_add_vertex() для добавления вершины с этими атрибутами. Например:
# 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))
В вершину включаются только атрибуты, добавленные до вызова surface_add_vertex(). Если вы добавите атрибут дважды перед вызовом surface_add_vertex(), будет использован только второй вызов.
Наконец, после добавления всех вершин вызовите surface_end(), чтобы сигнализировать о завершении создания поверхности. Вы можете вызывать surface_begin() и surface_end() несколько раз для создания нескольких поверхностей для одной сетки.
Пример кода ниже рисует один треугольник в функции _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()
ImmediateMesh также можно использовать между кадрами. Каждый раз, когда вы вызываете surface_begin() и surface_end(), вы добавляете новую поверхность в ImmediateMesh. Если вы хотите воссоздавать сетку с нуля в каждом кадре, вызовите clear_surfaces() перед вызовом surface_begin().
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()
Приведенный выше код будет динамически создавать и рисовать одну поверхность в каждом кадре.