9

HLSL 的 mul(x, y) 的参数在这里指出:说

  • 如果 x 是向量,则将其视为行向量。
  • 如果 y 是向量,则将其视为列向量。

那么这是否意味着:

一个。

  • 如果 x 是向量,则 y 被视为row-major matrix
  • 如果 y 是向量,则 x 被视为column-major matrix

湾。

由于 ID3DXBaseEffect::SetMatrix() 传入 a row-major matrix,因此我将按以下顺序使用传入着色器的矩阵:

前任。Output.mPosition = mul( Input.mPosition, SetMatrix()value );?

我刚开始使用着色器,目前正在重新学习我的矩阵数学。如果有人能澄清这一点,那就太好了。

4

2 回答 2

21

不。术语“行优先”和“列优先”纯粹是指矩阵组件在内存中的存储顺序。它们与矩阵和向量的乘法顺序无关。事实上,D3D9 HLSLmul调用在所有情况下都将矩阵参数解释为列优先。该ID3DXBaseEffect::SetMatrix()调用将其矩阵参数解释为行优先,并在幕后转置为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 矩阵相乘。)

请注意,上述两个等式之间的矩阵没有变化;只有向量的解释发生了变化。

所以,回到你原来的问题:

当您将向量传递给 HLSLmul时,它会根据它的参数自动“正确”解释它。如果向量在左侧,则为行向量,如果在右侧,则为列向量。

但是,矩阵总是以相同的方式被解释。矩阵是一个矩阵,无论它是与左侧的行向量还是右侧的列向量相乘。您可以自由决定在代码中使用行向量还是列向量数学,只要您对此保持一致即可。HLSL 在这一点上是不可知的,尽管 D3DX 数学库使用行向量。

事实证明,出于某种原因,在 D3D9 HLSL 中,mul总是期望矩阵以列优先顺序存储。但是,D3DX 数学库以行优先顺序存储矩阵,并且正如文档所述,ID3DXBaseEffect::SetMatrix()期望其输入以行优先顺序。它在幕后进行转置以准备矩阵以用于mul.

顺便说一句,D3D11 HLSL 默认为列优先顺序,但允许您使用编译器指令来告诉它使用行优先顺序。对于行向量与列向量数学,它仍然是不可知的。并且 OpenGL GLSL 也使用列优先顺序,但没有(据我所知)提供改变它的方法。

关于这些问题的进一步阅读:

于 2013-12-07T07:06:57.240 回答
7

是的,如果 x 是向量,则 x 被视为行主向量,y 被视为行主矩阵;反之亦然,对于列优先,因此对于行优先矩阵系统:

float4 transformed = mul(position, world);

对于列专业:

float4 transformed = mul(world, position);

由于矩阵乘法的工作方式,如果矩阵是列优先的,那么您必须乘以列向量才能获得正确的结果。如果矩阵是行优先的,则必须预先乘以行向量。

所以真的, hlsl 不在乎你的矩阵是行还是列主要,这取决于你以正确的顺序应用向量乘法以获得正确的结果。

于 2013-05-16T09:58:21.407 回答