いいえ。「行優先」と「列優先」という用語は、純粋にメモリ内の行列コンポーネントの格納順序を指します。行列とベクトルの乗算の順序とは関係ありません。実際、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
列の要素がすべて連続しています。ただし、これはどの要素が which であるかにまったく影響しません。どちらの方法でも、要素b
はまだ最初の行と 2 番目の列にあります。要素のラベル付けは変更されておらず、メモリへのマッピング方法のみが変更されています。
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 行列を掛けることはできます。)
上記の 2 つの方程式の間で行列が変化していないことに注意してください。ベクトルの解釈のみが変更されました。
したがって、元の質問に戻るには:
ベクトルを HLSL の に渡すと、mul
引数に応じて「正しく」自動的に解釈されます。ベクトルが左側にある場合は行ベクトルであり、右側にある場合は列ベクトルです。
ただし、行列は常に同じように解釈されます。行列は、左側の行ベクトルまたは右側の列ベクトルで乗算されているかどうかに関係なく、行列です。一貫性がある限り、コードで行ベクトル演算と列ベクトル演算のどちらを使用するかを自由に決定できます。D3DX 数学ライブラリは行ベクトルを使用しますが、HLSL はこの点にとらわれません。
mul
そして、なんらかの理由で、D3D9 HLSL では行列が常に列優先順で格納されることを期待していることが判明しました。ただし、D3DX 数学ライブラリは行列を行優先順で格納し、ドキュメントに記載されているように、ID3DXBaseEffect::SetMatrix()
その入力は行優先順であると想定しています。で使用する行列を準備するために、舞台裏で転置を行いmul
ます。
ところで、D3D11 HLSL はデフォルトで列優先順ですが、コンパイラ ディレクティブを使用して、代わりに行優先順を使用するように指示できます。行ベクトル対列ベクトルの計算に関しては、まだ不可知論的です。また、OpenGL GLSL も列優先順序を使用しますが、(私の知る限り)それを変更する方法は提供していません。
これらの問題に関する詳細情報: