C++ HLSL mul()变量说明

C++ HLSL mul()变量说明,c++,directx,hlsl,C++,Directx,Hlsl,HLSL的mul(x,y)参数表明:假设 如果x是一个向量,则将其视为行向量 如果y是一个向量,它将被视为一个列向量 这是否意味着: a 如果x是向量,则y被视为行主矩阵 如果y是向量,则x被视为列主矩阵 b 由于ID3DXBaseEffect::SetMatrix()以a的形式传递,因此我将按以下顺序使用传递到着色器中的矩阵: 例如,Output.mPosition=mul(Input.mPosition,SetMatrix()值) 我刚开始使用着色器,现在正在重新学习矩阵数学。如果有

HLSL的mul(x,y)参数表明:假设

  • 如果x是一个向量,则将其视为行向量
  • 如果y是一个向量,它将被视为一个列向量
这是否意味着:

a

  • 如果x是向量,则y被视为
    行主矩阵
  • 如果y是向量,则x被视为
    列主矩阵
b

由于ID3DXBaseEffect::SetMatrix()以a的形式传递,因此我将按以下顺序使用传递到着色器中的矩阵:

例如,
Output.mPosition=mul(Input.mPosition,SetMatrix()值)


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

是的,如果x是向量,那么x被视为行主向量,y被视为行主矩阵;反之亦然,对于列主矩阵系统,行主矩阵系统:

float4 transformed = mul(position, world);
至于专业栏目:

float4 transformed = mul(world, position);
由于矩阵乘法的工作方式,如果矩阵是列主矩阵,则必须用列向量进行后置乘法以获得正确的结果。如果矩阵是行主矩阵,则必须预先乘以行向量

因此,实际上,hlsl并不关心矩阵是行主矩阵还是列主矩阵,而是由您按照正确的顺序应用向量乘法来获得正确的结果。

否。术语“行主矩阵”和“列主矩阵”纯粹指矩阵组件在内存中的存储顺序。它们与矩阵和向量的乘法顺序无关。事实上,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
然后按行主顺序存储时,其内存如下所示:

[ 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
i、 行的元素在内存中都是连续的。如果以列主顺序存储,其内存将如下所示:

[ 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 ]
如果使用列向量,则将执行矩阵向量乘法:

            [ 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
时,它会根据它是哪个参数自动“正确”地解释它。如果向量在左边,它是行向量,如果它在右边,它是列向量

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

结果表明,出于某种原因,在D3D9 HLSL中,
mul
总是希望矩阵以列主顺序存储。但是,D3DX数学库以行主顺序存储矩阵,并且正如文档所述,
ID3DXBaseEffect::SetMatrix()
希望其输入以行主顺序进行。它在幕后进行转置,以准备矩阵与
mul
一起使用

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

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

  • 加泰林·齐马
  • 费边·吉森

+1谢谢,我想这都是订购的问题了。伟大的答复布局!这不太正确。“row major”(关于存储在内存中的矩阵组件的顺序)和“row vector convention”(关于乘法的顺序)之间有区别。在这两种情况下,矩阵都按行的主要顺序存储。第一种情况是使用行向量,第二种情况是使用列向量(并且必须为每个行向量适当地构建矩阵)。OpenGL允许您使用
布局
限定符指定每个统一的行/列主要顺序。它通常不太有用,因为glapi已经允许您在发送矩阵统一时转置它们,但是它对于统一缓冲区很有用。不幸的是,它只适用于制服。例如,一个
mat4
构造函数总是使用它的com