## GLSL 4×4 Matrix Fields

Here is a short article about manipulating **GLSL** mat4 fields. In C, an OpenGL 4×4 matrix is a 16-float array:

float c_matrix[16];

In GLSL the same matrix is:

mat4 glsl_matrix;

Let’s see how to map the C matrix to the GLSL one and vice-versa. Matrices in OpenGL are column-major. The c_matrix[] can be represented by:

The first column is made up of entries 0, 1, 2 and 3. The second column is 4, 5, 6, 7 and so on.

In C, the first entry of the first column is:

c_matrix[0];

While the second entry of the third column is:

c_matrix[9];

Now in GLSL. The first entry of the first column is:

glsl_matrix[0][0];

The second entry of the third column is:

glsl_matrix[2][1];

A mat4 can be seen as four vec4 vectors:

vec4 c0 = glsl_matrix[0].xyzw; vec4 c1 = glsl_matrix[1].xyzw; vec4 c2 = glsl_matrix[2].xyzw; vec4 c3 = glsl_matrix[3].xyzw;

The first entry of the first column is now:

glsl_matrix[0].x;

And the second entry of the third column is:

glsl_matrix[2].y;

In the case of an object transformation matrix, the 4×4 matrix usually contains the orientation and the position of the object. The orientation is stored in the upper 3×3 matrix, or in terms of a mat4, in the three first entries of the three first columns. The position is stored in the three first entries of the fourth and last column.

Here is now a GLSL code snippet that build a 4×4 transformation matrix from a 3D position and the three Euler’s angles:

mat4 build_transform(vec3 pos, vec3 ang) { float cosX = cos(ang.x); float sinX = sin(ang.x); float cosY = cos(ang.y); float sinY = sin(ang.y); float cosZ = cos(ang.z); float sinZ = sin(ang.z); mat4 m; float m00 = cosY * cosZ + sinX * sinY * sinZ; float m01 = cosY * sinZ - sinX * sinY * cosZ; float m02 = cosX * sinY; float m03 = 0.0; float m04 = -cosX * sinZ; float m05 = cosX * cosZ; float m06 = sinX; float m07 = 0.0; float m08 = sinX * cosY * sinZ - sinY * cosZ; float m09 = -sinY * sinZ - sinX * cosY * cosZ; float m10 = cosX * cosY; float m11 = 0.0; float m12 = pos.x; float m13 = pos.y; float m14 = pos.z; float m15 = 1.0; /* //------ Orientation --------------------------------- m[0] = vec4(m00, m01, m02, m03); // first column. m[1] = vec4(m04, m05, m06, m07); // second column. m[2] = vec4(m08, m09, m10, m11); // third column. //------ Position ------------------------------------ m[3] = vec4(m12, m13, m14, m15); // fourth column. */ //------ Orientation --------------------------------- m[0][0] = m00; // first entry of the first column. m[0][1] = m01; // second entry of the first column. m[0][2] = m02; m[0][3] = m03; m[1][0] = m04; // first entry of the second column. m[1][1] = m05; // second entry of the second column. m[1][2] = m06; m[1][3] = m07; m[2][0] = m08; // first entry of the third column. m[2][1] = m09; // second entry of the third column. m[2][2] = m10; m[2][3] = m11; //------ Position ------------------------------------ m[3][0] = m12; // first entry of the fourth column. m[3][1] = m13; // second entry of the fourth column. m[3][2] = m14; m[3][3] = m15; return m; }

**Remark:** manipulating mat4 fields can be dangerous. For example this code does not generate errors nor warnings (at least with my GTX 660 on Windows) but does not work at all:

//------ Position ------------------------------------ m[3][0] = m12; // first entry of the fourth column. m[3][1] = m13; // second entry of the fourth column. m[3][4] = m14; // ERROR! m[3][3] = m15;

In the third line, we set m14 to an out of range memory location. Such kind of bugs can be hard to detect…

If you wish to quick test mat4 fields, I prepared a little GLSL Hacker demo you can find in the code sample pack (host_api/GLSL_Misc/mat4_transform/demo.xml).

**Some references**

I will have to double check but I believe your memory layout ordering is wrong.

OpenGL is column major, but is laid out in memory in column order.

Eg. vec4 columns[4]; // First column is the first 4 memory slots

A little known fact is that the memory layout of OpenGL matrices is the same as DirectX!

(eg glTranslatef and D3DXMatrixTranslation should return the same in memory results)

http://www.mindcontrol.org/~hplus/graphics/matrix-layout.html

openGL is actually row major. People are confused by it because when they are looking at the modelview matrix they are looking at model * view and don’t consider that view is a transposed matrix.

Strictly model matrices (ie what you would pass to glMultMatrix) are row major. The first 4 values are the right vector. The next 4 the up vector, the next 4 the forward vector and the last 4 translation.

This whole row-major vs column-major thing is really confusing because it depends how you look at your matrices; some books place the homogeneous components in the last column and use pre-multiplication in order to transform vectors, while other books place the homogeneous components in the last row of the matrix and use post-multiplication. Depending on how you are accustomed to writing your matrices, you may think that memory layout in OpenGL is row-major or column-major. The easiest way to avoid confusion is to drop the whole “row- column-major” thing and just remember that OpenGL places the translation components of matrices at the 13th, 14th, and 15th elements of a 16-element array. And as Damian Trebilco pointed out, both Direct3D and OpenGL use the same matrix layout.