Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Mär 28, 2024 16:55

Foren-Übersicht » Programmierung » Shader
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 9 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Di Jan 27, 2015 17:05 
Offline
DGL Member

Registriert: Di Dez 16, 2014 10:18
Beiträge: 32
Programmiersprache: C++
HalliHallo,

ich wollte in meinem Shader eine einfache Rotation durchführen.

Meine Rotationsmatrix sieht dabei wie folgt aus:

Code:
  1. float s = sin(angle);
  2. float c = cos(angle);
  3. float oc = 1.0 - c;
  4.  
  5. mat4 rotMat = mat4(
  6.     oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,
  7.     oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,
  8.     oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,
  9.     0.0, 0.0, 0.0, 1.0);



Rotation eines Punktes wurde (bislang) so in der main-func aufgerufen:

Code:
  1. vec4 rPoint = rotMat * vec4(Point, 1.0f)


Wie sich jedoch heraus stellte, müssen die Matrix und der Vektor vertauscht werden, um das richtige Ergebnis zu erhalten:

Code:
  1. vec4 rPoint =  vec4(Point, 1.0f) *  rotMat


Ist das korrekt?

Danke schonmal

Lösung:
Der Konstruktor einer Matrix in GLSL ist spaltenweise (siehe GLSL Specs 1.50, Seite 52 ) aufgebaut und nicht wie hier angegeben, zeilenweise.

Die korrekte Rotationsmatrix ist in GLSL folgendermaßen definiert:
Code:
  1. mat4 rotMat = mat4(
  2.         oc * axis.x * axis.x + c,           oc * axis.y * axis.x + axis.z * s,  oc * axis.z * axis.x - axis.y * s,  0.0,
  3.         oc * axis.x * axis.y - axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.z * axis.y + axis.x * s,  0.0,
  4.         oc * axis.x * axis.z + axis.y * s,  oc * axis.y * axis.z - axis.x * s,  oc * axis.z * axis.z + c,           0.0,
  5.         0.0,                                0.0,                                0.0,                                1.0);
  6.  



Danke für eure Hilfe, Vorschläge und Bemühungen.


Zuletzt geändert von beecksche am Mi Jan 28, 2015 11:21, insgesamt 5-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Matrix- und Vektormultiplikation
BeitragVerfasst: Di Jan 27, 2015 17:50 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Wieso rotierst du die Matrix nicht ausserhalb des Shaders ?

Zitat:
Wie sich jedoch heraus stellte, müssen die Matrix und der Vektor vertauscht werden, um das richtige Ergebnis zu erhalten:

Die Reihenfolge der Multiplikation spielt ein grosse Rolle.

Bei dem Beispiel unten sieht man gut, das verschiedene Ergebnisse kommen.

Code:
  1.   gl_Position = WorldMatrix * vec4(inPos, 1.0);
  2.   gl_Position = vec4(inPos, 1.0) * WorldMatrix;
  3.  
  4.   Matrix = Matrix1 * Matrix2;
  5.   Matrix = Matrix2 * Matrix1;

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Matrix- und Vektormultiplikation
BeitragVerfasst: Di Jan 27, 2015 18:26 
Offline
DGL Member

Registriert: Di Dez 16, 2014 10:18
Beiträge: 32
Programmiersprache: C++
Ich möchten den CPU so gut wie möglich nicht benutzen.

Wie sehen dann die Rechenregeln für die Reihenfolgen aus?

Bei der einfachen Darstellung wird ja auch zuerst die MVP und dann der Vektor geschrieben:

Code:
  1. gl_Position = MVP * vec4(vertex, 1.0f)


In der MVP ist ja idR auch eine Modelmatrix (Rotation/Translation).

Werden dann hierbei beim Erstellen (via glm) eine invertierte Matrix erstellt, sodass dann die gewünschte Rotation entsteht?

Mathematisch betrachtet kann ich halt keinen Vektor mit einer Matrix multiplizieren (meines Wissens nach). Daher bin ich etwas irritiert.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Matrix- und Vektormultiplikation
BeitragVerfasst: Di Jan 27, 2015 18:35 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Zitat:
Ich möchten den CPU so gut wie möglich nicht benutzen.

