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 wrote about this a couple of weeks ago.
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.
Bethesda felt the need to jam a morality system into Fallout 3, and they blew it. Good and evil make no sense and the moral compass points sideways.
Revisiting a Dead Engine
I wanted to take the file format of a late 90s shooter and read it in modern-day Unity. This is the result.
A Lack of Vision and Leadership
People fault EA for being greedy, but their real sin is just how terrible they are at it.
Game at the Bottom
Why spend millions on visuals that are just a distraction from the REAL game of hotbar-watching?
Raytracing is coming. Slowly. Eventually. What is it and what will it mean for game development?
78 thoughts on “Things that drive me nuts about OpenGL”
I’ve never used OpenGL before, but I have used irrlicht, which has a really nice and well-thought-out api – I don’t think I’ve seen a better one, actually.
It’s a high level graphics engine, so it’s got all of the stuff you’d need for messing around with vectors right there.
For me, though, I just found it fun to code graphics stuff without all the boilerplate code.
And then the Mantle API happened.
This is getting silly.
You are not alone:
That was the page he linked at in the FIRST sentence of the article, just so you know.
Yeah, my bad, dark blue links in black text on grey background.
Seconded, there are no visual cues that’s a link.
IS this isolated? Do other people have trouble spotting links?
It’s an easy change if it would help readability, but I don’t like to make theme changes without getting feedback first.
I can find the links, but I usually have to be looking for them and then it’s as much the text giving the cue that I have to pay attention to the shading (like “my column this week”).
I will notice links while reading the text line by line, but then have trouble spotting said links while scanning.
So that evaluates to “kinda hard” on the hardness scale. *snicker*
For what it’s worth, I have no trouble at all spotting your links.
I can make out the difference if I look for them or if you give a contextual clue in the text that there’s a link coming up, but I usually miss them when just reading through.
As you don’t use any other link decoration I’d suggest making the link colour contrast more heavily with the body text as I imagine they’d be invisible to a lot of people with worse eyesight than mine.
I always had to search around for the links, they look absolutely the same. I think you fixed that already.
Links are clear as day for me.
Heh. I guess I’m oldschool. I feel links embedded in text should be underlined, even if that’s considered “uncool” by modern websites, it’s clear.
Also this: http://www.shamusyoung.com/twentysidedtale/?p=23079
Thanks for the link! If you enjoyed that article the homepage of that guy’s site is worth a visit:
Alright, people, that’s enough. Do you want all the traffic from Shamus’s site to overload that poor guy’s server?
Yeah, it’s a decent site. There’s sometimes good discussion on the posts, too! I wouldn’t bother following any links you find there though, as the community never links anything worthwhile.
Actual new link, a response to the original blog (of which there are now quite a few by various renderer coders who obviously have opinions on their secondary API): http://timothylottes.blogspot.co.uk/2014/05/re-things-that-drive-me-nuts-about.html
This stuff is all a mess, which is why the recommended step is to remove cross-platform issues and boilerplate with something like SDL2 (seriously, use SDL2 or live with boilerplate and a complex API because you’re programming a thousands-of-cores-wide processor with wavefronts and decades of different underlying hardware that OpenGL all talks to and with basically no decent deprecation system beyond Core/Compatibility, and if you’re wanting to use the legacy features (which you already know) then you’re explicitly asking to use the more bloated API that allows for coding to 20 year old hooks) and maybe even some extra maths libraries on top of SDL2’s internal offerings. Using SDL2 can basically just abstract the OS-dependent window creation, input & output management, and context creation and destruction stages. In the core loop you’re still coding to OpenGL but other people have made sure to build the boring stuff and test it so it actually works on lots of hardware and many platforms.
OpenGL is far from ideal but sometimes what the coder wants and what is available involves compromises. And sometimes you really want ints but (until DX10 hardware) you were programming on what is just a lot of float(16/32 – depending on era and architecture) processing blocks so that’s not really what you’ll find available to you as an easy option.
I believe a big part of OpenGL ES was to toss out a lot of the old cruft so it would work better on mobiles. OpenGL ES 3.0 is pretty powerful now, and basically just for games.
But all the old stuff is still available via the header files and libraries (libraries since glXGetProcAddress / wglGetProcAddress just devolve into dlsym / GetProcAddress, so the function has to be publicly exposed in the opengl shared object / dll; header files since … I’m not sure, actually).
So yeah, ES removes a *lot* of cruft (…and in turn, actually turns opengl into more of a 2d API than a 3d API, since you have to do the 3d->2d projection in the shaders). But it won’t actually fix (what I consider to be) the problem until all the old cruft gets completely removed.
…Actually, it’s worse than that. Because a whole lot of docs and examples online are still pointed at the non-ES setup. Until that all disappears, there will still be a lot of confusion. :-/
(Which is why I like webgl actually; extensions need to be explicitly activated, the non-ES stuff isn’t present at all, and the whole setup is new enough that a lot of the old stuff isn’t mentioned online anywhere. It also fixes a lot of the context setup problems, although you still need a few lines of code to turn an HTMLCanvas into a webgl context, and it gets a lot more complicated if you try to handle context loss. The problem, I suppose, is that now you’re dealing with a browser.)
Don’t forget that most every functionality you add now will in turn be cruft in 20 years.
A fair point, though it would still be better than all the cruft from now plus the cruft from 20 years ago.
Direct3D isn’t much younger than OpenGL (though OpenGL was based on IRIS GL, but vastly cleaned up with operating system and window system dependencies removed). If I recall correctly, we got the beta version of Direct3D in late 1995 or 1996, not so long after the initial release of the Game SDK (later renamed DirectX).
Keep in mind that OpenGL (originally) was intended to just specify 3D rendering (and really, its an abstraction of a Z-buffer pipeline and not really a good fit for other rendering systems), details that would depend on operating system, 2D/window system, programming language, were carefully left out. This did cause a number of problems (see how texture management evolved over time) but allowed OpenGL to be useful across a fairly wide variety of platforms.
A number of these complaints seem to be from people whose idea of portability is supporting desktop Windows and Xbox, while OpenGL was intended to be supported on systems from Windows/C++ to IRIS/NeWS/FORTRAN
I don’t think there was ever a time that OpenGL was generally faster than Direct3D on the same platform.
1. My recollection is that enables/disables that got their own calls usually had major effects on the configuration of the rendering pipeline while the glEnable/Disable attributes were just rendering attributes. I think this also showed up in rendering accuracy requirements (see the section on conformance in the OpenGL spec).
2. Leaving out windows/buffer creation code out of OpenGL was completely intentional. Just think of all the ways things could go wrong across all the possible platforms and imagine if OpenGL was responsible for it. What would you do if you got an error from OpenGL, what then? OpenGL contexts actually aren’t tied to a particular buffer or window except when you actually go and bind it to one, and even then you can disassociate it and bind it to a different window. This allows you to run multiple windows with one context (and share the texture maps, display lists, and other bits of state) or have multiple processes share a context, etc.
Basic data types
Pretty obviously punted to keep it programming language neutral.
Now OpenGL as it stands now has had a lot of stuff bolted on which may conflict with some of its original design principles…
OpenGL should probably make OpenGL 4.2 (that’s the latest right?) become the legacy OpenGL (so that old games way back to OpenGL 1 can still run) and only fix serious bugs with the drivers.
Then remake the API for OpenGL 5.
Currently OpenGL32.dll is used on Windows (it’s called that as OpenGL.dll was for 16bit Windows way back when). With OpenGL 5 they could just change this to, I don’t know, OpenGL.dll or OpenGL_5.dll and target x64, maybe mix some of the Mantle ideas into OpenGL 5 for example as that is also a open standard.
4.4 came out last Summer, Open GL Next (which is maybe coming with OpenGL ES 3.1, nee ES Next, this Summer) will almost certainly be talked about at SIGGRAPH so August (is it going to be 4.5 or is it going to be 5? A few people who are in Khronos meetings have been blogging about ‘if there was an OGL5 this is what I’d want it to look like’ so maybe not a point release or maybe this is the last point release before GL5 and ZeroOverhead as the Core profile next Summer come to fight DX12 & Mantle for dominance of low-CPU overhead rendering).
Oops! I actually meant 4.4, not sure why I said 4.2, I was too lazy to check Wikipedia, so I’m the fool either way I guess . :)
In any case, looks to be an interesting summer then.
Maybe Shamus could do some commentary on the SIGGRAPH stuff (there will be videos released this year of the talks I assume), that would be nice.
The Quaternions sound like they should be having their dastardly plans foiled by Dr. Who.
Either that or a seven country tour attended by screaming teenage roadies.
More like a sparsely-populated mid-size theater. If the Qauternions isn’t the name of an arty indie group or a prog band that’s been trying to hit it big since ’74, I don’t know what it could be. Although ‘Quaternion’ could be an experimental electronica outfit of unknown real identity(s).
Gimbal Lock and the Quaternions? Loved those guys.
It sounds more like Irish graffiti than a band to me.
Nowadays you can use middleware like Unity to put polygons on screen and let it worry about how to handle the problems with OpenGL.
A higher level API like Unity really isn’t a replacement for OpenGL. For one, because Unity is for a specific purpose (making games) while OpenGL is general purpose (drawing stuff); but also because higher level APIs only expose a subset of features and flexibility of the lower level API (though good higher level APIs provide ways of directly working with the lower level API; not sure if Unity does; but then you’re right back in the problem of “the OpenGL API has issues”).
Re: Adding vectors/matrices/etc.
This is outside OpenGL’s scope. OpenGL is meant to provide an API for developers to access and draw stuff with the graphics card, not do CPU side matrix or quaternion operations. Get GLM or something else to do that.
If those data structures were specified in OpenGL, you would have twenty different implementations from Nvidia, AMD, Intel, etc. all with different performance and bugs, not to mention a terrible C API with no operator overloading.
How are vectors outside of OpenGL’s scope? Your code is giong to spending a lot of its life handing vectors and matrices to OpenGL (even if ultimately you’ll be writing the shader code that makes use of them).
That there will be significant implementation differences is silly. By that standard why bother with any of OpenGL, since the drivers will vary. What Shamus is talking about is really simple stuff, far simpler than the pretty much anything else in OpenGL.
As for it being a C-API, yup, that’s the most portable API. Just about any major language will support C-bindings. It’s not really all that awful, and if it bugs you its easy to built thin wrapper around it to provide a more idiomatic interface for your language of choice.
Well, opengl has plenty of support for putting data into arrays in whichever format you chose, which is arguably the simplest and most general way they could support types; there’s also little difficulty in getting vectors, matrices etc. into uniforms. I tend to agree that this was probably the only sane way to do it without losing flexibility.
GLSL itself has plenty of very convenient support for these types and operations, which is where (in the renderer) you really need them after all
The data structures ARE defined by the standard. If you want to send a matrix to a shader, you have to give OpenGL a chunk of memory (the API loves void pointers) that will be interpreted in a specific way.
That is to say, OpenGL says for a particular type of matrix operations “A matrix is a collection of 16 values of type GLFloat (defined as 32 bit floating point numbers), with no padding, in column major (or is it row major? I can’t recall) ordering.”
The user is then tasked with writing code that produces matrices following this specification. It would be reasonable for the API to provide a data structure that followed their specification. Even if they weren’t going to provide matrix transformation functions, it would be simple to build a math library on top of the OpenGL types and add interoperability to different systems (since they’d all be built on top of the same basic types).
It would also add some very necessary type safety to the interface. Whenever you called a function, you’d be guaranteed to have the right kind of parameters. As things are, you might give OpenGL the wrong type of matrix without it complaining about it. And since the API asks for void pointers, everyone has to build their own types, which makes interoperability much more difficult.
The different weird way some vector libraries I’ve seen have worked makes me glad there’s no default way of doing it. I’d rather take an additional couple of hours to write my own.
It’s kind of funny. Programming languages seem to have a lot in common with spoken languages: The ones most in use are constantly evolving and, on the whole, are contradictory and nonsensical in their rules and use. Anyone trying to nail down a set of standards probably starts to feel like someone trying to preserve the “purity” of French.
Dead programming languages remain the same, are studied by academics, and may someday be used to name new kinds of bacteria.
Geldreich points to some reasons why developers might not use OpenGL. He’s ignoring several very important reasons why OpenGL has a long life ahead of it. In rough order of importance: iOS, Android, Mac OS X, WebGL, SteamOS, Linux.
I’m baffled as to why he thinks Mantle is a serious player. There is a reason that manufacturer specific APIs died more than a decade ago. Mantle better shit gold to justify adding yet another API to port software to.
Don’t forget the Nintendo and Playstation consoles!
Playstation has a platform specific low level api (PSGL) based on OpenGL. Not a lot of info about it on the web, i guess they have a strict NDA.
You should read this fascinating post if you are even remotely interested in this topic.
Every API that uses a unit test suite should be forced to have a program that scans their documentation for example code and turns those into test cases, so they fail regression if the examples are broken.
(Also, every API should be forced to have a unit test suite)
So, okay, I know this will sound crazy based on your history… but have you ever messed around with the Blender game engine? It’s got a Python-based API, is automatically cross-platform, and supports parametric content creation right out of the box. It’s quirky as all get out, but if all you’re looking to do is mess around with parametric stuff, it’s a great tool. Especially since it’s also a 3d modeling suite, so you can explore and tweak the content that your code generates instead of iterating based on display all the time.
Of course, since you’ve got the boilerplate done already, it might not be worth switching over. Just a thought.
Shamus, have you ever tried something one level more abstract, like OGRE? I know it’s overkill, unless you already want a decently complicated 3D game, but it might still be worth a look. It’s cross-platform, and works with either D3D or OpenGL, whichever is installed on the machine already. I gave up trying to set it up after like an hour, since I just wanted simple 2D stuff, and started using PyGame for my tinkering. :)
So, wait… you are recommending something that you couldn’t get set up yourself after an hour of fiddling…???
Doesn’t sound very promising… :-)
Well, to be honest, it’s mainly C++-oriented, and I haven’t remembered how to fuck with C++ projects since school. Also, I was technically messing with the Python wrapper/port. ^^;
Damn,now all I want is to make a car named Automobile Engine.
Bonus: Automobile Engine is the model, but Automobile is also the make.
That’s like my car, an 89 Oldsmobile 88.
Took me 6 years to figure out what the car actually was.
Are you sure it wasn’t an 88 Oldsmobile 89?
Either way, pretty clear it isn’t a Newmobile.
Just recently I found out that the guy who made them was called Olds.My mind was blown.
Reading this makes me glad that I only ever mucked around with DirectX and HLSL. Couldn’t think of writing Shader Code without Vectors and Matrices.
And stuff like ‘float4 output.rgba = DiffuseMap.Sample(anisotropic, input.tex).abgr’ just makes me happy XD (I really like HLSL v
Also “That's not how you're supposed to use Hungarian!” should really be “You are not supposed to use Hungarian!“
Yeah…Hungarian notation shouldn’t ever be needed. If it is, your code isn’t clear enough. ^^;
Which Hungarian notation?
OK, so apparently, according to this blog post, the type of Hungarian notation I was referring to (“systems”), is the wrong kind, and in fact the kind to which the inventor of the convention was not referring. This is “systems” notation, where you prefix the actual data type of the variable. i.e. strUserName would be a string, chUserType would be a character, etc. Next-to-useless, what I was taught in school, only helps solve bugs which amateurs make. ^^;
“Apps” notation, is where you prefix the variables with what kind of data they contain: row coordinates vs column coordinates (e.g. rowPlayer, colPlayer), unsafe vs safe strings (usUserName, sUserName), window-coordinates vs screen coordinates (winX, scrX). Very useful, makes sense, what the original person meant in his (white?) paper. :)
Ugh. I hate that they teach ‘systems’ in schools. Would be fine if I had any reason to think they also taught ‘apps’ or even mentioned it, but I don’t.
But it’s also why I asked. There’s too much space for confusion since they’re so different and I’ve also ran into people who mentally go “Hungarian notation -> ‘apps’ notation”.
Same with comments, really. If your function needs comments to be understood, you should split it up (and give it a better name than ‘func2’).
Oh in the shaders you’ve got matrices and vectors and the operations you need, it’s outside of that, in your actual program you have to make your own.
The shader language does have support for vectors and matrices. Which makes it all the more strange that the OpenGL API doesn’t. Once in the shader, it looks pretty much like your code there. However, to feed the vertex data to the card so the shader can use it, you have to use something that looks like this:
glBufferData( GL_ARRAY_BUFFER, sizeOfData, voidPointerToData, GL_STATIC_DRAW );
glEnableVertexAttribArray( attributeNumber );
glVertexAttribPointer( attributeNumber, 3, GL_FLOAT, GL_FALSE, sizeOfVertex, 0 );
What those three lines are doing is, first, loading the data to a buffer, which has reasonable parameters. You tell it which buffer target to use, how much data you want to buffer, where the data is, and what kind of access you’ll use (basically, if you’re going to modify the data or load it once and not touch it again).
Second, you enable an attribute. Since a vertex can have a variable number of attributes (position, color, normal, tex coords, etc), this is a reasonable requirement.
Finally, and here’s the problem, you describe the attribute. First you pass the attributeNumber that you enabled in the line before, so it knows what attribute you are describing (each attribute could be different, tex coordinates have only two values, while position can have 3).
The parameters 3, GL_FLOAT, and GL_FALSE however, could have been compressed into a single attribute if the API provided data types like “vector3f”. What these are doing is first, telling OpenGL that your attribute has 3 components. Next, that these components are of GL_FLOAT type. GL_FALSE specifies whether fixed-point data values should be normalized or converted directly as fixed-point values, but since I’m using floats it doesn’t apply.
The next two parameters describe whether the attributes are tightly packed or if you have padding or have attributes interleaved, and where to start reading the buffer.
It’s especially annoying because the software model for OpenGL is not very intuitive. It’s like working with a massive machine, where you have to flip switches, activate levers and spin dials to set it up, using special loading bays for materials, before standing back and seeing if it chokes on all of it or finally produces the right output.
“The shader language does have support for vectors and matrices. Which makes it all the more strange that the OpenGL API doesn't.”
It can’t, because the GL spec is actually language neutral, so it can’t define classes. Any reasonable vector implementation should have lots of class members for doing things like transforming a vec4 by a mat4, but there’s no language neutral way of doing that. Adding a ton of C members like glMultiplyVectorByMatrix isn’t a solution either because those functions would massively inflate the API, while being useless to most people who already have their own vector library, homegrown or third party.
For C++, there is GLM, which is basically all the functionality of the GLSL types, plus quaternion types and a number of other extensions. This has the advantage of letting you use exactly the same syntax in C++ application code as in GLSL in almost all cases.
Re: Quaternions–I don’t mean to be insulting, but it amazes me how easily you talk about quaternions here and on Twitter, when just last week you had an (contextually) inappropriate formula up for the cross product.
I’ve tutored people in statistics before, who just never can understand how to find the probability of a die roll, but have a breeze if you explain the use of convolution integrals to find moment-generating functions.
It’s like there’s just some wiring there I can’t pick up on. To me, one of these things intuitive and the other isn’t, and I don’t get the process by which someone else sees it opposite.
The incorrect formula is because I can’t read backboard math, so I didn’t know what I was posting. (Which I would usually just leave out, but I wanted to make a joke about looking for scratch paper being “labor intensive”.)
The only math I understand is expressed as [pseudo]code. The f(n) business with Greek symbols is often opaque to me. I read about it when I can, but it’s one of those areas of knowledge that’s pretty much only used in the classroom, so you can’t learn it by just hitting Wikipedia. (Wikipedia is TERRIBLE for this. It often contains explanations that are only useful to people who already understand them. I found a PDF a while back that built things up from first concepts. (It was on how to build a mathematical proof.) But since I almost never use it, I can’t seem to get the concepts to “stick”.)
To be fair, you really shouldn’t be using Wikipedia unless you at least know something about what you’re looking up. It’s curated, I suppose, but from my experience it’s not really trustworthy enough to use as a learning tool. There have been a few times when I’ve seen misleading bits of information that would have completely screwed me up if I didn’t already know better before I read them.
OT, looking at it the way you describe, I can see the disconnect. The dice thing still gets me, though.
Would you happen to have some kind of resource locator for such a PDF, Shamus? A uniform resource locator would be marvellous.
I’m a bit surprised to hear that. f(n) should be really easy to understand for programmers, I’d have thought.
is just the maths way of saying
(Forgive me if I mess up the code; I’ve not worked in C for many years)
EDIT: OK, no code tags? Given your site’s focus and readership, that’s really weird.
“No basic types for dealing with polygon data.”
Or, more importantly, “And now I've got four or five different types of vectors that supposedly do the same thing but which aren't compatible.”
How would OpenGL help? Now you’d have five or six different types of vectors that supposedly do the same thing but are subtly incompatible!
OK, so you use OpenGL’s vectors. That’ll still be 4 or 5. Most of these libraries couldn’t use them (because they support Direct3D also) and would end up just rolling their own. Incidentally, Direct3D doens’t provide any vectors either (D3DX, or DirectXMath, or whatever Microsoft are calling it this week does, but that’s kind of analogous to OpenGL’s deprecated GLU except DirectXMath isn’t quite so deprecated and isn’t provided by the graphics driver). And if OpenGL did provide its’ own, well, now its’ just pissed off all of the 3D engine developers who now have to translate to/fro GLvector3 format (Incidentally, GL types are all named GL). Easier just to take a void* which happens to point to three packed floats (and also helps with the fact that modern vertex buffers contain arbitrary packed attributes – modern games use some crazy vertex formats)
The generally accepted
Isn’t the whole pointer thing the cause of all sorts of weird graphics bugs? Like, if it’s expecting a float and you pass it a float, your alpha channel is now full of garbage.
I began with OpenGL in the 90s but switched to Direct3D 8.1 then 9.0 and 10. Honestly I don’t ever want to see OpenGL act like Direct3D. The main thing that drove me away from Direct3D is that whenever I needed to get really low level, I couldn’t without driver specific hacks. It was either the Direct3D way or some cripplingly slow software solution or some absurdly complex shader solution. OpenGL however let’s me get really low level and in a platform neutral way.
It does however need a standardized math API.
No basic types makes me mad.
I was playing around in Scala and was using a 2D OpenGL library to not have to bother with this annoying crap, and lo and behold, it came with vector types, but lacked all the usual math functions (like cross product). Then I found a second library that dealt with the vector math, and now I have two vector types everywhere. That’s just stupid. If your API requires vectors, it needs to specify a data format for them, and offer the usual conveniences, or else it’s a shitty API.
Leaving out basic types is the reason why we still fight over which string type to use in C++, which makes every single application written in it twice as annoying to work with, and that’s on top of being C++.
hey, i mostly agree but have some comments:
1) Most of the glEnable/Disable stuff is deprecated now. If you use the core profile you get an error if you use glEnable(GL_TEXTURE_2D) because you are supposed to use shaders. The only things you can use there is stuff you cannot program with shaders directly, like blending.
2) Yeah Context creation is bad, but then i again it’s not really OpenGL. You have all the window system specific parts (WGL,GLX,AGL,EGL,..) in one place and set it up once. It’s a tradeoff for having a platform neutral api.
5) I dont use glGetError anymore. Have a look at ARB_debug_output and KHR_debug. Thy are required since 4.3, but virtually all the drivers expose it for older api versions too.
This is one thing that REALLY annoys me. I have not been the most active OpenGL programmer, but I have learned to create a couple nice programs with it and now I throw my hands up in the air because I have to start all over learning shaders?
I am considering taking up gardening at this point.
One thing I dislike about high level APIs that do everything for you (create windows etc) is that they… do everything for you! Which is great, when they work, but find a bug and you have to wait until someone else fixes it, or in one case I came across, the behavior was how they wanted it to be, which was obtuse and annoying and required lots of code to do something which should be simple. I kick myself in the butt for not taking the time to learn to do it all myself and instead become over reliant on a high level API. I just finished a project using a high level API and my next one I will concentrate on creating my own framework for a game with boilerplate code I understand and can maintain without relying on others.
I’d understand the lack of basic types in the library more if they also didn’t exist on the GLSL side of things; defining the format of the data you’re passing to the shaders is a wonderfully flexible system that can very easily have basic types built on top of it, but the shaders expecting attributes of specific formats instead of using the same attribute definition system destroys a lot of the flexibility the attribute system offers in the first place..
If the attribute format definitions were somehow shared between the C++ and GLSL, however, I could see things being a lot less frustrating to work with.
The major differences between D3D and GL is that D3D is Object Oriented and GL is not. D3D9 and GLES2 basically have the same features. In fact if you plan on using OpenGL and do not need any GL3 or GL4 features you should base all you code on the GLES2 API(all GLES2 features are in GL2, but not the other way around).
Err, I thought dot and cross product were basic vector arithmetic?
Thanks for joining the discussion. Be nice, don't post angry, and enjoy yourself. This is supposed to be fun. Your email address will not be published. Required fields are marked*
You can enclose spoilers in <strike> tags like so:
<strike>Darth Vader is Luke's father!</strike>
You can make things italics like this:
Can you imagine having Darth Vader as your <i>father</i>?
You can make things bold like this:
I'm <b>very</b> glad Darth Vader isn't my father.
You can make links like this:
I'm reading about <a href="http://en.wikipedia.org/wiki/Darth_Vader">Darth Vader</a> on Wikipedia!
You can quote someone like this:
Darth Vader said <blockquote>Luke, I am your father.</blockquote>