OpenGL matrices are column-major by default.
You can make them row-major in GLSL with a layout qualifier (e.g. layout (row_major) uniform mat4 u_mvMatrix;
). Note that pre-multiplication of a row-major matrix is the same as post-multiplication of a column-major matrix, so this is a true statement:
(mat * vec) == (vec * transpose (mat))
In the fixed-function pipeline when OpenGL does a matrix multiply, it is always column-major and post-multiplied. Direct3D is row-major and pre-multiplied. In the programmable pipeline you have full control over the matrix notation and whether you pre- or post-multiply.
Getting back to your question, in this example you are post-multiplying (the matrix is on the l-hand side of the *
operator) a column-major matrix. The correct equivalence is therefore vec3 normal = u_mvMatrix [2].xyz;
For a lengthy article that does a decent job explaining what I just wrote, see this site.