In which you learn how all of computer graphics pivots around the triangle and extend your tools for rendering points to this new geometric primitive.
In the hello-triangles
application, the scheme used to group vertices into triangles is implicit. The GPU connects vertices together based only their sequence in the VBOs. Sometimes you want more explicit control over how vertices connect together.
Consider this square:
function initialize() {
const positions = [
// Triangle 0
0, 0, 0,
1, 0, 0,
1, 1, 0,
// Triangle 1
0, 0, 0,
1, 1, 0,
0, 1, 0,
];
attributes = new VertexAttributes();
attributes.addAttribute('position', 6, 3, positions);
// ...
}
function render() {
// ...
vao.drawSequence(gl.TRIANGLES);
// ...
}
Draw it on paper so you understand its structure before reading on.
Because the rectangle is being drawn with gl.TRIANGLES
, both triangles must include the shared vertices \(\begin{bmatrix}0&0&0\end{bmatrix}\) and \(\begin{bmatrix}1&1&0\end{bmatrix}\). This redundancy could be fixed by switching to a triangle fan. However, triangle fans support only a very particular form of connectivity in which the triangles radiate out from the central vertex.
A more general solution is to use indexed geometry. With indexed geometry, each vertex appears exactly once in the VBO. But you must explicitly list how these triangles connect together with an array of indices. Consider how the square changes when using indexed geometry:
function initialize() {
const positions = [
0, 0, 0, // Vertex 0
1, 0, 0, // Vertex 1
0, 1, 0, // Vertex 2
1, 1, 0, // Vertex 3
];
const indices = [
0, 1, 3, // Triangle 0
0, 3, 2, // Triangle 1
];
attributes = new VertexAttributes();
attributes.addAttribute('position', 4, 3, positions);
attributes.addIndices(indices);
// ...
}
Draw this square on paper again. Label each vertex with both its Cartesian coordinates and its index. Then observe how the indices of these vertices are listed in indices
to form triangles.
To draw a shape whose triangles are specified by indices, you replace the drawSequence
call with drawIndexed
:
function render() {
// ...
vao.drawIndexed(gl.TRIANGLES);
// ...
}
The addIndices
and drawIndexed
calls do no error checking. You are responsible for making sure your indices are valid.
hello-triangles
application to render your blocky T-shape using indexed geometry.