The Vertex Array Object stores how opengl should interpret a set of VBOs.
In essence it will let you avoid calling glVertexAttribPointer every time you want to render a new mesh.
If you don't want to deal with VAOs you can simply create one and bind it during program initialization and pretend they don't exist.
void glEnableVertexAttribArray(GLuint attribIndex);
void glDisableVertexAttribArray(GLuint attribIndex);
void glVertexAttribPointer(GLuint attribIndex, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer);
void glVertexAttribFormat(GLuint attribIndex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
void glVertexAttribBinding(GLuint attribIndex, GLuint bindingIndex);
void glBindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, GLintptr stride);
|the location for the vertex attribute to which the vertex array will feed data
|the number of components to be pulled from the attribute
|The C++ type of the attribute data in the buffer
|whether to map integer types to the floating-point range [0, 1] (for unsigned) or [-1, 1] (for signed)
|the byte offset into the buffer to the first byte of the attribute's data (cast to
void* for legacy reasons)
|the base byte offset from the beginning of the buffer to where the array data starts
|the offset to a particular attribute, relative to the base offset for the buffer
|the number of bytes from one vertex's data to the next
|the buffer object where the vertex arrays are stored
|the index to which the source buffer object will be bound
The separate attribute format VAO setup can interoperate with
glVertexAttribPointer (the latter is defined in terms of the former). But you must be careful when doing so.
The separate attribute format version have direct state access (DSA) equivalents in 4.5. These will have the same parameters but instead of using the bound VAO, the VAO being modified is passed explicitly. When using DSA de index buffer for
glDrawElements can be set with