Alright to to summarize,
Row major order:-
Vector is always on the left side of the multiplication with a matrix.
P = vM
Translation vector is always on the 12, 13 and 14th element.
Column major order:-
Vector is always on the right side of the multiplication with a matrix.
P = Mv
Translation vector is always on the 3, 7 and 11th element.
First up, I personally try to avoid using the terms row-major and column-major with matrices, because they mean different things to mathematicians and computer science people...
Maths people think that you're talking about whether you've got a matrix that's made up of basis vectors that are row-vectors / column-vectors, and comp-sci people think you're talking about the 2D->1D array indexing scheme. These are two very different things
Above, you're talking about the mathematical concept of "row matrices" vs "column matrices", and the comp-sci concept or array indexing is irrelevant.
So the only difference between HLSL and GLSL is how they layout this data in memory.
HLSL reads the matrix row by row. GLSL reads the matrix column by column.
So this is how HLSL layout the data in memory0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15And this is how GLSL layout the data in memory.0 4 8 12 1 5 9 13 2 6 10 14 3 7 11 15Alright. This makes sense. Now I have to understand how I should layout the matrix in C++ and send it to HLSL and GLSL correctly.
Man..... Why couldn't OpenGL just read things row by row...... WHY !!
By default, both HLSL and GLSL do actually use column-major array indexing! So if you're sending matrices from the C++ side, the individual floats should be stored in column order.
i.e. the storage order in RAM is:
0 4 8 12 1 5 9 13 2 6 10 14 3 7 11 15
Despite column-major being the default element storage order, HLSL for some reason chose to make their constructors interpret the arguments in row-major storage order... I always thought this mismatch was odd, but your example shows that it makes more visual sense, as the code appears in rows on the screen after all!
In HLSL, you can explicitly choose the (comp-sci) array indexing scheme / element storage order of a matrix with:
row_major float4x4 foo;
column_major float4x4 bar;
And GLSL similarly with:
layout(row_major) mat4 foo;
layout(column_major) mat4 bar;
And just to reiterate: your choice of row_major or column_major array storage order has absolutely no impact on the multiplication order that you should use / no impact on whether your data is mathematically row-major or column-major (as in, whether the layout of your basis vectors is going across or down)
You see a lot of posts on the internet where people are doing maths one way in D3D and maths another way in GL (opposite multiplication orders), or posts where people say "D3D is row-major, GL is column-major" -- nope, old crud.
Both D3D and GL use column-major storage ordering by default (but can be overridden), and neither forces a particular mathematical convention on you (column-vectors and row-vectors are equally supported).