Lazarus - OpenGL 3.3 Tutorial - Alpha Blending - Reihenfolge sortiert mit Texturen: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
(Die Seite wurde neu angelegt: „200px<br><br> =Alpha Blending - Reihenfolge sortiert mit Textu…“)
 
K (Einleitung)
 
(8 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 4: Zeile 4:
 
Da mit Texturen welche Alpha-Blending haben das gleiche Problem besteht, wie mit den Würfeln, muss man auch dort sortieren.<br>
 
Da mit Texturen welche Alpha-Blending haben das gleiche Problem besteht, wie mit den Würfeln, muss man auch dort sortieren.<br>
 
Da die Position der Bäume keine Drehbewegung haben, reicht ein Vector für dessen Position, eine Matrix ist nicht nötig.<br>
 
Da die Position der Bäume keine Drehbewegung haben, reicht ein Vector für dessen Position, eine Matrix ist nicht nötig.<br>
Für den Boden wird eine Matrix gebrauch, da ich diesen drehe.<br>
+
Für den Boden wird eine Matrix gebraucht, da ich diesen drehe.<br>
 
<br>
 
<br>
 
Zusätzlich habe ich für den Boden noch eine Textur genommen, somit sieht die Scene recht realistisch aus.<br>
 
Zusätzlich habe ich für den Boden noch eine Textur genommen, somit sieht die Scene recht realistisch aus.<br>
 
<br>
 
<br>
Wie Texturen funktionieren, in einem späteren Kapitel<br>
+
Wie Texturen funktionieren, in einem späteren Kapitel.<br>
 
<br><br>
 
<br><br>
 
Den Speicher für die Position der Bäume reservieren.<br>
 
Den Speicher für die Position der Bäume reservieren.<br>
Zeile 19: Zeile 19:
 
     New(TreePosArray[i]);
 
     New(TreePosArray[i]);
 
   end;</syntaxhighlight>
 
   end;</syntaxhighlight>
Die Position der Bäume wird zufällig bestimmt.<br>
+
Die Position der Bäume wird zufällig bestimmt.<br>
 
<syntaxhighlight lang="pascal">procedure TForm1.InitScene;
 
<syntaxhighlight lang="pascal">procedure TForm1.InitScene;
 
const
 
const
Zeile 34: Zeile 34:
 
Dabei ist es wichtig, das man zuerst den Boden zeichnet, weil die Bäume Alpha-Blending haben.<br>
 
Dabei ist es wichtig, das man zuerst den Boden zeichnet, weil die Bäume Alpha-Blending haben.<br>
 
Objecte mit Alpha-Blending sollte man immer zum Schluss zeichnen.<br>
 
Objecte mit Alpha-Blending sollte man immer zum Schluss zeichnen.<br>
<syntaxhighlight lang="pascal"> // --- Zeichne Boden
+
<syntaxhighlight lang="pascal">procedure TForm1.ogcDrawScene(Sender: TObject);
  
   SandTextur.ActiveAndBind;                             // Boden-Textur binden
+
  procedure QuickSort(var ia: array of PTreePos; ALo, AHi: integer);
 +
  var
 +
    Lo, Hi: integer;
 +
    dummy : PTreePos;
 +
    Pivot: TTreePos;
 +
  begin
 +
    Lo := ALo;
 +
    Hi := AHi;
 +
    Pivot := ia[(Lo + Hi) div 2]^;
 +
    repeat
 +
      while ia[Lo]^.z < Pivot.z do begin
 +
        Inc(Lo);
 +
      end;
 +
      while ia[Hi]^.z > Pivot.z do begin
 +
        Dec(Hi);
 +
      end;
 +
      if Lo <= Hi then begin
 +
        dummy := ia[Lo];
 +
        ia[Lo] := ia[Hi];
 +
        ia[Hi] := dummy;
 +
        Inc(Lo);
 +
        Dec(Hi);
 +
      end;
 +
    until Lo > Hi;
 +
    if Hi > ALo then begin
 +
      QuickSort(ia, ALo, Hi);
 +
    end;
 +
    if Lo < AHi then begin
 +
      QuickSort(ia, Lo, AHi);
 +
    end;
 +
  end;
 +
 
 +
var
 +
  i: integer;
 +
begin
 +
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);        // Frame und Tiefen-Puffer löschen.
 +
 
 +
  glEnable(GL_CULL_FACE);
 +
  glCullface(GL_BACK);
 +
 
 +
  Shader.UseProgram;
 +
 
 +
  glBindVertexArray(VBQuad.VAO);
 +
 
 +
  // --- Zeichne Boden
 +
   SandTextur.ActiveAndBind;                                   // Boden-Textur binden
 
   Matrix.Identity;
 
   Matrix.Identity;
 
   Matrix.Translate(0.0, 1.0, 0.0);
 
   Matrix.Translate(0.0, 1.0, 0.0);
