Design a site like this with WordPress.com
Get started

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.

Advertisement

Published by HorstBaerbel

Software developer by trade and interest, but I venture into the electronics- and diy-world from time to time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: