Graphics Reference
In-Depth Information
This is how the same cube would be drawn using
glDrawElements
:
#define VERTEX_POS_INDX 0
GLfloat vertices[] = { … };// (x, y, z) per vertex
GLubyte indices[36] = {0, 1, 2, 0, 2, 3,
0, 3, 4, 0, 4, 5,
0, 5, 6, 0, 6, 1,
7, 1, 6, 7, 2, 1,
7, 5, 4, 7, 6, 5,
7, 3, 2, 7, 4, 3 };
glEnableVertexAttribArray ( VERTEX_POS_INDX );
glVertexAttribPointer ( VERTEX_POS_INDX, 3, GL_FLOAT,
GL_FALSE, 0, vertices );
glDrawElements ( GL_TRIANGLES,
sizeof(indices)/sizeof(GLubyte),
GL_UNSIGNED_BYTE, indices );
Even though we are drawing triangles with
glDrawElements
and a
triangle fan with
glDrawArrays
and
glDrawElements
, our application
will run faster than
glDrawArrays
on a GPU for many reasons.
For example, the size of vertex attribute data will be smaller with
glDrawElements
as vertices are reused (we will discuss the GPU post-
transform vertex cache in a later section). This also leads to a smaller
memory footprint and memory bandwidth requirement.
Using primitive restart, you can render multiple disconnected primitives
(such as triangle fans or strips) using a single draw call. This is beneficial
to reduce the overhead of the draw API calls. A less elegant alternative
to using primitive restart is generating degenerate triangles (with some
caveats), which we will discuss in a later section.
Using primitive restart, you can restart a primitive for indexed draw
calls (such as
glDrawElements
,
glDrawElementsInstanced
, or
glDrawRangeElements
) by inserting a special index into the indices list.
The special index is the largest possible index for the type of the indices
(such as 255 or 65535 when the index type is
GL_UNSIGNED_BYTE
or
GL_UNSIGNED_SHORT
, respectively).
For example, suppose two triangle strips have element indices of (0, 1,
2, 3) and (8, 9, 10, 11), respectively. The combined element index list
if we were to draw both strips using one call to
glDrawElements*
with
primitive restart would be (0, 1, 2, 3,
255
, 8, 9, 10, 11) if the index type is
GL_UNSIGNED_BYTE
.