Ein grosse Entlastung für die CPU ist dies nicht, dafür hat die GPU richtigen Stress.
Nehmen wir mal ein einfaches Dreieck an. Wen du die Matrix mit der CPU berechnest, muss die Matrix einmal berechnet werden, in der GPU 3 mal.
Bei einem Würfel sind es schon 36 mal in der GPU, bei der CPU immer noch einmal.

Zitat:
Wie sehen dann die Rechenregeln für die Reihenfolgen aus?

Dies ist der richtige Weg.
Code:
  1. gl_Position = WorldMatrix * vec4(inPos, 1.0);
  2. // oder bei 2 Matrixen:
  3. gl_Position = projection_matrix * modelview_matrix * vec4(inPos, 1.0);


Zu diesem Thema hatte ich auch mal eine Thread eröffnet: http://www.delphigl.com/forum/viewtopic.php?f=30&t=11085

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Matrix- und Vektormultiplikation
BeitragVerfasst: Di Jan 27, 2015 18:40 
Offline
DGL Member

Registriert: Di Dez 16, 2014 10:18
Beiträge: 32
Programmiersprache: C++
Das mit der performance leuchtet mir ein. Ich werde es mal ausprobieren. Danke

Aber warum er mir trotzdem bei der richtigen Reihenfolge, das falsche Ergebnis liefert, würde mich dennoch interessieren.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Matrix- und Vektormultiplikation
BeitragVerfasst: Di Jan 27, 2015 19:37 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich nehme an, du hast einen Fehler bei der rotMat Berechnung.
Hattest du eine Vorlage für deine Berechnung ?

Ich würde zuerst die Matrix-Berechnung mit der CPU durchführen und testen, ob der Fehler immer noch ist.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Matrix- und Vektormultiplikation
BeitragVerfasst: Di Jan 27, 2015 19:40 
Offline
DGL Member

Registriert: Di Dez 16, 2014 10:18
Beiträge: 32
Programmiersprache: C++
ja das werde ich morgen mal versuchen: also die Matrix als uniform Variable im Shader und dann eine Rotationsmatrix mithilfe glm erstellen und "hochladen".

Die Rotationsmatrix hab ich von: https://gist.github.com/neilmendoza/4512992

Ich habe auch dieselbe ebenso in einer Lektüre gefunden und ich nehme diese auch bei der CPU-Berechnung.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Matrix- und Vektormultiplikation
BeitragVerfasst: Di Jan 27, 2015 22:52 
Offline
DGL Member
Benutzeravatar

Registriert: Di Apr 29, 2008 18:56
Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,

das mit der Performance ist so nicht ganz richtig. Natürlich ist es besser so wenig Berechnungen wie nötig im Shader zu machen, aber Matrizen müssen so oder so auf jeden Vertex angewendet werden, also is es durchaus sinnvoll das vom GPU machen zu lassen. Die Matrix im Shader sollte allerdings eine Konstante oder globale Variable sein, dann wird die nur einmal initialisiert. Wenn die Matrix in der Main-Method erstellt wird, dann hat mathias Recht, das wäre mehr als unperformant, da die matrix dann für jeden Vertex neu ausgerechnet werden müsste. Könnte aber auch seni das der Compiler so schlau ist und das selbst rausrechnet, wenn die genutzten Variablen in der Matrix selbst nur Konstanten sind, aber drauf verlassen würde ich mich drauf nicht.

Zum eigentlichen Problem: Vector * Matrix geht soweit ich weiß gar nicht, da hätte ich vom Compiler jetzt ein Fehler erwartet. Wenn man einen Vector mit einer Matrix manipulieren möchste, dann ist das immer ResultVector = Matrix * Vector. Die Formel für deine Rotationsmatrix sieht soweit ich das seh richtig aus. Was genau hat sich denn bei dir falsch gedreht. Bzw. was hast du erwartet wie es sich dreht? Vlt auch mal mit konkreten Werten. Wie rechnest du mit rPoint weiter? Vlt ist der Fehler auch wo anders im Code. Wäre gut wenn du den ganzen Ausschnitt mal posten könntest.

MfG Bergmann.

_________________
Aktuelle Projekte: BumpMapGenerator, Massive Universe Online
Auf meiner Homepage gibt auch noch paar Projekte und Infos von mir.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Matrix- und Vektormultiplikation
BeitragVerfasst: Di Jan 27, 2015 23:12 
Offline
DGL Member

