built-in matrices _Object2World, UNITY_MATRIX_MVP... row major or column major?

it confuses me that how the built-in 4x4 matrices like _Object2World or UNITY_MATRIX_MVP are structured and where they should be put in the mul() function.

in cases like

o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
float3 viewDirection = normalize( float3( float4( _WorldSpaceCameraPos, 1.0) - mul(_Object2World, v.vertex) ) );

the UNITY_MATRIX_MVP and the _Object2World matrices are the first argument in the mul() function.

so it seems that the UNITY_MATRIX_MVP and the _Object2World should be row major (?) according to the definition of the mul() function in the cg reference and that’s all I can guess.

And, the the second argument which is v.vertex should be a 4x1 vector, so is a float4 here automatically treated as a 4x1 but not a 1x4 vector?

in the following case

float3 normalDirection = normalize( mul( float4(v.normal, 0.0), _World2Object ).xyz );

the _World2Object is used as the second argument

so how does 4x4 matrices _World2Object, UNITY_MATRIX_MVP and the other built-in matrices actually look like internally, are they row major? like:

X1,X2,X3,X4

Y1,Y2,Y3,Y4

Z1,Z2,Z3,Z4

W1,W2,W3,W4

or column major? like:

X1,Y1,Z1,W1

X2,Y2,Z2,W2

X3,Y3,Z3,W3

X4,Y4,Z4,W4.

How can i tell where these built-in matrices should be put in the mul() function?

Many Thanks~~

when using matrix in c# . it is column-major.

I test code in vertex shader like that…

struct appdata
{
    	float4 vertex : POSITION;
};

struct v2f
{
    	float4 vertex : SV_POSITION;
};

v2f vert_colume_major(appdata v)
{
        v2f o;
        o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
        return o;
}

v2f vert_row_major(appdata v)
{
    	v2f o;
        float4x4 TMatrix = transpose(UNITY_MATRIX_MVP);
    	o.vertex = mul(v.vertex, TMatrix);
    	return o;
}

the result is no different. So I guess you are right .
cg transpose “v.vertex” automatically.

I think when using builtin unity shader matrix and mul() calculator, the matrix is a column one. So actually the vector on the right is being converted to a one-column column vector under the hood.