Open GL & Orthographic Projections
December 9th, 2011I’m currently working with Open GL ES 2.0 in Android for developing games. I’m focusing on 2D graphics which consists generally of rending quads on the z=0 plane in orthographic projection. I’ve had to code up a boiler plate a couple times and I keep having to scrounge the internet for the right code to setup the view port projection. Most tutorials are for 3D and go about showing you how to setup a model view projection matrix which isn’t all that helpful when you’re working in 2D.
I spent some time tonight working it out from scratch and now that I’ve got a good grasp on it I figured I’d put a quick run down of things to remember when setting up the basic render projection.
First, when you initialize the GL view port you are started off with a basic orthographic projection. However, It’s domain and range are (-1, 1) and the origin (0,0) is centered in the view port. Also, it is skewed to match your view port dimensions. That is to say, if you have a 300 x 200 view port you will have an orthographic projection with an aspect ratio of 3/2.
When working in 2D it is much more convenient to have the origin at the top left corner of the view port and have the domain and range be [0, width] and [0, height]. So we need an orthographic matrix that transposes and scales the projection to match our view port.
The “default” orthographic matrix looks like this:
[ 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 1 ]
The first step, is to scale the projection to match our view port.
[ 1/width, 0, 0, 0,
0, 1/height, 0, 0,
0, 0, 0, 0,
0, 0, 0, 1 ]
Our origin is still centered, so the next step is translating the origin to the top left corner. Now because we are moving the origin from the center we are effectively losing half of our display area. To compensate we need to adjust our width & height values by half (or simply double the numerator).
[ 2/width, 0, 0, 0,
0, 2/height, 0, 0,
0, 0, 0, 0,
-1, -1, 0, 1 ]
That leaves with an origin (0,0) at the top left corner of the screen, a domain [0, width] and a range [0, -height]. The last thing to address is the negative range. Right now, we have to specify a negative why value to show up in the view port. Which kind of makes sense when you think about the coordinate system in the traditional way of Y going up and down with positive values going up. But when it comes to graphic programming it is more convenient to flip the Y axis an have positive values going downwards. To fix the Y axis lets adjust the matrix one last time.
[ 2/width, 0, 0, 0,
0, -2/height, 0, 0,
0, 0, 0, 0,
-1, 1, 0, 1 ]
There we go. Now the range is [0, height]. This orthographic projection matrix can now be used in your shader programs. Your vertex position vectors should be multiplied by this projection matrix in order to be rendered correctly in the view port.




