Lazarus - OpenGL 3.3 Tutorial - Matrix - Matrix Rotieren: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
K (Einleitung)
 
(7 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 3: Zeile 3:
 
== Einleitung ==
 
== Einleitung ==
 
Hier wird eine '''4x4 Matrix''' verwendet, dies ist Standard bei allen Mesh Translationen.<br>
 
Hier wird eine '''4x4 Matrix''' verwendet, dies ist Standard bei allen Mesh Translationen.<br>
Im Timer wird Matrix-Rotation ausgeführt.<br>
+
Im Timer wird eine Matrix-Rotation ausgeführt.<br>
Für diese einfache Roatation, könnte man auch eine 2x2-Matrix nehmen, aber sobald man die Mesh auch verschieben will, braucht man '''4x4-Matrix''', auch wird es sonst komplizierter im Shader.<br>
+
Für diese einfache Roatation, könnte man auch eine '''2x2-Matrix''' nehmen, aber sobald man die Mesh auch verschieben will, braucht man '''4x4-Matrix''', auch wird es sonst komplizierter im Shader.<br>
 
<br><br>
 
<br><br>
 
Hier wird ein Matrix4x4-Typ deklariert.<br>
 
Hier wird ein Matrix4x4-Typ deklariert.<br>
 +
Für die Manipulationen einer Matrix eignet sich hervorragend ein '''Type Helper'''.<br>
 
<syntaxhighlight lang="pascal">type
 
<syntaxhighlight lang="pascal">type
   TMatrix = array[0..3, 0..3] of GLfloat;</syntaxhighlight>
+
   TMatrix = array[0..3, 0..3] of GLfloat;
Hier wird eine Einheits-Matrix erzeugt, bei einer 4x4-Matrix, sieht dies so aus:<br>
+
 
<syntaxhighlight lang="pascal">| 1 | 0 | 0 | 0 |
+
  TMatrixfHelper = Type Helper for TMatrix
| 0 | 1 | 0 | 0 |
+
    procedure Indenty;                  // Generiere eine Einheitsmatrix
| 0 | 0 | 1 | 0 |
+
    procedure Rotate(angele: single);  // Drehe Matrix
| 0 | 0 | 0 | 1 |</syntaxhighlight>
+
   end;</syntaxhighlight>
<syntaxhighlight lang="pascal">const
 
   MatrixIndenty: TMatrix = ((1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0));</syntaxhighlight>
 
 
Die Matrix selbst, die rotiert wird.<br>
 
Die Matrix selbst, die rotiert wird.<br>
 
Und die ID für den Shader.<br>
 
Und die ID für den Shader.<br>
Zeile 21: Zeile 20:
 
   MatrixRot: TMatrix;    // Matrix
 
   MatrixRot: TMatrix;    // Matrix
 
   MatrixRot_ID: GLint;    // ID für Matrix.</syntaxhighlight>
 
   MatrixRot_ID: GLint;    // ID für Matrix.</syntaxhighlight>
 +
Hier wird eine Einheits-Matrix erzeugt, bei einer 4x4-Matrix, sieht dies so aus:<br>
 +
<br>
 +
{| class="wikitable"
 +
| style="width:3em;height:3em;text-align:center"| 1 || style="width:3em;height:3em;text-align:center"| 0 || style="width:3em;height:3em;text-align:center"| 0 || style="width:3em;height:3em;text-align:center"| 0
 +
|-
 +
| style="width:3em;height:3em;text-align:center"| 0 || style="width:3em;height:3em;text-align:center"| 1 || style="width:3em;height:3em;text-align:center"| 0 || style="width:3em;height:3em;text-align:center"| 0
 +
|-
 +
| style="width:3em;height:3em;text-align:center"| 0 || style="width:3em;height:3em;text-align:center"| 0 || style="width:3em;height:3em;text-align:center"| 1 || style="width:3em;height:3em;text-align:center"| 0
 +
|-
 +
| style="width:3em;height:3em;text-align:center"| 0 || style="width:3em;height:3em;text-align:center"| 0 || style="width:3em;height:3em;text-align:center"| 0 || style="width:3em;height:3em;text-align:center"| 1
 +
|-
 +
|}
 +
<syntaxhighlight lang="pascal">procedure TMatrixfHelper.Indenty;
 +
const
 +
  MatrixIndenty: TMatrix = ((1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0));
 +
begin
 +
  Self := MatrixIndenty;
 +
end;</syntaxhighlight>
 
Mit dieser Procedure, wird die Matrix rotiert.<br>
 
Mit dieser Procedure, wird die Matrix rotiert.<br>
 
Der Winkel wird im '''Bogenmass''' angegeben.<br>
 
Der Winkel wird im '''Bogenmass''' angegeben.<br>
Für nicht Mathematiker, 360° sind 2*π ( 2*Pi ).<br>
+
Für nicht Mathematiker, '''360°''' sind '''2⋅π''' ( 2⋅Pi ).<br>
<syntaxhighlight lang="pascal">procedure MatrixRotate(var mat: TMatrix; angele: single);
+
<syntaxhighlight lang="pascal">procedure TMatrixfHelper.Rotate(angele: single);
 
var
 
var
 
   i: integer;
 
   i: integer;
Zeile 30: Zeile 47:
 
begin
 
begin
 
   for i := 0 to 1 do begin
 
   for i := 0 to 1 do begin
     x := mat[i, 0];
+
     x := Self[i, 0];
     y := mat[i, 1];
+
     y := Self[i, 1];
     mat[i, 0] := x * cos(angele) - y * sin(angele);
+
     Self[i, 0] := x * cos(angele) - y * sin(angele);
     mat[i, 1] := x * sin(angele) + y * cos(angele);
+
     Self[i, 1] := x * sin(angele) + y * cos(angele);
 
   end;
 
   end;
end;</syntaxhighlight>
+
end;
 +
</syntaxhighlight>
 
In diesem Code sind zwei Zeilen relevant, eine mit '''UniformLocation''' für die Matrix-ID.<br>
 
In diesem Code sind zwei Zeilen relevant, eine mit '''UniformLocation''' für die Matrix-ID.<br>
 
In der anderen wird die Matrix, die gedreht wird, erst mal als Einheits-Matrix gesetzt.<br>
 
In der anderen wird die Matrix, die gedreht wird, erst mal als Einheits-Matrix gesetzt.<br>
Zeile 45: Zeile 63:
 
   Color_ID := Shader.UniformLocation('Color');
 
   Color_ID := Shader.UniformLocation('Color');
 
   MatrixRot_ID := Shader.UniformLocation('mat'); // Ermittelt die ID von MatrixRot.
 
   MatrixRot_ID := Shader.UniformLocation('mat'); // Ermittelt die ID von MatrixRot.
   MatrixRot := MatrixIndenty;                   // MatrixRot auf Einheits-Matrix setzen.</syntaxhighlight>
+
   MatrixRot.Indenty;                             // MatrixRot auf Einheits-Matrix setzen.</syntaxhighlight>
 
Hier wird die Uniform-Variable '''MatrixRot''' dem Shader übergeben.<br>
 
Hier wird die Uniform-Variable '''MatrixRot''' dem Shader übergeben.<br>
Mit '''glUniform4fv(...''' kann man eine 4x4 Matrix dem Shader übergeben.<br>
+
Mit '''glUniform4fv(...''' kann man eine '''4x4 Matrix''' dem Shader übergeben.<br>
 
Für eine 2x2 Matrix wäre dies '''glUniform2fv(...''' und für die 3x3 '''glUniform3fv(...'''.<br>
 
Für eine 2x2 Matrix wäre dies '''glUniform2fv(...''' und für die 3x3 '''glUniform3fv(...'''.<br>
 
<syntaxhighlight lang="pascal">procedure TForm1.ogcDrawScene(Sender: TObject);
 
<syntaxhighlight lang="pascal">procedure TForm1.ogcDrawScene(Sender: TObject);
Zeile 59: Zeile 77:
 
   step: GLfloat = 0.01;          // Der Winkel ist im Bogenmass.
 
   step: GLfloat = 0.01;          // Der Winkel ist im Bogenmass.
 
begin
 
begin
   MatrixRotate(MatrixRot, step); // MatrixRot rotieren.
+
   MatrixRot.Rotate(step);       // MatrixRot rotieren.
 
   ogcDrawScene(Sender);          // Neu zeichnen.
 
   ogcDrawScene(Sender);          // Neu zeichnen.
 
end;</syntaxhighlight>
 
end;</syntaxhighlight>
 
<br><br>
 
<br><br>
 +
 
==Vertex-Shader:==
 
==Vertex-Shader:==
 
<br>
 
<br>

Aktuelle Version vom 19. Mai 2018, 21:18 Uhr

Lazarus - OpenGL 3.3 Tutorial - Matrix - Matrix Rotieren.png

Matrix - Matrix Rotieren

Einleitung

Hier wird eine 4x4 Matrix verwendet, dies ist Standard bei allen Mesh Translationen.
Im Timer wird eine Matrix-Rotation ausgeführt.
Für diese einfache Roatation, könnte man auch eine 2x2-Matrix nehmen, aber sobald man die Mesh auch verschieben will, braucht man 4x4-Matrix, auch wird es sonst komplizierter im Shader.


Hier wird ein Matrix4x4-Typ deklariert.
Für die Manipulationen einer Matrix eignet sich hervorragend ein Type Helper.

type
  TMatrix = array[0..3, 0..3] of GLfloat;

  TMatrixfHelper = Type Helper for TMatrix
    procedure Indenty;                  // Generiere eine Einheitsmatrix
    procedure Rotate(angele: single);   // Drehe Matrix
  end;

Die Matrix selbst, die rotiert wird.
Und die ID für den Shader.

var
  MatrixRot: TMatrix;     // Matrix
  MatrixRot_ID: GLint;    // ID für Matrix.

Hier wird eine Einheits-Matrix erzeugt, bei einer 4x4-Matrix, sieht dies so aus:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
procedure TMatrixfHelper.Indenty;
const
  MatrixIndenty: TMatrix = ((1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0));
begin
  Self := MatrixIndenty;
end;

Mit dieser Procedure, wird die Matrix rotiert.
Der Winkel wird im Bogenmass angegeben.
Für nicht Mathematiker, 360° sind 2⋅π ( 2⋅Pi ).

procedure TMatrixfHelper.Rotate(angele: single);
var
  i: integer;
  x, y: GLfloat;
begin
  for i := 0 to 1 do begin
    x := Self[i, 0];
    y := Self[i, 1];
    Self[i, 0] := x * cos(angele) - y * sin(angele);
    Self[i, 1] := x * sin(angele) + y * cos(angele);
  end;
end;

In diesem Code sind zwei Zeilen relevant, eine mit UniformLocation für die Matrix-ID.
In der anderen wird die Matrix, die gedreht wird, erst mal als Einheits-Matrix gesetzt.
Dies ist wichtig, ansonsten sieht man keine Mesh mehr, da diese unendlich klein skaliert wird.

procedure TForm1.CreateScene;
begin
  Shader := TShader.Create([FileToStr('Vertexshader.glsl'), FileToStr('Fragmentshader.glsl')]);
  Shader.UseProgram;
  Color_ID := Shader.UniformLocation('Color');
  MatrixRot_ID := Shader.UniformLocation('mat'); // Ermittelt die ID von MatrixRot.
  MatrixRot.Indenty;                             // MatrixRot auf Einheits-Matrix setzen.

Hier wird die Uniform-Variable MatrixRot dem Shader übergeben.
Mit glUniform4fv(... kann man eine 4x4 Matrix dem Shader übergeben.
Für eine 2x2 Matrix wäre dies glUniform2fv(... und für die 3x3 glUniform3fv(....

procedure TForm1.ogcDrawScene(Sender: TObject);
begin
  glClear(GL_COLOR_BUFFER_BIT);
  Shader.UseProgram;
  glUniformMatrix4fv(MatrixRot_ID, 1, False, @MatrixRot); // MatrixRot in den Shader.

Die Drehung der Matrix wird fortlaufend um den Wert step gedreht.

procedure TForm1.Timer1Timer(Sender: TObject);
const
  step: GLfloat = 0.01;          // Der Winkel ist im Bogenmass.
begin
  MatrixRot.Rotate(step);        // MatrixRot rotieren.
  ogcDrawScene(Sender);          // Neu zeichnen.
end;



Vertex-Shader:


Hier ist die Uniform-Variable mat hinzugekommen, dies ist auch eine 4x4-Matrix, so wie im Haupt-Programm.
Diese wird im Vertex-Shader deklariert, Bewegungen kommen immer in diesen Shader.

Man sieht dort auch gut, das die Vektoren mit dieser Matrix multipliziert werden.
Da diese Multiplikation im Shader ist, wird die Berechnung in der GPU ausgeführt, und somit wird die CPU entlastet.
Aus diesem Grund haben Gaming-Grafikkarten solch eine grosse Leistung.

#version 330

layout (location = 10) in vec3 inPos;    // Vertex-Koordinaten
uniform mat4 mat;                        // Matrix von Uniform

void main(void)
{
  gl_Position = mat * vec4(inPos, 1.0);  // Vektoren mit der Matrix multiplizieren.
}



Fragment-Shader:

#version 330

uniform vec3 Color;  // Farbe von Uniform
out vec4 outColor;   // ausgegebene Farbe

void main(void)
{
  outColor = vec4(Color, 1.0);
}


Autor: Mathias

Siehe auch