Your implementation suffers of over-engineering and is pretty rigid in terms of extensibility.
Legacy
- are there really that many platforms still under OGL < 1.5 ?
- if you have such case, does it even support C# ?
- IMO you should have a
LegacyRenderer(immediate) and aModernRenderer, don't mix them
Implementation
- your system only supports one type of vertex declaration : position, color, UV
- nowhere you are letting the user specify its custom declaration
- nowhere you are letting the user specify a shader
- the binding of vertex attributes have fixed positions
I would suggest to take a look at the following library I wrote a while ago, it does mimic what XNA does in the sense that you get VBOs, VAOs, Effects classes; and these are untied to any specific vertex declaration as you did.
Repository / usage example:
https://github.com/aybe/GLA https://github.com/aybe/GLA/blob/master/GLADemo/GameDemoGLA.cs#L125
(you will see 3 examples: lines, triangles, textures)
Dynamic assignment of vertex attributes according user declaration:
https://github.com/aybe/GLA/blob/master/GLA/VertexArray.cs https://github.com/aybe/GLA/blob/master/GLA/VertexDeclaration.cs https://github.com/aybe/GLA/blob/master/GLA/VertexElement.cs https://github.com/aybe/GLA/blob/master/GLA/VertexElementFormat.cs https://github.com/aybe/GLA/blob/master/GLA/VertexElementUsage.cs
I designed that library by reverse-engineering XNA using a decompiler such as DotPeek.
Also, another great source of inspiration to you could be the MonoGame project:
https://github.com/mono/MonoGame/tree/develop/MonoGame.Framework/Graphics/Vertices
Last thing, spending a few days in using XNA or MonoGame would certainly help you get a better picture of what's a good API and how you should design yours consequently :D
EDIT:
For your sprites at different positions, either render them by each time updating the transform matrix in your shader or use instanciation.