glVertexAttribPointer
Describes how one vertex attribute is laid out inside the currently bound GL_ARRAY_BUFFER.
Signature
void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
How it works
Your vertex buffer is just bytes; the GPU does not know that the first 12 bytes are a position and the next 8 are a UV. This function tells it, one attribute at a time.
For attribute index, it says: read size components of type type, skip stride bytes to get from one vertex to the next, and start pointer bytes into the buffer. It also captures WHICH buffer is bound to GL_ARRAY_BUFFER right now and stores it in the VAO.
The index matches layout(location = N) in the vertex shader.
Parameters
Attribute location, same as layout(location = N) in GLSL.
Components per vertex: 1, 2, 3 or 4 (e.g. 3 for a vec3 position).
Data type of each component in the buffer.
Common values
- GL_FLOAT
- 32-bit float — the most common.
- GL_UNSIGNED_BYTE
- 0–255, typically colors (use normalized = GL_TRUE).
- GL_INT / GL_SHORT / GL_HALF_FLOAT
- Other compact formats.
For integer types: GL_TRUE maps them to 0–1 (or -1–1). Ignored for floats — pass GL_FALSE.
Bytes from the start of one vertex to the start of the next. 0 means "tightly packed".
Byte offset of this attribute inside a vertex, cast to void*. Not a real pointer!
Tips & pitfalls
The attribute stays disabled until you call
glEnableVertexAttribArray(index).For integer attributes used as int/ivec in GLSL use
glVertexAttribIPointer, otherwise they are converted to float.Use offsetof(Vertex, member) to compute pointer safely when vertices are a struct.
Errors
When the call is invalid it does nothing and sets an error, which glGetError returns:
- GL_INVALID_VALUE
- index ≥ GL_MAX_VERTEX_ATTRIBS, size not in 1–4, or stride negative.
- GL_INVALID_OPERATION
- No VAO bound, or no GL_ARRAY_BUFFER bound while pointer is non-zero.
Example
1struct Vertex { glm::vec3 pos; glm::vec2 uv; };
2
3glBindVertexArray(vao);
4glBindBuffer(GL_ARRAY_BUFFER, vbo);
5
6// location 0: vec3 position
7glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, pos));
8glEnableVertexAttribArray(0);
9
10// location 1: vec2 uv
11glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, uv));
12glEnableVertexAttribArray(1);