
Projection matrix
There are two kinds of projection we can apply to the graphics pipeline, Perspective and Orthographic. Perspective projection, like the name implies, views the world in perspective, there is a vanishing point somewhere in the distance. Orthographic projection, on the other hand, has no vanishing point. If two lines are parallel in an orthographic projection, they will never touch. For this reason, perspective projection is generally used to render 3D elements, and orthographic projection is generally used to render 2D elements:

When designing a projection matrix the most important thing is not the perspective, but the coordinate system. Depending on how we construct this projection matrix, the world will either be in a Left Handed Coordinate System or a Right Handed Coordinate System. The difference between these coordinate systems is the direction of the Z-Axis. In a Left Handed Coordinate System, +Z goes into the screen. In a Right Handed Coordinate System, +Z comes out of the screen. The reason we call these views Left and Right Handed is because you can easily memorize them using your left and right hands.
Make a fist with both your hands. Extend both thumbs. Rotate your right wrist so both your thumbs are facing to the right. Extend your pointer and middle fingers. Your thumb is the X-Axis, your pointer finger is the Y-Axis, and your middle finger is the Z-Axis. Your left hand matches the orientation of a Left Handed Coordinate System while your right hand matches the orientation of a Right Handed Coordinate System:

Let's explore how we can build Left Handed Perspective and Orthographic projection matrices:

To build a perspective matrix, you first have to know the Field Of View (FOV) of the camera. Through trial and error, most games end up using an FOV of 60. We also need the aspect ratio of the screen; this is the width of the view area divided by its height. Lastly, we need to know the near and far distances of the view area.
Deriving these matrices is difficult, and there are different versions of each matrix online. If you are interested in the math behind the projection, the following article covers deriving both perspective and orthographic projections:
http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c10123/Deriving-Projection-Matrices.htm
Getting ready
We are going to implement both of the preceding projection matrices. The perspective projection function will take a field of view, an aspect ratio, and the near and far plane as arguments. The Orthographic projection function will take each side of the projection volume as arguments: left, right, top, bottom, near, and far. Both functions will return the matrices shown previously.
The standard C math library does not have a cotangent function. You can find the cotangent as follows: .
How to do it…
Follow these steps to implement orthographic and perspective projection matrices:
- Add the declaration for the
Projection
andOrtho
functions tomatrices.h
:mat4 Projection(float fov, float aspect, float zNear, float zFar); mat4 Ortho(float left, float right, float bottom, float top, float zNear, float zFar);
- Implement the
Projection
function inmatrices.cpp
:mat4 Projection(float fov, float aspect, float zNear, float zFar) { float tanHalfFov = tanf(DEG2RAD((fov * 0.5f))); float fovY = 1.0f / tanHalfFov; // cot(fov/2) float fovX = fovY / aspect; // cot(fov/2) / aspect mat4 result; result._11 = fovX; result._22 = fovY; // _33 = far / range result._33 = zFar / (zFar - zNear); result._34 = 1.0f; // _43 = - near * (far / range) result._43 = -zNear * result._33; result._44 = 0.0f; return result; }
- Implement the
Ortho
function inmatrices.cpp
:mat4 Ortho(float left, float right, float bottom, float top, float zNear, float zFar) { float _11 = 2.0f / (right - left); float _22 = 2.0f / (top - bottom); float _33 = 1.0f / (zFar - zNear); float _41 = (left + right) / (left - right); float _42 = (top + bottom) / (bottom - top); float _43 = (zNear) / (zNear - zFar); return mat4( _11, 0.0f, 0.0f, 0.0f, 0.0f, _22, 0.0f, 0.0f, 0.0f, 0.0f, _33, 0.0f, _41, _42, _43, 1.0f ); }
How it works…
The purpose of both of these projection matrices is to remap eye space into clip space, sometimes called projection space. In OpenGL clip space is a unit cube ranging from -1 to 1 on all axes. In DirectX clip space is a unit cube ranging from -1 to 1 on the X and Y axes, but ranges from 0 to 1 on the Z axis. For the perspective projection this is important because the contents of the frustum created by the matrix need to be scaled non-uniformly to fit into a cube.
Orthographic projection is defined by a cube area. This makes creating the Orthographic projection matrix easier than the perspective projection matrix. All this matrix has to do is remap the contents of a box into a cuboid.
Perspective projection is a little more complicated than orthographic projection. Because we have to remap a frustum shaped area into a cuboid, non linear scale must be used. The perspective introduced by this projection matrix also means that a four-dimensional vertex will not have a W component of 1 after being multiplied by the perspective projection matrix.