Vertex Array Object (VAO)

Some OpenGL users think that a Vertex Array Object (VAO)) in OpenGL is optional but it is not. If you use OpenGL 3.3+ you have to use a VAO not to cause an undefined behaviour, for example a crash. Before OpenGL draws anything it will use the current bound VAO to get the information about the data it will use to setup the shader channels and use the correct BO for the correct purpose.

You can imagine the meaning of the VAO as an object that holds references to one or multiple BO, a description how the VBO is structured, connection to the shaders attributes. In short, we can assign one/multiple VBO and one Index Buffer Object (IBO) to be precise and the good thing is, we just do all this (in the best case) only once and use the VAO multiple times. For example if we would have a 3D model for a car, a plane and a spaceship, we could setup 3 VAO for each of them once and then just bind the one we like to draw. We don't have to set anything else anymore.

Let's create an empty name for our VAO. We do that with glCreateVertexArrays:

GLuint vao {};
glCreateVertexArrays(1, &vao);

The next thing we need to do is to tell OpenGL where to find the vertex data which means which VBO we want to use and how the shader can use it later. We do that with the following line using our VBO and vertex structure from above. We do that with glVertexArrayVertexBuffer:

glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(vertex));

Parameter

Type

Description

1

GLuint vaobj

The VAO name.

2

GLuint bindingindex

The binding point for the VBO. This is not the attribute index for the shader. We just tell OpenGL that we like to reference the VBO we will specify that it will be identified with this index.

3

GLuint buffer

The VBO name we like to bind.

4

GLintptr offset

An offset within the VBO if we want to.

5

GLsizei stride

The distance between elements within the VBO.

Next is, we tell OpenGL how the shader will access those buffers. We do that with glVertexArrayAttribBinding:

glVertexArrayAttribBinding(vao, 0, 0);

glVertexArrayAttribBinding

Parameter

Type

Description

1

GLuint vaobj

The VAO name.

2

GLuint attribindex

The shader attribute index.

3

GLuint bindingindex

The binding point.

In the first parameter we pass our VAO we want to set the attribute bindings which is vao. The second is the index used inside the shader. The third parameter is the binding index we used in glVertexArrayVertexBuffer.

Now we have to tell OpenGL how our VBO is structured. We do that with glVertexArrayAttribFormat:

glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, offsetof(vertex, x));

glVertexArrayAttribFormat

Parameter

Type

Description

1

GLuint vaobj

The VAO name.

2

GLuint attribindex

The shader attribute index.

3

GLint size

The number of components

4

GLenum type

The type of the component.

5

GLboolean normalized

GL_TRUE integer values normalized to [-1, 1].GL_FALSE integer values converted directly to float values.

6

GLuint relativeoffset

The distance between elements within the buffer.

Again, the 1. parameter is the VAOs name we like to modify. The 2. parameter is how the shader can access this element. This is done in the shader with the (layout = 0) directive. The 3. parameter tells how many components this type will have. For example the position values we are using in the VBO has x, y z components. So we use 3 here. The 4. parameter is information about the type. We are using float values. The 5. parameter can be use to say it the values should be normalized or not. The 6. parameter gives information about the distance between elements within the buffer. For x,y,z as floats we would have a relative offset of sizeof(float) * 3.

Next we have to set is the divisor with glVertexArrayBindingDivisor:

glVertexArrayBindingDivisor(vao, 0, 0);

glVertexArrayBindingDivisor

Parameter

Type

Description

1

GLuint vaobj

The VAO name.

2

GLuint bindingindex

The binding point.

3

GLuint divisor

The divisor value.

Finally we need to enable the attribute with glEnableVertexArrayAttrib:

glEnableVertexArrayAttrib(vao, 0);

glEnableVertexArrayAttrib

Parameter

Type

Description

1

GLuint vaobj

The VAO name.

2

GLuint index

The shader attribute to enable.

Last updated