使用 ImmediateMesh
ImmediateMesh 是一个使用 OpenGL 1.x 风格的 API 创建动态几何体的便捷工具。这使得它对于需要每帧更新的网格来说,既易于使用又高效。
使用这个工具生成复杂的几何体(几千个顶点)效率很低,即使只做一次。相反,它的设计是为了生成每一帧变化的简单几何体。
首先,你需要创建一个 MeshInstance3D 并在检查其中向其添加一个 ImmediateMesh。
接下来,将脚本添加到 MeshInstance3D 上。如果你希望 ImmediateMesh 每帧都更新,则应该把 ImmediateMesh 的代码放在 _process()
函数中;如果你想创建一次网格体而后不再更新它,则代码应放在 _ready()
函数中。如果仅生成一次表面,则 ImmediateMesh 与任何其他类型的网格一样高效,因为生成的网格会被缓存并重用。
必须调用 surface_begin()
才能开始生成几何体 。surface_begin()
将一个 PrimitiveType
作为参数。PrimitiveType
(图元类型)指示 GPU 如何根据给定的顶点来安排图元,可以是三角形、线、点等。完整的列表可以在 Mesh 的类参考页面中找到。
一旦你调用了 surface_begin()
,就可以开始添加顶点了。每次添加一个顶点,首先使用 surface_set_****()
(例如 surface_set_normal()
)添加顶点的特定属性,如法线或 UV。然后调用 surface_add_vertex()
来添加一个带有这些属性的顶点。例如:
GDScript
# 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()
函数中绘制了一个三角形。
GDScript
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()
The ImmediateMesh can also be used across frames. Each time you call surface_begin()
and surface_end()
, you are adding a new surface to the ImmediateMesh. If you want to recreate the mesh from scratch each frame, call clear_surfaces()
before calling surface_begin()
.
GDScript
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()
上面的代码将在每个帧里动态地创建并绘制一个表面。