Skip to content

Mesh

High-level geometry container. A Mesh owns a list of vertices and optional instances. Internally it deduplicates vertices and always draws indexed and instanced (instance_count defaults to 1 when none are provided).

Vertex layouts are managed by the Shader. At render time, inputs declared in your shader’s vertex function (annotated with @location(N)) are derived from the source and matched by name and type to Mesh properties across both streams (instance first, then vertex).

Mapping is driven by shader reflection; there are no special-case names or reserved locations. The renderer matches attributes by explicit location if provided (instance first, then vertex), and otherwise by name.

If a required input cannot be found or its type does not match, rendering returns an error indicating the missing attribute or mismatch.

use fragmentcolor::mesh::{Mesh, Vertex, VertexValue};
let mut mesh = Mesh::new();
mesh.add_vertex([0.0, 0.5, 0.0]);
mesh.add_vertex([-0.5, -0.5, 0.0]);
mesh.add_vertex([0.5, -0.5, 0.0]);

Create an empty mesh. Add vertices with add_vertex (or add_vertices) and instances with add_instance, then attach the mesh to a shader to draw it.

use fragmentcolor::mesh::Mesh;
let m = Mesh::new();
1 collapsed line
_ = m;

Create a mesh from an iterator of Vertex values.

use fragmentcolor::Mesh;
let mesh = Mesh::from_vertices([
[0.0, 0.0],
[1.0, 0.0],
[0.0, 1.0],
]);

Append a single vertex to the mesh. Pass an array literal for the position ([x, y] or [x, y, z]); for vertices that carry uv, color, or other per-vertex attributes, build a Vertex first and pass it in.

use fragmentcolor::mesh::{Mesh};
let mut m = Mesh::new();
m.add_vertex([0.0, 0.0]);

Add many vertices to the mesh.

use fragmentcolor::mesh::Mesh;
let mut m = Mesh::new();
m.add_vertices([
[0.0, 0.0],
[1.0, 0.0],
]);

Add a single per-instance attribute set to the mesh.

An Instance is a bag of named attributes (transform, color, id, …) sent to the shader’s per-instance inputs. It carries no position; the mesh’s vertices are reused for every instance.

Adding an instance also clears any previously set instance count override (see Mesh::set_instance_count).

use fragmentcolor::mesh::{Mesh, Instance};
let m = Mesh::new();
let offset: [f32; 2] = [0.25, 0.10];
let tint: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
m.add_instance(Instance::new().set("offset", offset).set("tint", tint));

Add many per-instance attribute sets to the mesh in one call.

Each Instance is a bag of named attributes (transform, color, id, …) sent to the shader’s per-instance inputs. Instances carry no position; the mesh’s vertices are reused for every instance.

Adding instances also clears any previously set instance count override (see Mesh::set_instance_count).

use fragmentcolor::mesh::{Mesh, Instance};
let m = Mesh::new();
let red: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
let green: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
let blue: [f32; 4] = [0.0, 0.0, 1.0, 1.0];
m.add_instances([
Instance::new().set("tint", red),
Instance::new().set("tint", green),
Instance::new().set("tint", blue),
]);

Reset the mesh’s instance state to the default (1 draw, no per-instance data).

Specifically, this:

  • Drops any per-instance attributes added via add_instance / add_instances.
  • Clears any count override previously set with set_instance_count.

After calling, the mesh renders as a single instance unless you populate it again or call set_instance_count.

use fragmentcolor::mesh::{Mesh, Instance};
let m = Mesh::new();
let red: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
m.add_instance(Instance::new().set("tint", red));
m.clear_instances(); // back to a single uninstanced draw

Override how many instances to draw without providing per-instance attributes.

Use this when driving instance data from a storage buffer and indexing via @builtin(instance_index) in the vertex shader. Common for compute-driven simulations and large particle systems.

The override is automatically cleared if you later call add_instance / add_instances (those carry their own count) or clear_instances.

use fragmentcolor::mesh::Mesh;
let mut m = Mesh::new();
m.add_vertices([
[-0.01, -0.01],
[ 0.01, -0.01],
[ 0.00, 0.01],
]);
// Draw one million instances, fetching per-particle data from a storage buffer.
m.set_instance_count(1_000_000);

Provide the index buffer directly, bypassing the mesh’s automatic vertex dedup pass. Use this when an asset already carries its own indexing: glTF loaders, OBJ importers, or hand-authored meshes whose corners share positions but need to keep distinct UVs, normals, or tangents (the typical case for sharp creases and texture seams).

By default the mesh dedupes vertices by full attribute equality before producing an index array. That’s fine for hand-built meshes, wrong for assets where two corners with identical positions must stay separate because their other attributes differ. After set_indices, every vertex you added with add_vertex is packed in insertion order and the indices you supply are used verbatim. Call clear_indices to return to the auto-derived path.

use fragmentcolor::{Mesh, Vertex};
// A quad split into two triangles via explicit indexing. The four corners
// happen to carry distinct UVs (only positions repeat), so we keep them
// all and reference each by index.
let mesh = Mesh::new();
let uv00: [f32; 2] = [0.0, 0.0];
let uv10: [f32; 2] = [1.0, 0.0];
let uv11: [f32; 2] = [1.0, 1.0];
let uv01: [f32; 2] = [0.0, 1.0];
mesh.add_vertices([
Vertex::new([-0.5, -0.5]).set("uv", uv00),
Vertex::new([ 0.5, -0.5]).set("uv", uv10),
Vertex::new([ 0.5, 0.5]).set("uv", uv11),
Vertex::new([-0.5, 0.5]).set("uv", uv01),
]);
mesh.set_indices([0, 1, 2, 0, 2, 3]);

Drop the user-supplied index buffer and return to auto-derived indexing.

After set_indices the mesh draws vertices in insertion order using the indices you provided. clear_indices reverses that: the next render re-runs the vertex dedup pass and rebuilds the index buffer from the deduplicated unique set, the same way a freshly built mesh behaves.

use fragmentcolor::{Mesh, Vertex};
let mesh = Mesh::new();
mesh.add_vertices([
Vertex::new([-0.5, -0.5]),
Vertex::new([ 0.5, -0.5]),
Vertex::new([ 0.0, 0.5]),
]);
mesh.set_indices([0, 1, 2]);
mesh.clear_indices(); // back to auto-derived dedup