Your main question seems to be:
What would be the best way to draw frequently (really frequently, basically every frame) changing geometry with modern OpenGL?
In most ways, there's no big difference between 2d and 3d OpenGL. The graphics pipeline has that one extra coordinate, Z, which won't be used as much in 2d, but that's about it.
There's a few ways to change the geometry on each draw.
You can push new CPU-provided vertexes every frame. (See http://stackoverflow.com/questions/14155615/opengl-updating-vertex-buffer-with-glbufferdatahttps://stackoverflow.com/questions/14155615/opengl-updating-vertex-buffer-with-glbufferdata for some notes on reusing buffers.)
You can draw different portions of an existing buffer, with
glDrawArrays(mode, first, count)
. If the animation loops, maybe you can put the precomputed frames with the different vertex lists in one big buffer, and draw the appropriate portion of the buffer each frame.You can influence the vertex list with some other data, like a uniform array, or a texture. In your vertex shader, read this data and apply it appropriately. These are just other idioms for presenting data to the GPU, and probably won't have much difference in performance.
If you have many instances of the same geometry (possibly influenced by attributes), then
glDrawElementsInstanced()
may be usefulYou can influence the vertex list algorithmically in the vertex, geometry, or tessellation shaders. If the animation can be described mathematically, you might be able to keep the same vertex list, and change just a few shader uniforms each frame.
And perhaps your animation might be expressed as pure textures, with all animation done pixel by pixel by the cpu, or pre rendered from disk.
On the whole, I'd say, "Computers are fast, make it work the easiest way you can, which is probably by setting fresh CPU-made vertexes every frame. Then, see if that's good enough. Profile the battery/CPU usage first, memory footprint second."
Your other question, paraphrased, "What's a good way to draw circles and rectangles?"
Circles.
With tessellation shaders (or geometry shaders) you could make your geometry dynamic.
You could draw squares, and in your fragment shader only opaque (alpha = 1.0) within a radius, and transparent (alpha = 0.0) outside the radius. Then it's pixel perfect every time. (Make your square vertexes -1 to +1, and in fragment shader something like,
outColor.a = dot(coord.xy, coord.xy) < 1.0 ? 1.0 : 0.0;
. Could also smooth the edge a little, would look nice there...)You could just always use, say, a 120-triangle fan. Probably good enough.
Rectangles.
- I think you answered your own question, on that one. What you suggest will work fine!