Nein. Die Begriffe "Row-Major" und "Column-Major" beziehen sich rein auf die Reihenfolge Speicher der Matrix-Komponenten im Speicher. Sie haben nichts mit der Reihenfolge der Multiplikation von Matrizen und Vektoren zu tun. Tatsächlich interpretiert der Aufruf D3D9 HLSL mul
Matrixargumente in allen Fällen als Spaltenmajor. Der Aufruf ID3DXBaseEffect::SetMatrix()
interpretiert sein Matrixargument als Zeilenmajor und transponiert hinter die Kulissen mul
s erwartete Spaltenhauptordnung.
Wenn Sie eine Matrix, die abstrakt wie folgt aussieht:
[ a b c d ]
[ e f g h ]
[ i j k l ]
[ m n o p ]
dann, wenn sie in Reihe-Großauftrag gespeichert, sieht seinen Speicher wie folgt aus:
a b c d e f g h i j k l m n o p
dh die Elemente einer Reihe sind alle zusammenhängend im Speicher.Wenn in der Spalte-Großauftrag gespeichert, würde sein Gedächtnis wie folgt aussehen:
a e i m b f j n c g k o d h l p
mit den Elementen einer Spalte alle zusammenhängenden. Dies hat jedoch genau null Wirkung auf welches Element ist das. Element b
ist immer noch in der ersten Zeile und der zweiten Spalte. Die Beschriftung der Elemente hat sich nicht geändert, nur die Art, wie sie dem Speicher zugeordnet werden.
Wenn Sie in C ein Array wie float matrix[rows][cols]
deklarieren, verwenden Sie den Hauptspeicher für Zeilen. Einige andere Sprachen, wie FORTRAN, verwenden jedoch standardmäßig Spaltenspeicher für ihre mehrdimensionalen Arrays. und OpenGL verwendet auch Spalten-Hauptspeicher.
Nun, ganz getrennt, gibt es eine andere Wahl der Konvention, die ist, ob Zeile-Vektor oder Spalten-Vektor-Mathematik zu verwenden. Dies hat überhaupt nichts mit dem Speicherlayout von Matrizen zu tun, aber es beeinflusst, wie Sie Ihre Matrizen erstellen, und die Reihenfolge der Multiplikation. Wenn Sie Zeilenvektoren verwenden, werden Sie Vektor-Matrix-Multiplikation tun:
[ 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 ]
und wenn Sie Spaltenvektoren verwenden, dann werden Sie Matrix-Vektor-Multiplikation tun:
[ 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 ]
Dies liegt daran, in Zeilenvektormathematik, ein Vektor ist wirklich eine 1 × n-Matrix (eine einzelne Zeile), und in Spaltenvektormathematik ist es eine n × 1-Matrix (eine einzelne Spalte) und die Regel darüber, welche Größen von Matrizen zulässig sind multipliziert zusammen bestimmt die Reihenfolge. (Sie können eine 4 × 4-Matrix nicht mit einer 1 × 4-Matrix multiplizieren, aber Sie können eine 4 × 4-Matrix mit einer 4 × 1-Matrix multiplizieren.)
Beachten Sie, dass sich die Matrix zwischen den beiden nicht geändert hat obige Gleichungen; nur die Interpretation des Vektors änderte sich.
Also, um auf Ihre ursprüngliche Frage zurück:
Wenn Sie einen Vektor zu HLSL Pass mul
, interpretiert er automatisch „richtig“ nach dem Argument ist. Wenn der Vektor auf der rechten Seite ist, ist es ein Zeilenvektor, und wenn es auf der linken Seite ist, ist es ein Spaltenvektor.
Die Matrix wird jedoch auf die gleiche Weise immer interpretiert. Eine Matrix ist eine Matrix, unabhängig davon, ob sie mit einem Zeilenvektor auf der linken oder einem Spaltenvektor auf der rechten Seite multipliziert wird. Sie können frei entscheiden, ob Sie in Ihrem Code Zeilenvektor- oder Spaltenvektormathematik verwenden möchten, solange Sie darüber konsistent sind. HLSL ist in diesem Punkt agnostisch, obwohl die D3DX-Mathematikbibliothek Zeilenvektoren verwendet.
Und es stellt sich heraus, dass in D3D9 HLSL, mul
immer erwartet, dass Matrizen in der Spalte-Major-Reihenfolge gespeichert werden. Die D3DX-Mathebibliothek speichert jedoch Matrizen in Reihen-Haupt-Reihenfolge, und wie die Dokumentation sagt, erwartet ID3DXBaseEffect::SetMatrix()
seine Eingabe in Reihe-Haupt-Reihenfolge. Es wird hinter die Kulissen transponiert, um die Matrix für die Verwendung mit mul
vorzubereiten.
BTW, D3D11 HLSL verwendet standardmäßig die Reihenfolge der Spalten, erlaubt Ihnen jedoch, eine Compiler-Anweisung zu verwenden, um stattdessen die Reihenreihenfolge anzugeben. Es ist immer noch agnostisch hinsichtlich der Zeilenvektor- gegenüber der Spaltenvektormathematik. Und OpenGL GLSL verwendet auch die Spalten-Major-Reihenfolge, bietet aber (soweit ich weiß) keine Möglichkeit, diese zu ändern.
Weitere zu diesen Themen lesen:
+1 Danke, ich denke, es dann alles über die Bestellung ist. Großartige Antwort Layout! – dk123
Das ist nicht ganz richtig. Es gibt einen Unterschied zwischen "row-major" (was bedeutet, dass die Ordnungsmatrix-Komponenten im Speicher gespeichert sind) und "row vector convention" (was ungefähr der Reihenfolge der Multiplikation entspricht). Die Matrix wird in beiden Fällen in Zeilenreihenfolge * gespeichert. Der erste Fall ist ein Zeilenvektor und der zweite Fall ein Spaltenvektor (und die Matrix müsste für jeden passend aufgebaut sein). –