4 ms·
Would you mind clarifying your problems with the API? I've done a fair amount of work with OpenGL (mostly ES), and I've found it to be a sensible low-level targ
by rrradical 12y ago
Would you mind clarifying your problems with the API? I've done a fair amount of work with OpenGL (mostly ES), and I've found it to be a sensible low-level target for my rendering engine. That's not to say I haven't run into problems, but I assume any high performance graphics API has a learning curve. I don't have experience with Direct3D or other APIs to compare with it though.
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.
- flohofwoe 12y agoThe most confusing part to me is that the 'fast paths' in the API are not obvious, especially if you need to support older GL versions (GL2, GLES2). For instance: - 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.
- fzltrp 12y agoIn my humble opinion, they should write formal specifications which are not just targetting a C API, but may degrade consistently to a C API. With a more formal description of each function call, including predicates for parameters, and possibly the context itself, they make things way easier for user land, where these could be mechanically translated into API bindings, and thus checked automatically. If all these checks are made on the user side, then they may add a simple toggle in the API to remove the checks on the driver side. Most users aren't using the C API directly anyway, and people writing bindings would welcome specs which could be mechanically translated into their favorite language bindings. The problem might remain for WebGL though.
- flohofwoe 12y agoThere's actually an XML spec, don't know whether this is enough to automatically generate language bindings from it though: https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/gl.xml https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/pub...
- exDM69 12y ago> don't know whether this is enough to automatically generate language bindings from it though Yes it is and most language bindings are generated using them. This also includes "OpenGL extension loaders" which are required in C apps too.
- fzltrp 12y agoI have to admit that, while I knew these documents existed, I was not aware they included as much information as they do: I was under the impression that it was merely an xml version of the original C headers to facilitate their parsing. Having a second look, it seems that it also covers information like array expected size and valid enum subsets for parameters, which is very valuable data for all players using the API (even driver implementors could use it to generate basic conformance tests).
- deleted 12y ago[deleted]
- hrjet 12y agoThe craziest thing I found in OpenGL API was that there was no way to bind data to a primitive. You have to repeat it for every vertex of the primitive, which sometimes also means that you can't share vertices between primitives. This results in a 9x overhead in data for triangles! Examples illustrating what I am saying: http://stackoverflow.com/q/6530700 http://stackoverflow.com/q/6530700 http://stackoverflow.com/q/6056679 http://stackoverflow.com/q/6056679 http://stackoverflow.com/q/23879737 http://stackoverflow.com/q/23879737
- exDM69 12y agoYou can definitely "bind data to primitives" and share vertices between triangles in OpenGL and that has always been possible ever since the first version of OpenGL. 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.
- hrjet 12y agoI meant to say "bind data to elements". It's been a while since I programmed in OpenGL so the terminology is shaky. 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.
- flohofwoe 12y agoYou can share vertices between primitives if all vertex components are the same and indexing is used. 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...
- hrjet 12y ago
- exDM69 12y agoWithout getting into details, the worst part of the API is the inherent statefulness of it. To exaggerate a little, OpenGL is essentially a very complicated global state variable where state changes have side effects. (actually it's thread local but global scope in most programming languages - but this only makes matters worse) 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.