All of my complaints with OpenGL are related to, as jarrett mentioned, the lack of debugging tools and the fiddly cross-platform and cross-version issues.
All of my complaints with OpenGL are related to, as jarrett mentioned, the lack of debugging tools and the fiddly cross-platform and cross-version issues.
If you look back (or remember) graphics APIs from the 1980s and 1990s (e.g. the BGL library that shipped with Borland compilers), this was a common idiom.
Rather than saying
drawLine(100, 100, 200, 250, RED);
drawLine(200, 250, 300, 300, RED);
You did setColor(RED);
movePen(100, 100);
lineTo(200, 250);
lineTo(300, 300);
The idea behind this was to minimize the number of parameters passed to function calls, because they had to be pushed to the stack and then read back. This was a major source of performance overhead back then.So basically OpenGL is modelled after a performance optimization that was relevant some 30 years ago. These days it's actually hurting performance and adding unnecessary complexity. Premature optimization of the worst kind.
You could do a little comparison on how Direct3D 10.1 and newer work. The API is simpler, lot less stateful and you get a better idea what will actually happen. If I had a choice, I would use D3D, but it doesn't run on the platforms I care about.
- Using Vertex Array Objects should be fast since it's only a single call to change the vertex data binding. But in many GL implementations they are slower then using the old way calling VertexAttribPointer and EnableVertexAttribArray
- What's the fastest way to update dynamic vertex data? Buffer orphaning? Doing double buffering yourself? BufferData or BufferSubData? It's likely that the answer is different dependent on driver or GPU
Resource binding can introduce subtle errors by screwing up the GL state (for instance to create and initialize a resource you need to 'make it current', should the creation function restore the previous binding, or keep the GL state 'dirty'?)
Some call parameters are overloaded with completely different meaning depending on GL state. For instance the 'const void* pointer' argument in VertexAttribPointer is actually an integer offset and not a pointer if an array buffer is bound.
The most important problem which the OpenGL NG initiative tries to solve is validation overhead. In current OpenGL, an app can change every state at every time in the frame, and after each change (or rather before each draw call) the entire GL state must be validated. Most games (or 3D apps in general) only create a relatively small set of 'pre-compiled' state at startup and then just switch between these state presets. With this pattern, all expensive validation can happen once at startup, and not during the render loop.
Yes it is and most language bindings are generated using them. This also includes "OpenGL extension loaders" which are required in C apps too.
Examples illustrating what I am saying:
http://stackoverflow.com/q/6530700
Are you talking about legacy OpenGL style glBegin/glVertex/glEnd? That hasn't been the preferred way of drawing ever, and since OpenGL 1.5 (circa 1999), vertex buffers are the way to go.
If you want to share vertices between triangles, you should build and index buffer and use glDrawElements* functions.
I saw your other answer below too. I am not able to visualise how the duplicate data could affect caching postively. But anyway, I don't have deep knowledge about the hardware.
And I didn't know other 3D APIs had the same problem. Thanks for mentioning that.
That's the same on all 3D APIs though. I think the only exception was the Wii where you could have positions, texcoords, normals, etc... in different arrays of different sizes and index them with multiple indices per vertex. I can't image that this was efficient though...
I see your point, having interlaced vs. non-interlaced data arrays. Many 3d model interchange formats use the latter because it saves some bytes. All 3D APIs use the former.
But this example works exactly the same way on every 3d API out there. Having a single index per vertex (rather than separate indices into position, normal, texcoord arrays) simplifies the vertex pipeline a little bit.
Using a single index will also make more efficient caching of vertex data and post-transform caching (ie. output of vertex shaders are cached if possible). Separate indices would need more complicated cache addressing.
Of course, with modern OpenGL, you can do more complicated addressing of data in the vertex shader. This isn't likely going to increase performance, though.
However, this is largely a non-issue. Modern 3d graphics simply isn't limited by the number of vertices or triangles. Having to duplicate some data isn't going to make a significant difference in practice.
Also, you can toggle the interpolation mode for varying variables (ie. fragment shader inputs) so you can use per-vertex normals and make them flat shaded if your whole model is going to be flat shaded.