Ich bin gründlich verwirrt über Matrixdefinitionen. Ich habe eine Matrixklasse, die eine enthält, von float[16]
der ich angenommen habe, dass sie Zeilenmajor ist, basierend auf den folgenden Beobachtungen:
float matrixA[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
float matrixB[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };
matrixA
und matrixB
beide haben das gleiche lineare Layout im Speicher (dh alle Zahlen sind in Ordnung). Laut http://en.wikipedia.org/wiki/Row-major_order weist dies auf ein Zeilen-Haupt-Layout hin.
matrixA[0] == matrixB[0][0];
matrixA[3] == matrixB[0][3];
matrixA[4] == matrixB[1][0];
matrixA[7] == matrixB[1][3];
Daher matrixB[0]
= Zeile 0, matrixB[1]
= Zeile 1 usw. Dies zeigt wiederum das Zeilen-Haupt-Layout an.
Mein Problem / meine Verwirrung entsteht, wenn ich eine Übersetzungsmatrix erstelle, die wie folgt aussieht:
1, 0, 0, transX
0, 1, 0, transY
0, 0, 1, transZ
0, 0, 0, 1
Welches in Erinnerung geblieben ist als , { 1, 0, 0, transX, 0, 1, 0, transY, 0, 0, 1, transZ, 0, 0, 0, 1 }
.
Wenn ich dann glUniformMatrix4fv aufrufe , muss ich das Transponierungsflag auf GL_FALSE setzen, um anzuzeigen, dass es spaltenmäßig ist. Andernfalls werden Transformationen wie translate / scale usw. nicht richtig angewendet:
Wenn die Transponierte GL_FALSE ist, wird angenommen, dass jede Matrix in der Hauptreihenfolge der Spalte geliefert wird. Wenn die Transponierte GL_TRUE ist, wird angenommen, dass jede Matrix in der Hauptreihenfolge der Zeile geliefert wird.
Warum muss meine Matrix, die Zeilenmajor zu sein scheint, als Spaltenmajor an OpenGL übergeben werden?
GL_FALSE
"? Wie benutzt du die Uniform?Antworten:
Die in der OpenGL-Dokumentation verwendete Matrixnotation beschreibt nicht das speicherinterne Layout für OpenGL-Matrizen
Wenn Sie denken, dass es einfacher ist, wenn Sie das gesamte "Zeilen- / Spalten-Haupt" -Ding löschen / vergessen. Dies liegt daran, dass der Programmierer neben Zeilen- / Spaltenmajor auch entscheiden kann, wie er die Matrix im Speicher anordnen möchte (ob benachbarte Elemente Zeilen oder Spalten bilden), zusätzlich zur Notation, was zu Verwirrung führt.
OpenGL-Matrizen haben das gleiche Speicherlayout wie DirectX-Matrizen .
x.x x.y x.z 0 y.x y.y y.z 0 z.x z.y z.z 0 p.x p.y p.z 1
oder
{ x.x x.y x.z 0 y.x y.y y.z 0 z.x z.y z.z 0 p.x p.y p.z 1 }
x, y, z sind 3-Komponenten-Vektoren, die das Matrixkoordinatensystem beschreiben (lokales Koordinatensystem innerhalb relativ zum globalen Koordinatensystem).
p ist ein 3-Komponenten-Vektor, der den Ursprung des Matrixkoordinatensystems beschreibt.
Das bedeutet, dass die Übersetzungsmatrix wie folgt im Speicher angelegt werden sollte:
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }.
Lassen Sie es dabei, und der Rest sollte einfach sein.
--- Zitat aus alten opengl faq--
quelle
Um die Antworten von SigTerm und dsharlet zusammenzufassen: Die übliche Methode zum Transformieren eines Vektors in GLSL besteht darin, den Vektor mit der Transformationsmatrix nach links zu multiplizieren:
Damit dies funktioniert, erwartet OpenGL, dass das
T
von SigTerm beschriebene Speicherlayout wie folgt lautet:{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }
was auch als "Column Major" bezeichnet wird. In Ihrem Shader-Code (wie in Ihren Kommentaren angegeben) haben Sie den Vektor jedoch mit der Transformationsmatrix rechts multipliziert:
was nur dann das richtige Ergebnis liefert, wenn
T
es transponiert wird, dh das Layout hat{ 1, 0, 0, transX, 0, 1, 0, transY, 0, 0, 1, transZ, 0, 0, 0, 1 }
(dh "Row Major"). Da Sie Ihrem Shader bereits das richtige Layout zur Verfügung gestellt haben, nämlich Row Major, war es nicht erforderlich, das
transpose
Flag von zu setzenglUniform4v
.quelle
Sie haben es mit zwei getrennten Problemen zu tun.
Zunächst befassen sich Ihre Beispiele mit dem Speicherlayout. Ihr [4] [4] -Array ist Zeilenmajor, da Sie die von C-mehrdimensionalen Arrays festgelegte Konvention verwendet haben, um mit Ihrem linearen Array übereinzustimmen.
Die zweite Ausgabe ist eine Frage der Konvention, wie Sie Matrizen in Ihrem Programm interpretieren. Mit glUniformMatrix4fv wird ein Shader-Parameter festgelegt. Ob Ihre Transformation für einen Zeilenvektor oder eine Spaltenvektortransformation berechnet wird , hängt davon ab, wie Sie die Matrix in Ihrem Shader-Code verwenden. Da Sie sagen, dass Sie Spaltenvektoren verwenden müssen, gehe ich davon aus, dass Ihr Shader-Code die Matrix A und einen Spaltenvektor x verwendet , um x ' = A x zu berechnen .
Ich würde argumentieren, dass die Dokumentation von glUniformMatrix verwirrend ist. Die Beschreibung des Transponierungsparameters ist ein Umweg, um nur zu sagen, dass die Matrix transponiert ist oder nicht. OpenGL selbst transportiert diese Daten nur zu Ihrem Shader. Ob Sie sie transponieren möchten oder nicht, ist eine Konventionssache, die Sie für Ihr Programm festlegen sollten.
Dieser Link hat einige gute weitere Diskussion: http://steve.hollasch.net/cgindex/math/matrix/column-vec.html
quelle
gl_Position = vec4(v_xy, 0.0, 1.0) * v_ViewMatrix * v_ProjectionMatrix;
vector x model x view x projection;
tunprojection x view x model x vector;
?