HLSL的mul(x,y)参数表示here:说明
这是否遵循以下含义:
一个。
row-major matrix
column-major matrix
湾
因为ID3DXBaseEffect :: SetMatrix()传入row-major matrix
,因此我按照以下顺序使用传递到着色器的矩阵:
离。 Output.mPosition = mul( Input.mPosition, SetMatrix()value );
?
我刚开始使用着色器和当前重新学习我的矩阵数学。如果有人能澄清这一点会很好。
答案 0 :(得分:15)
没有。术语“行主要”和“列主要”纯粹指的是存储器中矩阵组件的存储的顺序。它们与矩阵和向量的乘法顺序无关。实际上,D3D9 HLSL mul
调用在所有情况下都将矩阵参数解释为列主要。 ID3DXBaseEffect::SetMatrix()
调用将其矩阵参数解释为row-major,并在后台转换为mul
预期的列主要顺序。
如果你有一个抽象的矩阵:
[ a b c d ]
[ e f g h ]
[ i j k l ]
[ m n o p ]
然后以行主要顺序存储时,其内存如下所示:
a b c d e f g h i j k l m n o p
即。行的元素在内存中都是连续的。如果按列主要顺序存储,其内存将如下所示:
a e i m b f j n c g k o d h l p
列的元素都是连续的。但是,这对哪个元素的影响正好为零。无论哪种方式,元素b
仍然在第一行和第二列。元素的标记没有改变,只是它们被映射到内存的方式。
如果在C中声明类似float matrix[rows][cols]
的数组,那么您正在使用行主存储。但是,其他一些语言(如FORTRAN)默认使用列主存储作为其多维数组; OpenGL也使用列主存储。
现在,完全单独地,有另一个约定选择,即是使用行向量还是列向量数学。这与矩阵的内存布局没有任何关系,但它会影响你构建矩阵的方式以及乘法的顺序。如果你使用行向量,你将进行向量矩阵乘法:
[ a b c d ]
[x y z w] * [ e f g h ] = [x*a + y*e + z*i + w*m, ... ]
[ i j k l ]
[ m n o p ]
如果你使用列向量,那么你将进行矩阵向量乘法:
[ a b c d ] [ x ]
[ e f g h ] * [ y ] = [x*a + y*b + z*c + w*d, ... ]
[ i j k l ] [ z ]
[ m n o p ] [ w ]
这是因为在行向量数学中,向量实际上是1×n矩阵(单行),而在列向量数学中它是n×1矩阵(单列),以及关于什么的规则允许矩阵的大小相乘以确定顺序。 (你不能将4×4矩阵乘以1×4矩阵,但你可以将4×4矩阵乘以4×1矩阵。)
注意,矩阵在上述两个方程之间没有变化;只有对矢量的解释发生了变化。
所以,回到原来的问题:
当你将一个向量传递给HLSL的mul
时,它会根据它的参数自动“正确地”解释它。如果向量在右边,它是一个行向量,如果它在左边,它就是一个列向量。
然而,矩阵总是以相同的方式解释。矩阵是一个矩阵,无论它是左侧的行向量还是右侧的列向量。您可以自由决定是否在代码中使用行向量或列向量数学,只要您对它保持一致即可。虽然D3DX数学库使用行向量,但HLSL在这一点上是不可知的。
事实证明,由于某些原因,在D3D9 HLSL中,mul
总是希望矩阵以列主顺序存储。但是,D3DX数学库以行主顺序存储矩阵,正如文档所述,ID3DXBaseEffect::SetMatrix()
期望其输入按主行顺序排列。它在幕后进行转置,以准备与mul
一起使用的矩阵。
BTW,D3D11 HLSL默认为列主要顺序,但允许您使用编译器指令来告诉它使用行主顺序。对于行向量与列向量数学,它仍然是不可知的。 OpenGL GLSL也使用列主要顺序,但是(据我所知)没有提供改变它的方法。
进一步阅读这些问题:
答案 1 :(得分:8)
是的,如果x是向量,则x被视为行主向量,y被视为行主矩阵;对于行主要矩阵系统,反之亦然:
float4 transformed = mul(position, world);
和专栏:
float4 transformed = mul(world, position);
由于矩阵乘法的工作方式,如果矩阵是列主要的,那么您必须乘以列向量以获得正确的结果。如果矩阵是行主要的,则必须预先乘以行向量。
实际上,hlsl并不关心你的矩阵是行还是列主要,你可以按正确的顺序应用向量乘法来得到正确的结果。