Decompose the OpenGL projection matrix

Sometimes you need to decompose the OpenGL projection matrix into its original components to adjust some values. Here's how to do that. I found a thread on stackoverflow on the subject. The formulas there are in row-major format though, but OpenGL is column-major, so they need to be swapped around:

For a perspective matrix:
near   = m43 / (m33 - 1);
far    = m43 / (m33 + 1);
bottom = near * (m32 - 1) / m22;
top    = near * (m32 + 1) / m22;
left   = near * (m31 - 1) / m11;
right  = near * (m31 + 1) / m11;

For an orthographic matrix:
near   =  (1 + m43) / m33;
far    = -(1 - m43) / m33;
bottom =  (1 - m42) / m22;
top    = -(1 + m42) / m22;
left   = -(1 + m41) / m11;
right  =  (1 - m41) / m11;

When you now use a standard C-Array for storage, the indices become:

For the perspective matrix:
GLfloat projection[16];
GLfloat near   = projection[14] / (projection[10] - 1.0f);
GLfloat far    = projection[14] / (projection[10] + 1.0f);
GLfloat bottom = nearPlane * (projection[9] - 1.0f) / projection[5];
GLfloat top    = nearPlane * (projection[9] + 1.0f) / projection[5];
GLfloat left   = nearPlane * (projection[8] - 1.0f) / projection[0];
GLfloat right  = nearPlane * (projection[8] + 1.0f) / projection[0];

For the orthographic matrix:
GLfloat projection[16];
GLfloat near   =  (1.0f + projection[14]) / projection[10];
GLfloat far    = -(1.0f - projection[14]) / projection[10];
GLfloat bottom =  (1.0f - projection[13]) / projection[5];
GLfloat top    = -(1.0f + projection[13]) / projection[5];
GLfloat left   = -(1.0f + projection[12]) / projection[0];
GLfloat right  =  (1.0f - projection[12]) / projection[0];

To calculate a matrix again from those values, use an identity matrix and set:

For a perspective matrix:
matrixProjection[0] = 2.0f * near / (right - left);
matrixProjection[5] = 2.0f * near / (top - bottom);
matrixProjection[8] = (right + left) / (right - left);
matrixProjection[9] = (top + bottom) / (top - bottom);
matrixProjection[10] = -(far + near) / (far - near);
matrixProjection[11] = -1.0f;
matrixProjection[13] = -(2.0f * far * near) / (far - near);
matrixProjection[15] = 0.0f
;

For an orthographic matrix:
matrixProjection[0] = 2.0f / (right - left);
matrixProjection[5] = 2.0f / (top - bottom);
matrixProjection[10] = -2.0f / (far - near);
matrixProjection[12] = -(right + left) / (right - left);
matrixProjection[13] = -(top + bottom) / (top - bottom);
matrixProjection[14] = -(far + near) / (far - near);

If you want even more options, read this

Comments