Registriert: Di Dez 16, 2014 10:18
Beiträge: 32
Programmiersprache: C++
Danke für den Hinweis. Ich werde morgen mal jegliche Varianten ausprobieren, dokumentieren und hier präsentieren.

Das genaue Problem sieht wie folgt aus:

Ich habe mehrere Koordinaten die um eine gewisse Achse rotiert werden. Die Koordinaten liegen in einem VBO und ich wollte alle mithilfe eines VertexShaders rotieren lassen und mithilfe des Transform Feebacks wieder auslesen, da ich die "neuen" Koordinaten für weitere Berechnungen am CPU benötige.

Das einachste Beispiel sieht so aus:

Rotationsgerade: (0.0, 1.0, 0.0)
Rotationswinkel: 90°

Betrachte ich in diesem Beispiel den Punkt (1.0, 0.0, 0.0).

Nach der Rotation hat der Punkt die neuen Koordinaten: (0.0, 0.0, -1.0).
Soweit die Theorie und Praxis mit dem CPU.

Mit dem Shader (Matrix * Vektor) bekomme ich jedoch diese Koordinaten zurück: (0.0, 0.0, +1.0). Als ob der Rotationswinkel das negative Vorzeichen besitzt.
Ich habe jedoch die Übergabe der Rotationsgerade und des -winkels bei der glUniform-Übergabe überprüft und diese sind korrekt.

Wenn ich nun im Shader jedoch die Reihenfolge der Multiplikation vertausche (also Vektor * Matrix), bekomme ich die korrekten Koordinaten.

:?: :?:


EDIT:

Wenn ich die Rotationsmatrix als uniform übergebe
Code:
  1. glm::mat4 rotate;
  2. rotate = glm::rotate(
  3.     rotate,
  4.     angle,
  5.     glm::vec3(0.0f, 1.0f, 0.0f));

, erhalte ich das richtige Ergebnis.

Konkret:
Code:
  1. in vec3 vertex;
  2.  
  3. uniform mat4 rotMat;
  4.  
  5. out vec3 outValue;
  6.  
  7. void main() {
  8.     vec4 rP = rotMat * vec4(vertex, 1.0f);
  9.     outValue = rp.xyz;
  10. }

liefert das richtige Ergebnis.

Code:
  1. in vec3 vertex;
  2.  
  3. uniform float angle;
  4. uniform vec3 axis;
  5.  
  6. float s = sin(angle);
  7. float c = cos(angle);
  8. float oc = 1.0 - c;
  9. mat4 rotMat = mat4(
  10.     oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0,
  11.     oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0,
  12.     oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0,
  13.     0.0, 0.0, 0.0, 1.0);
  14.  
  15. out vec3 outValue;
  16.  
  17. void main() {
  18.     vec4 rP = rotMat * vec4(vertex, 1.0f);
  19.     outValue = rp.xyz;
  20. }

liefert das falsche Ergebnis. Wenn ich jedoch im letzten Shader die Reihenfolge der Multiplikation vertausche:
Code:
  1. void main() {
  2.     vec4 rP = vec4(vertex, 1.0f)* rotMat;
  3.     outValue = rp.xyz;
  4. }

erhalte ich das richtige Ergebnis. Was jedoch nicht auftreten sollte :?: :?:


EDIT #2:

Ich glaube ich habe den Fehler:

Nach OpenGL Specs 1.50 GLSL, Seite 52 ist der Konstruktor einer Matrix folgendermaßen definiert:
Code:
  1. mat4(float, float, float, float, // first column
  2. float, float, float, float, // second column
  3. float, float, float, float, // third column
  4. float, float, float, float); // fourth column
  5.  


Und dies entrspricht meiner transponierten (!!) Rotationsmatrix. Daher auch der "falsche" Drehsinn und daher auch das richtige Ergebnis bei der geänderten Reihenfolge!

Ist die Rotationsmatrix demnach in der Quelle falsch?


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 9 Beiträge ] 
Foren-Übersicht » Programmierung » Shader


Wer ist online?

Mitglieder in diesem Forum: Google [Bot] und 10 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.032s | 18 Queries | GZIP : On ]