glDrawElements
Draws primitives using an index buffer to choose which vertices to use.
Signature
void glDrawElements(GLenum mode, GLsizei count, GLenum type, const void *indices);
How it works
Instead of reading vertices in order, the GPU reads count indices from the element buffer stored in the bound VAO, and fetches the vertex each index points to. A cube needs only 8 unique vertices plus 36 small indices, instead of 36 full vertices.
The GPU also caches recently transformed vertices, so reused indices are nearly free.
Parameters
Primitive type.
Common values
- GL_TRIANGLES
- Every 3 vertices form one triangle. The default choice.
- GL_TRIANGLE_STRIP
- Each new vertex forms a triangle with the previous two.
- GL_TRIANGLE_FAN
- All triangles share the first vertex.
- GL_LINES / GL_LINE_STRIP / GL_LINE_LOOP
- Line segments.
- GL_POINTS
- One point per vertex.
Number of INDICES to read.
Type of each index in the element buffer.
Common values
- GL_UNSIGNED_INT
- 32-bit — safe default.
- GL_UNSIGNED_SHORT
- 16-bit — up to 65 535 vertices, half the memory.
- GL_UNSIGNED_BYTE
- 8-bit — up to 255 vertices.
Byte offset into the element buffer, cast to void*. Usually 0.
Tips & pitfalls
type must match the actual C++ type of your index array: unsigned int ↔ GL_UNSIGNED_INT.
If nothing is drawn, check that the EBO was bound while the VAO was bound.
Errors
When the call is invalid it does nothing and sets an error, which glGetError returns:
- GL_INVALID_ENUM
- type is not one of the three unsigned types.
- GL_INVALID_OPERATION
- No VAO bound, or no program in use.
Example
1unsigned int indices[] = { 0, 1, 3, 1, 2, 3 }; // quad = 2 triangles
2glBindVertexArray(vao);
3glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
4glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
5
6glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);