Zeile 42: Zeile 87:
 
   Matrix.RotateA(Pi / 2);
 
   Matrix.RotateA(Pi / 2);
  
   Matrix.Multiply(GroundPos, Matrix);
+
   Matrix := FrustumMatrix * WorldMatrix * GroundPos * Matrix; // Matrizen multiplizieren.
 
 
  Matrix.Multiply(WorldMatrix, Matrix);                  // Matrixen multiplizieren.
 
  Matrix.Multiply(FrustumMatrix, Matrix);
 
  
   Matrix.Uniform(Matrix_ID);                             // Matrix dem Shader übergeben.
+
   Matrix.Uniform(Matrix_ID);                                 // Matrix dem Shader übergeben.
   glDrawArrays(GL_TRIANGLES, 0, Length(QuadVertex) * 3); // Zeichnet einen kleinen Würfel.
+
   glDrawArrays(GL_TRIANGLES, 0, Length(QuadVertex));
  
 
   // --- Zeichne Bäume
 
   // --- Zeichne Bäume
   QuickSort(TreePosArray, 0, TreeCount - 1);             // Die Bäume sortieren.
+
   QuickSort(TreePosArray, 0, TreeCount - 1);                 // Die Bäume sortieren.
  
   BaumTextur.ActiveAndBind;                             // Baum-Textur binden
+
   BaumTextur.ActiveAndBind;                                   // Baum-Textur binden
  
 
   for i := 0 to TreeCount - 1 do begin
 
   for i := 0 to TreeCount - 1 do begin
 
     Matrix.Identity;
 
     Matrix.Identity;
     Matrix.Translate(TreePosArray[i]^);                 // Die Bäume an die richtige Position bringen
+
     Matrix.Translate(TreePosArray[i]^);                       // Die Bäume an die richtige Position bringen
  
     Matrix.Multiply(WorldMatrix, Matrix);
+
     Matrix := FrustumMatrix * WorldMatrix * Matrix;           // Matrizen multiplizieren.
    Matrix.Multiply(FrustumMatrix, Matrix);
 
  
 
     Matrix.Uniform(Matrix_ID);
 
     Matrix.Uniform(Matrix_ID);
     glDrawArrays(GL_TRIANGLES, 0, Length(QuadVertex) * 3);
+
     glDrawArrays(GL_TRIANGLES, 0, Length(QuadVertex));
   end;</syntaxhighlight>
+
   end;
Da sieht man, das es recht nur den Vector zu drehen.<br>
+
 
 +
  ogc.SwapBuffers;
 +
end;</syntaxhighlight>
 +
Da sieht man, das es reicht nur den Vector zu drehen.<br>
 
<syntaxhighlight lang="pascal">procedure TForm1.Timer1Timer(Sender: TObject);
 
<syntaxhighlight lang="pascal">procedure TForm1.Timer1Timer(Sender: TObject);
 
const
 
const
Zeile 80: Zeile 124:
 
end;</syntaxhighlight>
 
end;</syntaxhighlight>
 
<br><br>
 
<br><br>
 +
 
==Vertex-Shader:==
 
==Vertex-Shader:==
 
<syntaxhighlight lang="glsl">#version 330
 
<syntaxhighlight lang="glsl">#version 330
  
 
layout (location =  0) in vec3 inPos; // Vertex-Koordinaten
 
layout (location =  0) in vec3 inPos; // Vertex-Koordinaten
layout (location = 10) in vec2 inUV;   // Textur-Koordinaten
+
layout (location = 10) in vec2 inUV; // Textur-Koordinaten
  
 
out vec2 UV0;
 
out vec2 UV0;
Zeile 93: Zeile 138:
 
