As you have hopefully noticed, you have to enable attribute arrays with glEnableVertexAttribArray
when dealing with vertex array objects. Even though you can bind different buffers per attribute, you can't bind different attributes 'per draw call' or similar. This means that everything pointed to by a VAO must have the same attributes stored. You could, of course, ignore some attributes given by the VAO, but this may lead to inefficiency and it probably wouldn't be a good practice.
This again means that, every draw call with the same VAO bound, uses the same attributes. I think this is the best way to determine whether you need a new VAO or not, first determine if you need a different set of attributes. You can then easily determine what piece of the object to draw by pointing to a set of indices at some other location within your index buffer.
In a more object orientated scene (like a game, in which you have distinct meshes) the most practical way is to simply create one or more VAOs per mesh. This allows you to have different types of buffers per mesh (static, dynamic or stream). You could even have a couple of large buffers (1 to 8 MB per buffer or similar) and have multiple VAOs which use the same buffer. I often do this to avoid frequent memory allocation.
I just gave you two options:
- A new VAO for each new set of attributes
- A new VAO for each distinct object in the scene
It depends on the type of scene you have which is the most convenient, but in most cases you probably won't find that big of a difference in performance. There are of course cases in which one has slightly better performance, but you should figure that out yourself.
Considering your problem, I can see two options. You didn't say whether you are going to update the vertices often or not. If you are constantly altering your graph and updating your vertices, I would give the axes their own VAO, as they will never change, ergo they can use a static buffer while the graph itself can use a dynamic or stream buffer. But if the axes are part of the entire graph, thus meaning the graph itself won't be updated often, you can just throw them all in a single VAO for convenience.
Remember these are just suggestions, you should choose what fits best in your framework and/or has the best performance or simply which is the most convenient.
Hope this helped a bit.