Upload bytes, then describe them
A buffer stores bytes. A vertex attribute declaration explains how a draw interprets some of those bytes: component count, scalar type, normalization, stride, and offset. A VAO retains the vertex-input configuration used for later draws. It does not replace the buffer owner or magically infer the C++ struct layout.
The starter interleaves position and color in a standard-layout Vertex and uses sizeof(Vertex) for stride and offsetof for field offsets. The pointer-looking argument is a byte-offset token into the bound buffer for this API call, not a host pointer that OpenGL should dereference. Keep that API-specific convention localized.
In this baseline, glVertexAttribPointer captures the currently bound array buffer into the VAO’s attribute association. Simply rebinding GL_ARRAY_BUFFER later does not redirect that stored attribute. Enable the intended locations explicitly and keep the GLSL input locations aligned with the C++ description.
Trace one vertex’s position and color bytes through their stride and offsets. Change only a color first, then deliberately diagnose one wrong offset.