{
 
{
 
   gl_Position = Matrix * vec4(inPos, 1.0);
 
   gl_Position = Matrix * vec4(inPos, 1.0);
   UV0        = inUV;                           // Textur-Koordinaten weiterleiten.
+
   UV0        = inUV;                 // Textur-Koordinaten weiterleiten.
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 
<br><br>
 
<br><br>
 +
 
==Fragment-Shader==
 
==Fragment-Shader==
 
<syntaxhighlight lang="glsl">#version 330
 
<syntaxhighlight lang="glsl">#version 330

Aktuelle Version vom 1. August 2018, 20:11 Uhr

Lazarus - OpenGL 3.3 Tutorial - Alpha Blending - Reihenfolge sortiert mit Texturen.png

Alpha Blending - Reihenfolge sortiert mit Texturen

Einleitung

Da mit Texturen welche Alpha-Blending haben das gleiche Problem besteht, wie mit den Würfeln, muss man auch dort sortieren.
Da die Position der Bäume keine Drehbewegung haben, reicht ein Vector für dessen Position, eine Matrix ist nicht nötig.
Für den Boden wird eine Matrix gebraucht, da ich diesen drehe.

Zusätzlich habe ich für den Boden noch eine Textur genommen, somit sieht die Scene recht realistisch aus.

Wie Texturen funktionieren, in einem späteren Kapitel.


Den Speicher für die Position der Bäume reservieren.

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to TreeCount - 1 do begin
    New(TreePosArray[i]);
  end;

Die Position der Bäume wird zufällig bestimmt.

procedure TForm1.InitScene;
const
  d = 10;
var
  i: integer;
begin
  for i := 0 to TreeCount - 1 do begin
    TreePosArray[i]^.x := -d / 2 + Random * d;
    TreePosArray[i]^.y := 0.0;
    TreePosArray[i]^.z := -d / 2 + Random * d;
  end;

Der Boden und die Bäume zeichen.
Dabei ist es wichtig, das man zuerst den Boden zeichnet, weil die Bäume Alpha-Blending haben.
Objecte mit Alpha-Blending sollte man immer zum Schluss zeichnen.

procedure TForm1.ogcDrawScene(Sender: TObject);

  procedure QuickSort(var ia: array of PTreePos; ALo, AHi: integer);
  var
    Lo, Hi: integer;
    dummy : PTreePos;
    Pivot: TTreePos;
  begin
    Lo := ALo;
    Hi := AHi;
    Pivot := ia[(Lo + Hi) div 2]^;
    repeat
      while ia[Lo]^.z < Pivot.z do begin
        Inc(Lo);
      end;
      while ia[Hi]^.z > Pivot.z do begin
        Dec(Hi);
      end;
      if Lo <= Hi then begin
        dummy := ia[Lo];
        ia[Lo] := ia[Hi];
        ia[Hi] := dummy;
        Inc(Lo);
        Dec(Hi);
      end;
    until Lo > Hi;
    if Hi > ALo then begin
      QuickSort(ia, ALo, Hi);
    end;
    if Lo < AHi then begin
      QuickSort(ia, Lo, AHi);
    end;
  end;

var
  i: integer;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);        // Frame und Tiefen-Puffer löschen.

  glEnable(GL_CULL_FACE);
  glCullface(GL_BACK);

  Shader.UseProgram;

  glBindVertexArray(VBQuad.VAO);

  // --- Zeichne Boden
  SandTextur.ActiveAndBind;                                   // Boden-Textur binden
  Matrix.Identity;
  Matrix.Translate(0.0, 1.0, 0.0);
  Matrix.Scale(10.0);
  Matrix.RotateA(Pi / 2);

  Matrix := FrustumMatrix * WorldMatrix * GroundPos * Matrix; // Matrizen multiplizieren.

  Matrix.Uniform(Matrix_ID);                                  // Matrix dem Shader übergeben.
  glDrawArrays(GL_TRIANGLES, 0, Length(QuadVertex));

  // --- Zeichne Bäume
  QuickSort(TreePosArray, 0, TreeCount - 1);                  // Die Bäume sortieren.

  BaumTextur.ActiveAndBind;                                   // Baum-Textur binden

  for i := 0 to TreeCount - 1 do begin
    Matrix.Identity;
    Matrix.Translate(TreePosArray[i]^);                       // Die Bäume an die richtige Position bringen

    Matrix := FrustumMatrix * WorldMatrix * Matrix;           // Matrizen multiplizieren.

    Matrix.Uniform(Matrix_ID);
    glDrawArrays(GL_TRIANGLES, 0, Length(QuadVertex));
  end;

  ogc.SwapBuffers;
end;

Da sieht man, das es reicht nur den Vector zu drehen.

procedure TForm1.Timer1Timer(Sender: TObject);
const
  rot = 0.0134;
var
  i: integer;
begin
  for i := 0 to TreeCount - 1 do begin
    TreePosArray[i]^.RotateB(rot);
  end;
  GroundPos.RotateB(rot);

  ogc.Invalidate;
end;



Vertex-Shader:

#version 330

layout (location =  0) in vec3 inPos; // Vertex-Koordinaten
layout (location = 10) in vec2 inUV;  // Textur-Koordinaten

out vec2 UV0;

uniform mat4 Matrix;                  // Matrix für die Drehbewegung und Frustum.

void main(void)
{
  gl_Position = Matrix * vec4(inPos, 1.0);
  UV0         = inUV;                 // Textur-Koordinaten weiterleiten.
}



Fragment-Shader

#version 330

in vec2 UV0;

uniform sampler2D Sampler;              // Der Sampler welchem 0 zugeordnet wird.

out vec4 FragColor;

void main()
{
  FragColor = texture( Sampler, UV0 );  // Die Farbe aus der Textur anhand der Koordinten auslesen.
}


Autor: Mathias

Siehe auch