I’m assuming you’re not using GL4.3. In GL4.2, a VAO mainly stores properties of multiple vertex arrays, i.e. memory layout definitions of data stored in an ARRAY_BUFFER object. It also stores a debug label and and any ELEMENT_ARRAY_BUFFER_BINDING done after binding the VAO. Initially the element array buffer binding is 0.
What I know about them is that VAO’s are there to allow you to use a single identifier to refer to multiple buffers that conceptually represent one “object.”
The VAO itself refers to no buffer object other than an element array buffer, if any. The VAO stores a list of vertex attribute indices and a corresponding ARRAY_BUFFER object name. If you call glVertexAttribPointer(index, …) and no ARRAY_BUFFER is bound at the time, this associtaion will be (index, 0) and thus drawing operations will be undefined. If an ARRAY_BUFFER is bound at the time, the association will be simply (index, GL_ARRAY_BUFFER_BINDING). Therefore, you can associate different vertex array with different ARRAY_BUFFER objects which will be sourced when you call a draw command like glDrawArrays.
GL4.3 relaxes this very static binding mechanism with a more flexible approach. Check out this extension for more info.
Note that no ARRAY_BUFFER needs to be bound when a VAO is bound for drawing (i.e. GL_ARRAY_BUFFER_BINDING will be 0) and a VAO will not change GL_ARRAY_BUFFER_BINDING - it will change, however, the value of GL_ELEMENT_ARRAY_BUFFER_BINDING.
Furthermore, you can delete associated buffer objects and look at the funny results when drawing (if the application does not crash). Unless you want to be welcomed to undefined-behavior-land, please don’t delete
When you create a VAO and bind it to make it active
True. Although “make it active” should probably be “make its state current” or something like that. 
any subsequent buffers you bind and load data into are automatically associated with the VAO that you just bound. Is this right? So if you bind another VAO identifier, then all subsequent buffer generations and binds are associated with this new VAO identifier.
Nope. Especially buffer object name generation (glGenBuffers) has nothing to do with binding and absolutely nothing to do with VAOs. “Generating” a buffer merely means returning a currently unused, non-zero name for a buffer object.
As I said before, a VAO does merely store the current GL_ELEMENT_ARRAY_BUFFER_BINDING. You can change whatever buffer binding other than that and it will not affect the VAO. Only when you call glVertexAttribPointer is the current state of GL_ARRAY_BUFFER_BINDING important. Any other buffer is simply bound to it’s respective target. Refer to Section 6.2 / Table 6.6 of the GL4.2 core spec for the VAO state table.
- generate 2 vao’s
- bind vao[0]
- gen buffer b1 and bind to a target and load data to it
- bind vao[1]
- gen buffer b2 and bind to a target and load data to it
- bind vao[0] and call a draw command -> if b1 contained vertex data it would be drawn
- bind vao[1] and call a draw command -> if b2 contained vertex data it would be drawn
You’re forgetting stuff: you need to setup actual buffer layouts with glVertexAttribPointer and enable vertex arrays before anything will be drawn. Also, it makes no sense to draw if you’re only using a VAO associating vertex attrib arrays with vertex colors. It could look like this, re-structured to emphasize the disconnect between ARRAY_BUFFER objects and VAOs:
- generate 2 VBOs // lets say buffer names 1 and 2
- generate 1 VAO
- bind VAO // only one VAO, multiple buffers, multiple vertex array with
- bind VBO[0] and upload data // positions
- specify vertex attrib arrays sourcing from VBO0 (index 0, buffer name 1)
- bind VBO[1] and upload data // colors
- specify vertex attrib array sourcing from VBO1 (index 1, buffer name 2)
- enable array 0 and 1
- unbind both VBOs
This is a corresponding implementation (don’t get confused by the use of the gl namespace. it’s still the same function only more scoped):
void setupBuffers()
{
GLfloat points[] = {-1.f, 0.f, -1.f, 1.f,
-1.f, 0.f, 1.f, 1.f,
1.f, 0.f, 1.f, 1.f,
1.f, 0.f, 1.f, 1.f,
1.f, 0.f, -1.f, 1.f,
-1.f, 0.f, -1.f, 1.f};
GLfloat colors[] = { 1.f, 0.f, 0.f, 1.f,
0.f, 1.f, 0.f, 1.f,
0.f, 0.f, 1.f, 1.f,
0.f, 1.f, 1.f, 1.f,
1.f, 0.f, 1.f, 1.f,
1.f, 1.f, 0.f, 1.f};
GLuint vbos[2];
GLuint vao;
gl::GenBuffers(2, vbos);
gl::GenVertexArrays(1, &vao);
gl::BindVertexArray(vao);
gl::BindBuffer(gl::ARRAY_BUFFER, vbos[0]);
gl::BufferData(gl::ARRAY_BUFFER, sizeof(points), points, gl::STATIC_DRAW);
gl::VertexAttribPointer(0, 4, gl::FLOAT, gl::FALSE_, 0, 0); // associate (index 0, buffer name vbos[0])
gl::EnableVertexAttribArray(0);
gl::BindBuffer(gl::ARRAY_BUFFER, vbos[1]);
gl::BufferData(gl::ARRAY_BUFFER, sizeof(colors), colors, gl::STATIC_DRAW);
gl::VertexAttribPointer(1, 4, gl::FLOAT, gl::FALSE_, 0, 0); // associate (index 1, buffer name vbos[1])
gl::EnableVertexAttribArray(1);
gl::BindBuffer(gl::ARRAY_BUFFER, 0); // no ARRAY_BUFFER_BINDING anymore ( == 0)
}
EDIT: Damn you carsten! 