I thought this was kind of an interesting question because it makes me think a bit. So, I looked at my code. Turns out, I declare it backwards from what you said and it works fine. I declare and bind vbo, vao, and ibo in that order.
I think you generally see it that way because it’s kind of logical. Define what a vertex is. Then declare a buffer full of vertices. Then declare a buffer of indices to reference it. But it looks like the order you do that in is actually irrelevant as long as it’s all done before the draw call.
The main OGL books are probably the most likely books to give you really in depth answers, but I find them to be difficult reading much like reading a dictionary or encyclopedia. I’m not sure of a book that has the exact answers you’re looking for. Those books as reference books may be the best choice to answer a specific question. I just started reading red book cover to cover and it’s, again, like reading an encyclopedia cover to cover.
Check out LearnOpenGL.com if you have not already. I’m always kind of on the lookout for new OGL learning material. That’s one that’s really impressed me.
Here’s my code:
bool HandCodedObjectClass::DefineMesh(int NumberOfVertices, GLfloat* VertexList, int NumberOfIndices, GLuint* IndexList, Texture2DClass* ColorMap)
{
Texture = ColorMap;
VerticesInMesh = NumberOfVertices;
IndicesInMesh = NumberOfIndices;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, NumberOfVertices * sizeof(GLfloat) * 12, VertexList, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, nullptr); //Vertex Position.
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (GLvoid*)(sizeof(GLfloat) * 3)); //Vertex UV.
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (GLvoid*)(sizeof(GLfloat) * 5)); //Vertex Normal.
glEnableVertexAttribArray(2);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 12, (GLvoid*)(sizeof(GLfloat) * 8)); //Vertex RGBA color.
glEnableVertexAttribArray(3);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*NumberOfIndices, IndexList, GL_STATIC_DRAW);
return true;
}