A little while ago someone linked to this list of complaints on OpenGL from Valve Developer Rich Geldreich. It’s pretty common knowledge that I use OpenGL in all my projects, and some people are wondering what I think of this list.
Here we’re talking about the OpenGL API. API is Application Programming Interface. If I write some code and bundle it up in a package for others to use, then the API dictates how you (another programmer) can use it. It’s the control panel for my code. The design of an API involves a lot of things. I can give you lots of power at the expense of making things really complicated. I can make things very clear at the expense of making you do a lot of typing. I can save you some typing at the expense of making everything inscrutable abbreviations. A good API is easy to read, offers you exactly the functionality you need, and once you learn half of it you can intuit how the rest works. A bad API will send you to the docs again and again so you can figure out why it’s not working even though it totally should because I copy-pasted right from the example and it’s still not working what the hell!?!?
I can’t actually comment on a lot of the points Geldreich makes. The author is coming at OpenGL from a very different angle. I’ve never messed with console ports. I haven’t touched Microsoft’s toolset since the 90’s. I’m usually mucking around with procedural content, not pushing the hardware as hard as I can. (Although my current project is a tiny step in correcting this.) All of this means that I don’t have anything to compare OpenGL to, because I haven’t really used it in difficult circumstances or explored the alternatives. Furthermore, my low-tech work means I’m just less sensitive to quirks in the system.
On the PC, the two big players have been Direct 3D and OpenGL, and I gather they’ve been playing tug-of-war since the 90’s. At first OpenGL was faster. Then D3D. Then OpenGL again. Now it sounds like D3D has the performance edge. Again, I’m just extrapolating. I don’t have any first-hand experience with D3D.
But I suppose I can comment on a couple of these points. Here is what I think, put in plain language for non-coders. (Bolded text is from original article.)
|This was what the world looked like when OpenGL was designed. Image credit: VintageComputing.com|
1. 20 years of legacy, needs a reboot and major simplification pass
I agree. OpenGL was first introduced in 1992, which was so different from today that it might as well have been invented on another planet.
One example of how OpenGL shows its age: There’s a lot of unused stuff in the API for dealing with rendering using a 16 or 256 color palette, which hasn’t been relevant since the early 90’s.
The problem here is getting people to agree on which stuff needs to be thrown out. This might be one of those situations where everyone only uses 10% of the API, but each of them uses a slightly different 10%. Still, I’m sure there are a few things nobody uses.
But it’s not just about unused things. It’s also about very, very old ways of doing things. For example, at any given time there are a ton of switches you can turn on and off to control how things are drawn. Want to disable texture mapping so everything is flat color?
Want to enable it again?
Here, let me set a bunch of switches:
glEnable (GL_CULL_FACE); glDisable (GL_FOG); glEnable (GL_DEPTH_TEST); glDisable (GL_LIGHTING); glEnable (GL_BLEND);
This syntax is pretty old-school.
glEnable () just takes any old value you like, so it’s possible to confuse things. I might accidentally do
glEnable (GL_DEPTH_FUNC) instead of
glEnable (GL_DEPTH_TEST). The first actually doesn’t make any sense and will probably do something random. (Like flip some other, unrelated switch that I may or may not even care about.) A more modern design would make it so that using a wrong value like this will immediately be flagged as an error, letting me know the thing I’m trying to enable isn’t an on/off switch and shouldn’t be used this way.
More confusing is stuff like this:
glDepthWrite (bool enable);
Er. So we’ve got all these switches we can turn on and off with
glEnable () and
glDisable (), but then here we have a special switch with its own name. Why doesn’t it work like all the others? Why does it get its own special function like this? There’s even a value in the headers that makes it look like
glEnable (GL_DEPTH_WRITEMASK) should work, but no. (If you arrived via Google and are wondering why this doesn’t work: GL_DEPTH_WRITEMASK is just for use with glGet () so you can see if it’s on or off. You still have to use
There are dozens of oddball conventions like this. All of them can trip you up and lead you to wrong conclusions.
2. GL context creation hell:
YES. Gah. So annoying.
Okay, so in order to start drawing stuff we first need a window. How it works on Windows is that we create a Windows-windowDamn you Microsoft, this sentence is all your fault. You shouldn’t name your operating system WINDOWS for the same reason you don’t create a model of car called AUTOMOBILE or ENGINE. and then we plug that window into OpenGL so it knows where it is supposed to be doing its drawing. This ends up being pages and pages of boilerplate code.
And then when you port to Linux you need to re-write all of it.
And then again for Mac, Xbox, Playstation, UNIVAC, or wherever else you’re trying to port to. Since OpenGL has to have a bunch of talking-to-windows code that’s unique to each platform, couldn’t it just do me a favor and also create the damn thing while it’s at it?
So what happens is we all turn to some third-party solution (yet another API) to abstract away all of this stuff.
OpenGL lets you call this as a way of asking if anything is wrong. “Hey, is anything screwed up?” The problem is that it’s not terribly useful. The errors it returns are obtuse to the point of comedy. They boil down to “You did something you shouldn’t have at some point.” So if you’re looking for where you went wrong, you can either check
glGetError() every single time you do ANYTHING (which would be insane) or just check it once per frame and if it has a problem you go hunting for it manually.
9. GLSL version of the week hell:
I’ll add my biggest gripe, which arguably might be part of #10 on Geldreich’s list:
No basic types for dealing with polygon data.
When you’re throwing polygons around, you need vectors of xyz values. You need tables of numbers (called a matrix) for manipulating those values. You need red-green-blue color values. OpenGL, being old as hell, doesn’t offer this stuff. Which means EVERYONE writes their own. This becomes fun when systems collide. I write my own vectors from scratch. Maybe I call my vector a Shamus3D. Then I use some code written by someone else for importing 3D models. That guy needed vectors in his project, so he wrote them and named them Bob3D. Oh! And this physics library has vectors called
PhysicsThreeDeeVectorFloatsYou can always tell which programmers have massive jumbotron monitors. They’re the people who seem to think screen space is limitless and variable names are a great place to tell your life story.. And here’s another vector with this positional audio package.
And now I’ve got four or five different types of vectors that supposedly do the same thing but which aren’t compatible.
In newer versions of OpenGL, the matrix stack is deprecated. Meaning, you’re not supposed to use the matrix system that’s built into OpenGL. But since OpenGL doesn’t come with matrix variables it means everyone will need to write their own matrix code. There’s no way that doesn’t end in tears.
I think the bare minimum you need for doing ANY kind of graphics programming is: Vectors, matrices, and RGB color values. Vectors should do basic arithmetic with each other and matrices.
And that’s just to save us from living like savages. To have a really robust toolset we should also be able to do dot product, cross product, reflection, and normalization on the vectors. And we should also have quaternions.
The danger here is that this is the stuff of holy wars. What do we call the vectors?
It doesn’t say how many dimensions it has, which can lead to confusion if we add a 2D vector later.
Ugh. Long and mixed case, with capital letters on the front AND back.
Yeah, no. Looks like it says “Ogleved”. Maybe the types should have a lowercase prefix like the rest of the library.
Actually, the rest of the library uses lowercase “gl” followed by a capitalized word.
Is the d really necessary?
Now it looks like Hungarian notation. People will think “gl” is the type.
That’s not how you’re supposed to use Hungarian!
That doesn’t change the fact that it’s confusing!
It’s not the job of the API to protect us from bad coders!
YOU’RE a bad coder.
Your MOM is a bad coder!
Anyway. Even if we can get these idiots to agreeAnd good luck with that. There aren’t two agendas in this argument, there are dozens. how to name stuff, we’re still faced with the problem of where to draw the line. How much stuff do we add? Vectors are nice, but we could do more. This isn’t just a slippery slope, this is a mountain of grease. What I outlined above is nice, but you could make a strong case for adding a lot more:
2D vectors would be handy for dealing with texture coords or 2D rendering. We’ll also need them to do arithmetic with each other. And they should probably interact with matrices and 3D vectors in a sensible way. Maybe we should have some kind of abstract “model” class that ties a bunch of vectors, vexture coords, and color values together into something we can render.
And nearly everyone needs tools for reading image files and turning them into textures, so we should probably add that too. And if we’re doing that, then we might as well add the ability to convert between various internal image formats. And if we’re importing images then on top of RGB color values, we ought to have a HSVHue, saturation, value. In this system we define a color by what hue it is, how saturated the color is, and how bright it is. value and the ability to freely convert between the two.
Model manipulation! Animation formats! Variables for holding triangle indices! Bounding boxes! Common GLSL tools like
Lerp () and
Smoothstep ()! A flashlight and a can opener!
OpenGL has been about the low-level interactions with graphics hardware for as long as there’s been graphics hardware. But if you go too far then you end up making a massive “game engine” instead of a simple “graphics API”. And I think the minimalist design is one of OpenGL’s strong points.
Still, I think the basics of vectors, matrices, and RGB color values are warranted.
OpenGL is old. It’s odd. But it’s basically the only way to get polygons on the screen if you’re not looking to to create an arranged marriage between your project and Microsoft. We need it, but it would be great to have this functionality with a modern interface.
 Damn you Microsoft, this sentence is all your fault. You shouldn’t name your operating system WINDOWS for the same reason you don’t create a model of car called AUTOMOBILE or ENGINE.
 You can always tell which programmers have massive jumbotron monitors. They’re the people who seem to think screen space is limitless and variable names are a great place to tell your life story.
 And good luck with that. There aren’t two agendas in this argument, there are dozens.
 Hue, saturation, value. In this system we define a color by what hue it is, how saturated the color is, and how bright it is.
Juvenile and Proud
Yes, this game is loud, crude, childish, and stupid. But it it knows what it wants to be and nails it. And that's admirable.
Linux vs. Windows
Finally, the age-old debate has been settled.
The Best of 2016
My picks for what was important, awesome, or worth talking about in 2016.
Games and the Fear of Death
Why killing you might be the least scary thing a game can do.
A video discussing Megatexture technology. Why we needed it, what it was supposed to do, and why it maybe didn't totally work.