API Reference · Geometry

Batching

Namespace: Ava3D

public static class Batching

Folding a group's static surfaces into as few draws as they can be drawn in.

Why this is the control's job and not a caller's. It was written twice before it was written here — once in full by a consumer whose wreck compartment was submitting 455 draw calls to carry 7,200 triangles, sixteen apiece, and once ad hoc in four places in this repository's own demo. Two independent implementations of one idea, with different rules about what may be merged, is the signal effects-and-shaders.md §2 names for a missing feature.

What it is for. A GPU finishes twelve triangles in no time at all and then waits for the CPU to hand it the next twelve, so a room built from four hundred small pieces is expensive to submit and free to draw — which is exactly the wrong way round, and leaves no budget for the geometry that would make it look like anything. Merging by material turns those four hundred submissions into a handful.

What it is not. Instancing. The two are complementary and the difference is worth stating because reaching for the wrong one is easy: MeshNode.Instances is for many copies of one mesh, and costs one draw and one upload however many copies there are. This is for many different meshes that happen to share a material, and costs one draw and one upload of all their vertices together. A room wants both — instancing for its four hundred identical bolts, folding for its fifty-five differently-shaped walls — and a node that already carries instances is left alone here, because it is already one draw.

What is deliberately left alone. Anything named, anything with children, anything hidden, anything carrying instances, anything skinned or morphed, anything that swaps its mesh or stops drawing at a distance, anything with a map that reads the second UV set or a texture transform of its own, and anything the caller says it is still holding. A merged surface has no transform of its own any more and cannot be moved, hidden or looked up — so the rule is that only the anonymous, static, leaf geometry of a group is eligible, and everything a caller can open, light or walk through stays exactly as it was.

Fields

MemberDescription
static int MostTriangles

The triangle half of the same ceiling.

static int MostVertices

The most vertices one merged mesh may carry.

A merge with no ceiling is a way of losing a whole room at once and being told nothing. An index buffer of sixteen-bit words holds 65,536 vertices, and this library's own offline renderer drops any mesh past its triangle budget silently and from the end of the draw order. Folding turns four hundred draws into a handful, and once a group's tiling is baked out every wall in a room can share one material — so what goes over a line is not a few surfaces, it is all the walls together.

Well under both limits, because a fold that has to be reasoned about at the boundary is a fold nobody trusts.

Methods

MemberDescription
static int Fold(Node parent, IReadOnlyCollection<MeshNode> pinned = null)

Merges what can be merged among a node's children, in place.

parent

The group to fold. Only its own children, and the leaves of plain groups among them.

pinned

Meshes the caller still needs as separate objects — anything it animates, lights, hides or holds a reference to. Passed rather than inferred, because a node cannot be asked whether somebody is holding it, and a fold that guessed would take away the door somebody was about to open.

returns

How many draws the fold removed, for a caller that wants to say so.

See also