17/08/2013 update: after this post, you should read this addendum
I’ve been working with 3D graphics in the past, but never at low level. That was something I really wanted to do: high level tools are fun for building stuff rapidly, but you know, you never get that sense of fulfilment from knowing exactly what’s going on under the hood.
For working with 3D computer graphics at low level there aren’t many options to choose from: OpenGL or DirectX. I’m not a big fan of online religion-wars, but for me picking OpenGL was a no-brainer: portability and openness always mattered to me, and anyway OpenGL knowledge nowadays is even more attractive for its applicability on mobile platforms (OpenGL ES) and the web (WebGL). Also, the common opinion is: once that you know one of the two, switching to the other one is not that hard.
After deciding to learn OpenGL, I started reading documentation and testing small code snippets.
There’s a lot of OpenGL documentation, but when you’re a newbie it’s not easy to choose a book or a series of tutorials that works for you. Getting oriented needs a little time, and there’s another important thing to be aware: the switch from immediate mode to “modern”, shader-driven OpenGL programming, made a lot of available documentation outdated.
Of course you can learn tecniques from old-style tutorials and update their implementations to the current best practices, but that’s something for who already knows the basics – if you are starting to learn, you need some working foundations.
Also, OpenGL is narrowly focused on interacting with the GPU to provide 2D/3D graphics rendering, so to get up and running you basically need a few libraries that handle these tasks:
- creating an OpenGL context on your operating system (something that is out of the OpenGL specs, and so platform dependent)
- handling input from at least keyboard/mouse
- performing mathematical computations commonly used in 3D computer graphics (with vectors, matrices, quaternions…)
- loading OpenGL extensions
- loading images to be used as textures
- loading 3D models (maybe with animations)
So, the main questions are:
- what documentation?
- which supporting libraries?
For a quick hands-on introduction that doesn’t involve buying books (and, from what I read online, it looks like there’s not really any single book everybody agrees it’s the best way to learn modern OpenGL: you need to use multiple sources anyway), I think these series of tutorials offer lots of useful information:
- http://www.opengl-tutorial.org/ (using GLM and GLFW)
- written for beginners, and so very easy to follow: a good place to start
- http://ogldev.atspace.co.uk/ (using a custom math class and FreeGlut)
- many interesting tutorials, ranging from basics stuff to more advanced topics such as shadow volumes, deferred shading, skeletal animation
- http://www.arcsynthesis.org/gltut/ (using GLM and FreeGlut)
- a little hard to start with, but often goes deeper than other resources and also provides a good amount of theory. An interesting framework gets built as you proceed with the tutorials, but you often need to take your time and study the code on your own
Other stuff worth checking:
- work in progress at the time I write, but the basic info is there already and is in my opinion very nicely presented
- many interesting readings, such as the “GLSL core Tutorial”
Which supporting libraries?
I propose here my choices, based on my recent experimentation, but beware: I’m not saying these are absolutely the best libraries, I’m saying that I think these are the ones more appropriate, for the little I found out in the past weeks, in a position similar to mine (learning and experimentation trying to use a modern approach). Next month I could change my mind 🙂
So, context creation/window handling and basic input are often handled by a single library.
Freeglut is a popular choice for this, and was the first library I tested, but then I switched to GLFW.
GLFW looks more actively developed and modern, and provides many options in the creation of the OpenGL context. Freeglut is an open source rewrite of the GLUT library, that dates back to 1998 (!), so while it’s worth checking (at least for understading the structure of the many examples that use it), I think it’s better picking something else.
I prefer the way GLFW handles input (offering both polling and callbacks), and another difference I find important is that it puts you in charge of controlling the main render loop, while with Freeglut you must use the idle/display callbacks.
Alternatively, SDL, SFML and Qt are some bigger libraries that provide lots of other functionalities and aren’t focused on OpenGL, but support it. Even if they might end up being more productive/useful at some point (for example when you are developing a full featured game or a 3D enabled application), I think that they aren’t the right choice for learning purposes and experimentation.
So, the first winner is GLFW.
What about mathematics? In many tutorials/examples I see, a custom minimal math library gets built. Probably, math inclined people like doing that for getting a more deep understanding of the involved data types and operations. I’m not one of them: I think in my life I’ve already learnt and forgot how to invert a matrix too many times, so I’m happy to have a well written and tested library that does that for me. I’m not saying that it can’t make sense at some point (when you start thinking about optimization, device costraints etc) but surely not in learning stage. And excluding efficiency concerns, picking the math library is easy: OpenGL Mathematics (GLM). Why? Simple: its classes and functions are similar to those of GLSL, the OpenGL shading language. You have to write shaders in GLSL, so you have to learn that syntax anyway, so it’s nice being able to use it in C++ code too. I also have been using the Configurable Math Library (CML) for a bit, and while that’s probably a perfectly viable alternative, and a valid C++ math library, I think that for learning purpose the advantage GLM gives with its syntax is unbeatable. Both are header only libraries, and that’s cool.
Second winner: GLM.
What’s next? Extension handling. AFAIK there are only two alternatives: GLEW and GLee. And picking the winner here is easy too: GLEW is the most recently updated of the two (2012, providing support for OpenGL 4.3, against 2011, supporting OpenGL 3.0)
What about image handling for texturing? As you can imagine, image files handling is a common task also outside the scope of 3D graphics, so many libraries exist. So, it’s about picking between the ones supporting image formats particularly used in texturing, and maybe explicitly written to be used with OpenGL. Honestly I still haven’t made my choice in this area. For production purposes, I’d care about speed (and so, texture compression: you might want to check this paper from Nvidia), but for learning, I think it’s more about what library supports more formats, is painless to add as dependency, etc. I’ve found myself using using DevIL, FreeImage and ImageMagick. I still have to test OpenGL Image (GLI), that’s from the same author of GLM (something that encourages me to try it). Another library on my radar is Simple OpenGL Image Library (SOIL) .
Last step: loading 3d assets. The winner here is Assimp (yeah, I know, some could think Assetimp would have been a better name, but I’m with the developers and their unintentional pun, as explained in the FAQ). It supports a wide range of formats, and for what I know there aren’t similar alternatives.
If you are a 3D artist too and do your own models, or someone does them for you following your directions, you might want to stick to a single format and use a specific loader for that one, avoiding a library dependency. Otherwise, using Assimp looks reasonable, and avoids you wasting time converting models around.
What about skinning and character animation? I’m not at that point yet, and it’s out of my current scope, but if you’re interested in that, I’ve heard about Cal3D. Maybe I’ll look into it in a future post, for now I think I’ve already written too much 🙂
Do you think I missed something important? I would be surprised of the opposite, so feel free to leave me a comment!