来自gameres.com论坛wjk98550328发表
Re:关于变换矩阵的行列性
行列都没所谓的,只要你应用层知道每行是什么意义,每列是什么意义,如果矩阵是行有意义,那就Matrix×Vector,vector理解为列向量,如果是列有意义的矩阵,那就Vector×Matrix,那个被变换的矩阵理解为行向量。仅此而已,在数学上不是还有矩阵转置,行列在数学上不就是一堆数据么,没有应用,行列就没多大意义。。。
既然要讨论这个问题,我们就来仔细看看,
1:看dx原话
Effect matrix parameters and HLSL matrix variables can define whether the value is a row-major
or column-major matrix;
Matrix packing order for uniform parameters is set to column-major by default.
This means each column of the matrix is stored in a single constant register.
however, the DirectX APIs always treat D3DMATRIX and D3DXMATRIX as row-major.
很显然,dx api使用行矩阵,dx hlsl或fx使用列矩阵。
所以,我们随便看个dx sample里头hlsl文件中,
对于变换是这么写的:
Output.Position = mul(vAnimatedPos, g_mWorldViewProjection);
没错,是行向量×列矩阵;
然而你看cpp代码
s_pD3D9Effect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProj )
直接设置了一个行矩阵,这后面是d3dx9.dll帮你把行矩阵,抽出一行一行,设置进寄存器,也就转成了列矩阵。
2:突变
Matrix packing order for uniform parameters is set to column-major by default.
This means each column of the matrix is stored in a single constant register
.
--dx sdk原文,很明白,默认你的app矩阵的一列将占用一个寄存器,但有个前提条件,就是你使用ID3DXConstantTable:: SetMatrix或者这个ID3DXBaseEffect::SetMatrix接口进行矩阵设置,这个row major和column major只影响sdk提供的setmatrix接口提供参数的解析形式。如果你使用IDirect3DDevice9:: SetVertexShaderConstantF进行矩阵设置,结果就是上面英文写的对此完全没有影响。理解了不?
也就是你在cpp进行矩阵运算是完全使用列矩阵(dx默认是行矩阵),那么你设置shader矩阵参数时就不能用ID3DXBaseEffect::SetMatrix,而是用IDirect3DDevice9:: SetVertexShaderConstantF,进行一列一列的设置。
再说明白点,在shader代码中,完全没有行矩阵,列矩阵区分,在shader代码中matrix只是个n×m的数据块,对于矩阵的行列区分完全自动转换,看这个
mul (DirectX HLSL)
Multiplies x and y using matrix math. The inner dimension x-columns and
y-rows must be equal.
ret mul(x, y)
Parameters
x
[in] The x input value. If x is a vector, it treated as a row vector.
y
[in] The y input value. If y is a vector, it treated as a column vector.
也就是说,在shader中矩阵就是看到float4x3的矩阵,你并不能确定它占几个常量寄存器,也许是3个,也许是4个,但它一定是4行3列,根据线性代数原则,可以左乘一个3×n的向量,这时矩阵就是行矩阵,如果它右乘一个n×4的向量,则矩阵自动理解为列矩阵,这个n×4的向量时行向量。
应该讲清楚了。