Up to date
This page is up to date for Godot 4.3
.
If you still find outdated information, please open an issue.
Using the SurfaceTool¶
The SurfaceTool provides a useful interface for constructing geometry. The interface is similar to the ImmediateMesh class. You set each per-vertex attribute (e.g. normal, uv, color) and then when you add a vertex it captures the attributes.
The SurfaceTool also provides some useful helper functions like index()
and generate_normals()
.
Attributes are added before each vertex is added:
st.set_normal() # Overwritten by normal below.
st.set_normal() # Added to next vertex.
st.set_color() # Added to next vertex.
st.add_vertex() # Captures normal and color above.
st.set_normal() # Normal never added to a vertex.
st.SetNormal(); // Overwritten by normal below.
st.SetNormal(); // Added to next vertex.
st.SetColor(); // Added to next vertex.
st.AddVertex(); // Captures normal and color above.
st.SetNormal(); // Normal never added to a vertex.
When finished generating your geometry with the SurfaceTool
call commit()
to finish generating the mesh. If an ArrayMesh is passed
to commit()
then it appends a new surface to the end of the ArrayMesh. While if nothing is passed
in, commit()
returns an ArrayMesh.
st.commit(mesh)
# Or:
var mesh = st.commit()
st.Commit(mesh);
// Or:
var mesh = st.Commit();
Code creates a triangle with indices
var st = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
# Prepare attributes for add_vertex.
st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(0, 0))
# Call last for each vertex, adds the above attributes.
st.add_vertex(Vector3(-1, -1, 0))
st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(0, 1))
st.add_vertex(Vector3(-1, 1, 0))
st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(1, 1))
st.add_vertex(Vector3(1, 1, 0))
# Commit to a mesh.
var mesh = st.commit()
var st = new SurfaceTool();
st.Begin(Mesh.PrimitiveType.Triangles);
// Prepare attributes for AddVertex.
st.SetNormal(new Vector3(0, 0, 1));
st.SetUV(new Vector2(0, 0));
// Call last for each vertex, adds the above attributes.
st.AddVertex(new Vector3(-1, -1, 0));
st.SetNormal(new Vector3(0, 0, 1));
st.SetUV(new Vector2(0, 1));
st.AddVertex(new Vector3(-1, 1, 0));
st.SetNormal(new Vector3(0, 0, 1));
st.SetUV(new Vector2(1, 1));
st.AddVertex(new Vector3(1, 1, 0));
// Commit to a mesh.
var mesh = st.Commit();
You can optionally add an index array, either by calling add_index()
and adding
vertices to the index array or by calling index()
which shrinks the vertex array
to remove duplicate vertices.
# Creates a quad from four corner vertices.
# add_index does not need to be called before add_vertex.
st.add_index(0)
st.add_index(1)
st.add_index(2)
st.add_index(1)
st.add_index(3)
st.add_index(2)
# Alternatively:
st.index()
// Creates a quad from four corner vertices.
// AddIndex does not need to be called before AddVertex.
st.AddIndex(0);
st.AddIndex(1);
st.AddIndex(2);
st.AddIndex(1);
st.AddIndex(3);
st.AddIndex(2);
// Alternatively:
st.Index();
Similarly, if you have an index array, but you want each vertex to be unique (e.g. because
you want to use unique normals or colors per face instead of per-vertex), you can call deindex()
.
st.deindex()
st.Deindex();
If you don't add custom normals yourself, you can add them using generate_normals()
, which should
be called after generating geometry and before committing the mesh using commit()
or
commit_to_arrays()
. Calling generate_normals(true)
will flip the resulting normals. As a side
note, generate_normals()
only works if the primitive type is set to Mesh.PRIMITIVE_TRIANGLES
.
You may notice that normal mapping or other material properties look broken on
the generated mesh. This is because normal mapping requires the mesh to
feature tangents, which are separate from normals. You can either add custom
tangents manually, or generate them automatically with
generate_tangents()
. This method requires that each vertex have UVs and
normals set already.
st.generate_normals()
st.generate_tangents()
st.GenerateNormals();
st.GenerateTangents();
By default, when generating normals, they will be calculated on a per-face basis. If you want
smooth vertex normals, when adding vertices, call add_smooth_group()
. add_smooth_group()
needs to be called while building the geometry, e.g. before the call to add_vertex()
(if non-indexed) or add_index()
(if indexed).