I'm finally learning OpenGL above 2.1, which would require some extra driver knowledge in Linux, and a Hail Mary from Apple in regards to OpenGL 4.0 and above. What I'm wondering is: what are the important features differences between OpenGL 3.x and OpenGL 4.x? My guess is that OpenGL 4.2 (I think) provides geometry shaders which allows for hardware batching. In other words, if I had a model of a character, I could render dozens of instances of that character in 1 draw call per mesh in that model. Another are compute shaders in OpenGL 4.3 which is a nice replacement for OpenCL, more of an equivalent to DirectX 11, and possibly VERY useful for processing audio samples for interesting DSP effects that'd typically be handled by the motherboard's audio hardware. There are also 3D textures, and better techniques for rendering volumetric clouds, from what I've heard. Are there any other interesting features to look out for while I learn about OpenGL?
Now, how do vertex array objects (VAOs) work, exactly? From what I've read so far, they preserve vertex state, and by vertex state, I think it means the state of which vertex arrays are enabled. For example, if I have a model that is composed of 5 meshes, and the vertex format for all meshes are the same: position, texture coordinate and normal. So, when setting up my vertex array, I'd generate a VAO, bind to it, enable the first 3 vertex attribute arrays, then unbind. Now, when I wanted to draw the model, I'd just bind to that VAO again, bind my VBOs containing references to the vertex data, and call glDrawElements(). I no longer need to call glEnableVertexAttribArray() or glDisableVertexAttribArray() whenever I draw something because the VAO I've just bound preserves which vertex arrays to enable/disable --effectively batching, or rather, caching those calls into a single gl* call.
Then, there are VBOs... VBOs are completely separate from VAOs. A VBO must be generated per vertex attribute, whether they're separate arrays, or interleaved via structures, blobs, etc. Then, I may have an IBO (index buffer array) if my vertices are indexed, but again, has nothing to do with VAOs. VAOs only cache which vertex attribute arrays are enabled. Is that correct?
NOTE: If this is correct, would it make sense to no store VAOs on a per-model basis, but at a graphics context basis instead. If I have 5 different models that all happen to have the same number of vertex attribute arrays enabled, then I'd create 1 VAO that'd enable the first 3 vertex attribute arrays, bound once, render all instances of all 5 models, then bind to another VAO that uses a different number of arrays.
EDIT: I think I just realized something. So, I'd generate a new VAO, then bind it to configure it. At this point, I'd enable all the attribute arrays needed, and then generate, bind and fill my VBOs/IBOs. Then, I'd also setup glVertexAttribPointer() per attribute to specify the starting address for each attribute in the VBO, or VBOs if I'm going the array-per-attribute route. Finally, I'd unbind for safety. Then, when I want to draw something, it's a matter of setting the correct shader, setting the uniforms (probably with UBOs, but I haven't read that far yet), binding the VAO, and then drawing with glDrawArrays() or glDrawElements(). So, VAOs would greatly reduce the amount of gl* calls by caching these commands in a VAO, which serves similarly to a mini-command buffer that could be modified or calls on-the-fly. Which, if this is correct, then do binding VAOs introduce any type of scope for binding VBOs? For example, if I bound a VBO while a VAO is bound, once I bound the current VAO to zero, would it revert the currently-bound VBO to whatever VBO I was bound to when I wasn't in VAO scope? Does all of this sound about right?