Friday, April 20, 2012

OpenGL 3.3 - The Rant

As might be known, I have an experimental OpenGL 3.3 Quake 2 engine that I've been working some on recently. Part of the motivation for that was to scratch an itch I had about how modern(ish) OpenGL compares to other APIs, and part of it was some fairly intense frustration at the older OpenGL API being used by RMQ.

This is basically an OpenGL 3.3 core profile, meaning that absolutely everything is being done with shaders and VBOs, and no deprecated functionality is used.

Regarding the API itself, it's quite nice to work with. I'd place it as better than D3D9 but not as good as D3D11 in my personal rankings; a lot of the insane stuff that was brought in with GL 1.5, 2.0 and 2.1 is just gone, and in it's place are some good, common-sense features. Unfortunately some insane stuff remains, but I guess you can't have everything.

What's good is glMapBufferRange, which makes dynamic vertex buffers actually usable with the discard/no-overwrite pattern that D3D has had for the past 12-odd years (it's actually marginally nicer to use than D3D11's Map). Explicit vertex attribute binding locations are something that should have been in the first version of GLSL. Vertex Array Objects look good on paper, but I'm either misreading something in the spec or hitting a driver bug as I can't seem to get them working right. Texture arrays make lightmap handling an absolute breeze, allow for larger draw batch sizes, and remove a lot of messy CPU-side sorting. Primitive restart is nice to keep index buffer sizes down, but it's maybe a 50/50 wash with converting to triangles. I haven't done much in the way of geometry shader work yet, but I'm hoping to get something going with particles shortly.

What's not so nice are the things that weren't fixed, and the things that are obviously first-cuts of a design-by-committee spec.

Whoever on the ARB is so in love with bind-to-modify needs to be taken out and shot. It's astonishing that this hasn't been removed from the API yet. GL 3.0 was the perfect opportunity, and they missed it.

Uniform Buffer Objects share one nasty characteristic with D3D9 occlusion queries - they look like they were designed by a pack of monkeys on LSD. I'm sure that there's a sane, usable API in there somewhere, but it's not coming through from reading the spec and looking at code samples.

Lack of explicit uniform binding locations is another missed opportunity. If UBOs were sane this wouldn't be such a big deal - I'd just use UBOs (as I do with constant buffers in D3D11) and be done with it. This is a step backwards from the old ARB assembly programs, and compares unfavourably with HLSL, which has always supported it (but not required it) in all of it's incarnations.

Not being able to use the default depth buffer with FBOs - that just sucks. It wouldn't have hurt to include it as an option.

Despite all that, it is mostly fun to use, and I'm feeling quite productive writing code rather than feeling like I'm fighting against stupidity most of the time, which overall ranks it reasonably high. A good result.

3 comments:

Anonymous said...

does this mean you're considering moving to ogl 3 for rmq?

mhquake said...

Not my decision. RMQ still needs to run on a lot of legacy hardware though, so it's unlikely, but the final decision about that is with the team leaders. This one was just to scratch a personal itch.

Spike said...

my problem with ubos is that I'm not really sure how to use them in a generic way, that is - how do I avoid calculating expensive matricies if I can't tell when the shader doesn't need them. or should I be creating a different ubo layout for every single shader? for anything where the shader is strictly hardcoded in the program I guess they're a real joy.
vaos are kinda annoying too. I'd be happier with them if my nvidia drivers didn't crash so easily with it.
targetting a core context requires so many different things, vbos, vaos, ubos, glsl, matricies, textures, just to get something on screen, its all kinda daunting for a newbie, or even myself when I've got something wrong but don't know where... gl3 is simple but complex. which makes no sense.

but yeah gl3 allows some rather streamlined draw calls.