HLSL mul()变量澄清

dk1*_*123 6 c++ directx hlsl

HLSL的mul(x,y)的参数在这里表示:说

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

这是否遵循以下含义:

一个.

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

因为ID3DXBaseEffect :: SetMatrix()传入a row-major matrix,所以我会按照以下顺序使用传递到着色器的矩阵:

恩.Output.mPosition = mul( Input.mPosition, SetMatrix()value );

我刚开始使用着色器和当前重新学习矩阵数学.如果有人能澄清这一点会很好.

Nat*_*eed 16

不可以.术语"行主要"和"列主要"完全是指存储器中矩阵组件的存储顺序.它们与矩阵和向量的乘法顺序无关.实际上,D3D9 HLSL mul调用在所有情况下都将矩阵参数解释为列主要.该ID3DXBaseEffect::SetMatrix()调用将其矩阵参数解释为row-major,并将幕后转换为mul预期的列主要顺序.

如果你有一个抽象的矩阵:

[ a b c d ]
[ e f g h ]
[ i j k l ]
[ m n o p ]
Run Code Online (Sandbox Code Playgroud)

然后以行主要顺序存储时,其内存如下所示:

a b c d e f g h i j k l m n o p
Run Code Online (Sandbox Code Playgroud)

即一行的元素在内存中都是连续的.如果以列主要顺序存储,其内存将如下所示:

a e i m b f j n c g k o d h l p
Run Code Online (Sandbox Code Playgroud)

列的元素都是连续的.然而,这对哪个元素的影响恰好为零.b无论哪种方式,元素仍然在第一行和第二列.元素的标记没有改变,只是它们映射到内存的方式.

如果您float matrix[rows][cols]在C中声明一个数组,那么您正在使用行主存储.但是,其他一些语言(如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 ]
Run Code Online (Sandbox Code Playgroud)

如果你使用列向量,那么你将进行矩阵向量乘法:

[ 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 ]
Run Code Online (Sandbox Code Playgroud)

这是因为在行向量数学中,向量实际上是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也使用列主要顺序,但是(据我所知)并没有提供改变它的方法.

进一步阅读这些问题:


gar*_*eek 9

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

float4 transformed = mul(position, world);
Run Code Online (Sandbox Code Playgroud)

对于专栏:

float4 transformed = mul(world, position);
Run Code Online (Sandbox Code Playgroud)

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

实际上,hlsl并不关心你的矩阵是行还是列主要,你可以按正确的顺序应用向量乘法来得到正确的结果.

  • 这不太对。“行主要”(关于矩阵分量存储在内存中的顺序)和“行向量约定”(关于乘法的顺序)之间存在差异。在这两种情况下,这里的矩阵都以行主顺序*存储*。第一种情况使用行向量,第二种情况使用列向量(并且必须为每个矩阵适当地构建矩阵)。 (2认同)