Primitive Assembly
Primitive assembly is a crucial stage in the DirectX rendering pipeline. It takes the processed vertices from the vertex shader and organizes them into primitives (points, lines, or triangles) that can then be rasterized.
The Role of Primitive Assembly
After vertices have been transformed and lit by the vertex shader, they exist as individual data points in clip space. Primitive assembly's primary responsibility is to group these vertices into geometric primitives. The type of primitive is determined by the graphics hardware and the application's settings.
Primitive Types
- Points: Each vertex is rendered as a single point.
- Lines: Vertices are grouped into pairs to form line segments. Options include independent lines or connected strips.
- Triangles: Vertices are grouped into triplets to form triangles. This is the most common primitive type for 3D graphics due to its simplicity and ability to tessellate complex surfaces. Similar to lines, triangles can be rendered independently or as a strip.
Topology
The way vertices are connected to form primitives is defined by the primitive topology. Common topologies include:
D3D_PRIMITIVE_TOPOLOGY_POINTLISTD3D_PRIMITIVE_TOPOLOGY_LINELISTD3D_PRIMITIVE_TOPOLOGY_LINESTRIPD3D_PRIMITIVE_TOPOLOGY_TRIANGLELISTD3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
Input Assembler
The Input Assembler (IA) stage is responsible for fetching vertex data from memory (typically vertex buffers) and assembling it into the primitives specified by the primitive topology. This stage reads vertex data, applies any necessary indexing if an index buffer is used, and outputs a stream of geometric primitives to the next stage of the pipeline.
Vertex Buffers and Index Buffers
- Vertex Buffers: Store the attributes of each vertex, such as position, color, texture coordinates, and normals.
- Index Buffers: An optional buffer that contains indices referencing vertices in the vertex buffer. Using index buffers can significantly reduce memory usage and improve performance by allowing multiple primitives to share vertices.
The Input Assembler uses the primitive topology setting to know how to interpret the incoming vertex stream. For example, if D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST is set, the IA will read vertices three at a time to form triangles.
Example Pseudocode
This pseudocode illustrates how the Input Assembler might conceptually process vertices for a TRIANGLELIST:
// Assuming vertices are in a contiguous array and topology is TRIANGLELIST
function AssembleTriangles(vertex_data) {
primitives = [];
for (i = 0; i < vertex_data.length; i += 3) {
// Fetch three vertices
v0 = vertex_data[i];
v1 = vertex_data[i+1];
v2 = vertex_data[i+2];
// Form a triangle primitive
triangle = { v0, v1, v2 };
primitives.push(triangle);
}
return primitives;
}
When using an index buffer, the process involves reading indices and using them to fetch vertices from the vertex buffer, allowing for significant reuse of vertex data.
Next Steps
Once primitives are assembled, they are passed to the next stage, which is typically the Rasterizer. The rasterizer determines which pixels on the screen are covered by the primitives.