Vertex arraysGL 2.0

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.

vertex 0vertex 1xyzuvxyzuv0481216202428323640stride = 20offset = 12offset = 0location 0: size 3, GL_FLOATlocation 1: size 2, GL_FLOAT
Two vertices of an interleaved buffer: position (3 floats) then texture coordinates (2 floats). Every attribute uses the same stride, 20 bytes from one vertex to the next; the offset says where inside a vertex the attribute starts.

Parameters

indexGLuint

Attribute location, same as layout(location = N) in GLSL.

sizeGLint

Components per vertex: 1, 2, 3 or 4 (e.g. 3 for a vec3 position).

typeGLenum

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.
normalizedGLboolean

For integer types: GL_TRUE maps them to 0–1 (or -1–1). Ignored for floats — pass GL_FALSE.

strideGLsizei

Bytes from the start of one vertex to the start of the next. 0 means "tightly packed".

pointerconst void *

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

example.cpp
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);
Official Khronos documentation