Seite 1 von 1
Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 14.10.2009, 10:24
von Marserdling
Hallo,
ich versuche schon seit einiger Zeit aus den ganzen Quellen im Internet schlau zu werden, aber komme auf keinen grünen Zweig weil scheinbar jeder andere Definitionen verwendet. Deshalb versuche ich mich an eine Quelle zu wenden um endlich einheitliche Informationen zu bekommen..
Also ein paar Fragen die die Verwirrung begründen:
Was ist der Unterschied zwischen "row-major" und "row-order"?
Fallen Vektoren auch in das Schema row-major / column major?
Im folgenden ein paar Absätze um genauer zu zeigen wo es hakt und was ich schon weiß:
OpenGL und DirectX haben beide bereits eingebaute Matrixtransformationen, in der DirectX Hilfe steht, dass D3DXMatrixMultiply
zwei Matrizen derart multipliziert, dass der Operator hintenangestellt ist...also "post multiply" mit "row major" Matrizen.
OpenGL macht anscheinend "pre multiply" und zwar mit "column major" Matrizen, wie hier beschrieben
http://www.gamedev.net/community/forums ... _id=541613
OpenGL FAQ:
Column-major versus row-major is purely a notational convention. Note that post-multiplying with column-major matrices produces the same result as pre-multiplying with row-major matrices.
1,Also sehen Matrizen und Vektoren im Speicher immer gleich aus, richtig? Das macht aber keinen Sinn, denn wenn ich eine Matrix Element für Element runterschreibe, kommt eine andere Reihenfolge heraus wenn ich das per Zeile mache wie per Spalte.
Bsp:
( 1 2)
( 3 4)
Zeilenweise: 1234 Spaltenweise: 1324
2, Heißt das, damit ich in OpenGL dieselbe Transformation bekomme wie in DirectX, ich die Matrix aus DirectX hernehmen kann (welche ja row-major ist) und dann mit der Matrix aus OpenGL (welche column-major ist) pre multiplizieren muss?
Ich werde die Sachen noch selbst testen mit den beiden API's, aber bevor ich nicht eine genauere Idee habe, was ich testen soll und was überhaupt in die richtige Richtung geht, würde das nur weitere Verwirrung stiften+ewig dauern. Dankbar für jede Antwort die hilft :)
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 14.10.2009, 13:34
von Richard Schubert
Die Antwort ist gar nicht so leicht. :)
In D3D sind matrizen row-major (weiß nicht ob es sich mit D3D10 geändert hat). Das Koordinatensytem ist linkshändig bis D3D9, D3D10 & XNA sind rechtshändig.
OpenGL ist column-major und rechtshändig.
Das sind aber alles Definitionen der jeweiligen APIs, du kannst sowohl die Händigkeit als auch die row/column-major angelegenheit mit deiner eigenen mathlib anders festlegen.
In Shadern sollten in der Regel alle matrizen column-major gespeichert werden, egal für welche welche API.
zu 1. Ja die sehen unterschiedlich im Speicher aus.
zu 2. würde theoretisch funktionieren, wenn beide APIs gleichhändig wären. Praktisch wirst du nur Erfolg haben wenn du zum Beispiel eine D3DMatrix von linkshändig nach rechtshändig konvertierst, um diese in OGL verwenden zu können. Aso ja, mit D3D10 oder XNA Matrizen sollte das natürlich laufen (da rechtshändig).
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 14.10.2009, 14:14
von Krishty
Richard Schubert hat geschrieben:In Shadern sollten in der Regel alle matrizen column-major gespeichert werden, egal für welche welche API.
Warum? column-major lässt sich z.B. schlechter optimieren als row-major.
Gruß, Ky
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 14.10.2009, 14:16
von Jörg
Nee, OpenGL und DirectX-Matriyen sehen im Speicherlayout (als wenn man sie per float* auslesen wuerde) identisch aus, da sie entsprechend ihrer 'majority' gespeichert werden. D.h. bei row-major geht es zeilenweise, bei column-major spaltenweise. Da ausserdem die Matrizen mathematisch transponiert sind (wegen der Vektoren, die mal von links und mal von rechts anmultipliziert werden), kommt im Speicherbild das gleiche raus. Irgendwo gabs dazu mal was von J. Watte, ich find's nur net so schnell.
Was bitte sind D3D10-Matrizen? ;) D3DX-Mathlib, oder XNAMath oder was meinst Du? Die einzige 'Haendigkeit' die ich da erkenne, ist die des Backbuffers, und die ist doch bei D3D9 auch rechtsrum, nicht ?
Edit: Na hier ham' wa 's:
http://www.mindcontrol.org/~hplus/graph ... ayout.html
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 14.10.2009, 16:04
von Richard Schubert
Krishty hat geschrieben:Richard Schubert hat geschrieben:In Shadern sollten in der Regel alle matrizen column-major gespeichert werden, egal für welche welche API.
Warum? column-major lässt sich z.B. schlechter optimieren als row-major.
Gruß, Ky
um dp3/dp4 zu verwenden, um einen vektor zu transformieren, muss die matrix doch schon transponiert vorliegen, also column-major, oder verwechsle ich die jetzt?
Jörg hat geschrieben:Nee, OpenGL und DirectX-Matriyen sehen im Speicherlayout (als wenn man sie per float* auslesen wuerde) identisch aus, da sie entsprechend ihrer 'majority' gespeichert werden. D.h. bei row-major geht es zeilenweise, bei column-major spaltenweise. Da ausserdem die Matrizen mathematisch transponiert sind (wegen der Vektoren, die mal von links und mal von rechts anmultipliziert werden), kommt im Speicherbild das gleiche raus. Irgendwo gabs dazu mal was von J. Watte, ich find's nur net so schnell.
Ja stimmt, Denkfehler von mir.
Jörg hat geschrieben:
Was bitte sind D3D10-Matrizen? ;) D3DX-Mathlib, oder XNAMath oder was meinst Du? Die einzige 'Haendigkeit' die ich da erkenne, ist die des Backbuffers, und die ist doch bei D3D9 auch rechtsrum, nicht ?
D3D9 ist linkshändig:
http://msdn.microsoft.com/en-us/library ... S.85).aspx
Wenn man keine Shader verwendet und die voreingestelltemn Matrizen der jeweiligen APIs verwendet, dann spielt die Händigkeit eine Rolle. Oder man importiert Daten aus anderen Koordinatensystemen. Man muss sich jedenfalls für ein System entscheiden.
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 14.10.2009, 16:49
von Krishty
Richard Schubert hat geschrieben:um dp3/dp4 zu verwenden, um einen vektor zu transformieren, muss die matrix doch schon transponiert vorliegen, also column-major, oder verwechsle ich die jetzt?
Nein, aber wenn sie row-major vorliegen kannst du sie stattdessen über vier multiply-adds transformieren. Dabei ist die Performance noch gleich den vier dp4s von column-major. Weißt du allerdings, dass die W-Komponente des Vektors immer 1 ist (wie bei 99% der Geometrie), kannst du die Transformation in
drei mads bewältigen, also 25% schneller als bei column-major. (
Quelle)
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 14.10.2009, 20:59
von Jörg
Oh, da verlinke ich mal gegen (deswegen bezog ich mich auch auf den Backbuffer, war ehrlich gesagt mehr als Scherz gemeint):
"The Direct3D Transformation Pipeline" (mist, das White Paper kann ich nicht verlinken, ist im SDK).
Da sieht man dass der Backbuffer sehr wohl rechtshaendig ist: X nach rechts, Y nach unten und Z nach hinten.
Allerdings wird ja erwaehnt, dass die Viewport-Transformation eine Spiegelung beinhaltet. Deshalb sind die Standardmatrizen vorher natuerlich linkshaendig, das wollte ich nicht in Frage stellen.
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 14.10.2009, 22:05
von Marserdling
So we've come to the second issue: how matrices are stored in memory. If you treat vectors as columns, then in OpenGL matrices are stored column major. If you treat vectors as rows, then matrices are stored (as they are in the current GL) row major.
Das hier versteh ich nicht, weil er hier sehr wohl sagt dass OpenGL je nach Interpretation des Programmierers Matrizen anders in den Speicher legt. Sein Erklärungsansatz ist, dass man in OpenGL seine Matrizen auch als row major verstehen kann (er sagt hier row major wäre sowieso OpenGL, aber etwas vorher in seinem Post schreibt er noch dass OpenGL column major speichert.... Oo?!), und diese dann auch so gespeichert werden...das ist seltsam, das impliziert, dass ich in OpenGL mit auch ohne Probleme mit row-major Matrizen rechnen kann und das dann plötzlich einen Effekt darauf hätte wie sie gespeichert werden.
Quelle:
http://steve.hollasch.net/cgindex/math/ ... n-vec.html
Nee, OpenGL und DirectX-Matriyen sehen im Speicherlayout (als wenn man sie per float* auslesen wuerde) identisch aus, da sie entsprechend ihrer 'majority' gespeichert werden. D.h. bei row-major geht es zeilenweise, bei column-major spaltenweise. Da ausserdem die Matrizen mathematisch transponiert sind (wegen der Vektoren, die mal von links und mal von rechts anmultipliziert werden), kommt im Speicherbild das gleiche raus.
Woher weiß denn die Sprache die ich gerade benutze welche majority meine Matrix gerade hat um sie dementsprechend zu speichern? (falls die Programmiersprache nicht dafür verantwortlich ist Matrizen in den Speicher zu legen -entschuldigt bitte meine Naivität)
Warum/wann genau werden Matrizen transponiert? Sehe momentan keinen Zusammenhang zwischen deinen 2 Aussagen.
Deinen Link les ich mir morgen genauer durch, momentan keine Kapazität mehr.
Das Koordinatensytem ist linkshändig bis D3D9, D3D10 & XNA sind rechtshändig.
Wow danke, das war mir völlig neu. Wahnsinn dass das nie stärker kolportiert wurde.
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 15.10.2009, 10:01
von Jörg
Die Sprache 'weiss' das i.A. nicht, es ist eine Designentscheidung der API.
Matrizen sollte man transponieren, wenn man moechte, dass ein Zeilenvektor (v) genauso transformiert wird wie ein (komponentengleicher) Spaltenvektor v^T.
v*M = (M^T * v^T)^T
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 15.10.2009, 21:36
von exploid
...
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 15.10.2009, 22:19
von klickverbot
exploid hat geschrieben:(1) Die Produktbildung ist nur möglich, wenn die Spaltenzahl von A mit der Zeilenzahl von B übereinstimmt.
Daraus ergibt sich die Tatsache, dass Spaltenvektoren von rechts, Zeilenvektoren aber von links an eine Matrix multipliziert werden müssen. OpenGL »verwendet« Spaltenvektoren, DirectX Zeilenvektoren. Deswegen müsstest du, wie Jörg schon geschrieben hat, eine »OpenGL-style«-Matrix transponieren, wenn du sie in DirectX für die gleiche Transformation verwenden wolltest,
wenn sich nicht auch das Speicherlayout von Matrizen in OpenGL und DirectX unterscheiden würde.
Da bei der Transposition ja gewissermaßen Zeilen und Spalten der Matrix vertauscht werden, und sich row- und column-major-Layout genau dadurch unterscheiden, kannst du Matrizen für eine bestimmte Operation 1:1 übernehmen, wenn du die Matrix lediglich als
float[16] betrachtest. Würdest du hingegen eine Matrix für eine bestimmte Transformation in OpenGL erzeugen und sie dann elementweise in eine Matrix für DirectX kopieren (also nach der jeweiligen Konvention aus der einen Matrix das Element (i,j) auslesen und es dann an die Position (i,j) in der anderen Matrix schreiben), würdest du nicht das gewünschte Ergebnis erhalten, da die durch die unterschiedlichen Speicherlayouts bei der direkten Kopie »implizierte« Transposition wegfällt.
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 19.10.2009, 20:31
von Marserdling
Die Sprache 'weiss' das i.A. nicht, es ist eine Designentscheidung der API.
Matrizen sollte man transponieren, wenn man moechte, dass ein Zeilenvektor (v) genauso transformiert wird wie ein (komponentengleicher) Spaltenvektor v^T.
v*M = (M^T * v^T)^T
Hm evt. verstehe ich etwas falsch, aber auf dem Papier brauche ich keine dritte Transponierung (die außerhalb der Klammern) mehr damit die Terme auf beiden Seiten gleich sind.
Wow klickverbot, ausgezeichnete Erklärung,
vielen Dank dafür ! Habs mir auf dem Papier durchgerechnet, und es funkt alles. Intuitiv sitzen tut es noch nicht, aber das kommt noch mit mehr Übung :)
Hier nochmal eine Erklärung wie es jetzt "in meinem Gehirn aussieht", vielleicht hilft es jemandem der das liest und noch immer nicht zurechtkommt:
Ich speichere eine DX Matrix ganz normal runter in ein float[16] nach row-major Reihenfolge und in OpenGL wird diese dann ohnehin anders ausgelesen...nämlich in eine column-major Matrix! Damit haben wir effektiv eine Transponierung erreicht, welche wir dringend nötig hatten, denn column-major Vektoren aus OpenGL können nur von links mit Matrizen multipliziert werden. Hätten wir unsere Matrix also nicht implizit vorher transponiert (=durch das andere Auslesen was OpenGL macht), ständen wir vor dem Problem dass unterschiedliche Lösungen herauskämen wenn wir die Matrix auf die andere Seite stellen ohne zu transponieren.
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 19.10.2009, 20:50
von klickverbot
Marserdling hat geschrieben:Hm evt. verstehe ich etwas falsch, aber auf dem Papier brauche ich keine dritte Transponierung (die außerhalb der Klammern) mehr damit die Terme auf beiden Seiten gleich sind.
Doch, die brauchst du rein auf dem Papier, damit auf der rechten Seite statt einem Spaltenvektor wieder ein Zeilenvektor steht (jetzt mal davon ausgegangen, dass v ein Zeilenvektor ist).
In der Computergraphik-Praxis merkst du natürlich nichts davon, weil OpenGL ja ohnehin Spaltenvektoren erwartet; die Transposition brauchst du in dem Beispiel oben nur, damit die linke und rechte Seite der Gleichung wirklich gleich sind.
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 20.10.2009, 20:22
von Ingrater
Nur so nebenbei. Seit OpenGL 3.x ist das ganze Matrix Zeugs sowieso rausgeflogen und du musst jetzt den Mathekram komplett selber machen. Das einzige was du beachten musst beim übergeben von Matrizen an Shader ist ein Transponieren-Flag das dann mehr oder weniger dafür steht ob du eine Zeilen oder eine Spaltenmatrix übergibst.
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 20.10.2009, 22:49
von Marserdling
Also jetzt ist doch noch eine Frage aufgetaucht, ich stecks hier mal nach:
(Achtung, sehr naiv)
Was für einen Unterschied macht es, wenn ich zwei Matrizen miteinander multipliziere, und die Reihenfolge vertausche? Gibt es da irgendeine allgemeine Regel? (schon klar dass es einen Unterschied gibt, habe das auf Papier ausprobiert. Die Frage ist wie man sich diesen Unterschied vorstellen kann?) Gibt es hier auch Unterschiede zwischen OpenGL und DirectX ? Ich habe in Selbstübungen immer ein wenig herumprobiert, und bin auch stets zum gewünschten visuellen Ergebnis gelangt, aber so verstanden hab ich es nie.
Bsp: will ich einer 3D Rotationsmatrix noch ein wenig mehr Rotation verleihen, oder was immer ein Grund zur Verwirrung war: von welcher Seite ich die Modelview Matrix mit einer neuen Translationsmatrix multiplizieren soll.
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 20.10.2009, 23:08
von Aramis
Was für einen Unterschied macht es, wenn ich zwei Matrizen miteinander multipliziere, und die Reihenfolge vertausche
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 21.10.2009, 00:02
von klickverbot
Marserdling hat geschrieben:[…] von welcher Seite ich die Modelview Matrix mit einer neuen Translationsmatrix multiplizieren soll.
Nehmen wir an, du arbeitest mit Spaltenvektoren, musst einen Vektor
v also folgendermaßen transformieren:
v' =
M *
v. Wenn deine Transformationsmatrix
M aus drei einzelnen Matrizen bzw. Transformationen zusammengesetzt wurde, könntest du das ja auch folgendermaßen aufschreiben
v' = (
M3 * M2 * M1) *
v. Da für die Matrizenmultiplikation das Assoziativgesetz gilt, kannst du die Klammern auch folgendermaßen setzen:
v' = (
M3 * M2) * (
M1 *
v). Das sieht jetzt nicht besonders berauschend aus, erlaubt dir aber folgenden Schluss: Bei der Verwendung von Spaltenvektoren wird die Transformation, deren Matrix als letztes von rechts an eine gemeinsame Transformationsmatrix multipliziert wurde, als erstes auf den zu transformierenden Vektor angewendet; bei Zeilenvektoren natürlich vice versa.
Ich weiß nicht, ob dir das in irgendeiner Weise hilft, aber ich habe hier in der Ressourcen-Sektion eine Arbeit zum Thema
Mathematische Grundlagen der 3D-Grafik eingestellt, die ich unlängst geschrieben habe. Eine Warnung gleich vorweg: Abgesehen davon, dass generell das Niveau der Arbeit recht niedrig angesetzt ist, habe ich einige Basics der 3D-Grafik beschreiben müssen, die einem Programmierer vollkommen klar sein sollten, da die Arbeit im Rahmen meiner Mathematik-Matura entstanden ist – das betreffende Kapitel kannst du getrost ignorieren.
P.S.: Könnte man dem Forum bitte LaTeX-Unterstützung spendieren? ;)
Re: Matrixmultiplikation_ Unterschiede DirectX - OpenGL
Verfasst: 21.10.2009, 13:25
von eXile
P.S.: Könnte man dem Forum bitte LaTeX-Unterstützung spendieren? ;)
Auch wenn es offtopic ist: Ich bin auch dafür :lol: