1. The VAO is used to remember states that VBOs use. You can have a VAO with multiple VBOs bound to it, where each VBO contains vertex positons, normals etc.
glEnableVertexAttribArray(0) // enables slot 0
glVertexAttribPointer(0, ..., offsetof(vertex_t, x))
glEnableVertexAttribArray(1) // enables slot 1
glVertexAttribPointer(1, ..., offsetof(normals_t, nx))
A VAO can also hold just a single VBO, and also remember all the indexes at the same time. Just bind a single VBO when the VAO is bound, then enable all the indexes and inform the drivers of the offsets to each variable in your vertex structure.
VAOs are relatively simple. You create, bind, enable & set attribs, done. After that you can bind and render with them.
2. Yes, global state. Unfortunately. It's simple enough, which is what people generally like about it. It does make room for ALOT of bugs if you don't use something that hides all the interaction, like a GL wrapper that already has all of this implemented properly and is well tested. The drawback is overhead in function calls, solved by bindless future outworld technology available 2020. We generally use opengl 3.x now, as that is the most common and not as horribad as 2.1.
3. Because just like ANSI-C, OpenGL has so much baggage, that it's not fun to think about it. Just try to ignore it. Of course, I think most people are unlike me and don't care about how bad an API is. BindFramebuffer isn't THAT bad. The function name makes alot of sense, and so does everything else in the APIs if you already know the usage and reasons behind them.
4. There is no relation between glEnable* and the others.
You need to have a VAO bound, and a vertex attrib array index enabled for openGL to care about it. In no particular order.
Example with 3 floats (which we will call x, y, z in our vertex structure named vertex_t):
glVertexAttribPointer(index, 3, GL_FLOAT, GL_FALSE, sizeof(vertex_t), offsetof(vertex_t, x))
Edited by Kaptein, 03 May 2014 - 05:55 PM.