Lazarus - OpenGL 3.3 Tutorial - Texturen - Multitexturing: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
Zeile 1: Zeile 1:
[[Image:Lazarus - OpenGL 3.3 Tutorial - Texturen - Texturen Perspektiven-Korrektur.png|200px]]<br><br>
+
[[Image:Lazarus - OpenGL 3.3 Tutorial - Texturen - Multitexturing.png|200px]]<br><br>
=Texturen - Texturen Perspektiven-Korrektur =
+
=Texturen - Multitexturing =
 
== Einleitung ==
 
== Einleitung ==
Für sehr einfache Texturen, ist das xpm-Format geeignet. Mit diesem kann man sehr schnell eine einfache Textur mit einem Text-Editor erstellen.<br>
+
Multitexturing, tönt Anfangs sehr kompliziert, aber im Grunde ist es sehr einfach.<br>
 +
Der Unterschied zu einer einzelnen Textur ist, das man mehrere Texturen über die Mesh zieht.<br>
 +
Somit muss man auch mehrere Texturen beim Zeichenen mittels '''glActiveTexture(...''' aktivieren.<br>
 +
<br>
 +
Hier im Beispiel, ist es ein Stück Mauer, welches mit einer farbigen Lampe angeleuchtet wird.<br>
 
<br><br>
 
<br><br>
Da etwas anderes als '''BMP''' gleaden wird, muss anstelle von '''TBitmap TPicture''' verwendet werden.<br>
+
Die Textur-Puffer deklarieren, sehr einfach geht dies mit einer Array.<br>
 +
<syntaxhighlight lang="pascal">var
 +
  Textur: array [0..1] of TTexturBuffer;</syntaxhighlight>
 +
Textur-Puffer erzeugen und Shader vorbereiten.<br>
 +
Die Textur-Sampler muss man durchnummerieren.<br>
 +
<syntaxhighlight lang="pascal">procedure TForm1.CreateScene;
 +
begin
 +
  Textur[0] := TTexturBuffer.Create;
 +
  Textur[1] := TTexturBuffer.Create;
 +
 
 +
  Shader := TShader.Create([FileToStr('Vertexshader.glsl'), FileToStr('Fragmentshader.glsl')]);
 +
  with Shader do begin
 +
    UseProgram;
 +
    Matrix_ID := UniformLocation('mat');
 +
    glUniform1i(UniformLocation('Sampler[0]'), 0);  // Dem Sampler[0] 0 zuweisen.
 +
    glUniform1i(UniformLocation('Sampler[1]'), 1);  // Dem Sampler[1] 0 zuweisen.
 +
  end;</syntaxhighlight>
 +
Mit diesr Klasse geht das laden einer Bitmap sehr einfach.<br>
 +
Man kann die Texturen auch von einem '''TRawImages''' laden.<br>
 +
<syntaxhighlight lang="pascal">procedure TForm1.InitScene;
 +
begin
 +
  Textur[0].LoadTextures('mauer.xpm');
 +
  Textur[1].LoadTextures('licht.xpm');</syntaxhighlight>
 +
Da man bei Multitexturing mehrere Sampler braucht, muss man mitteilen, welche Textur zu welchen Sampler gehört.<br>
 +
Dies macht man mit '''glActiveTexture(...''', Dazu muss man als Parameter die '''Sampler-Nr + GL_TEXTURE0''' mitgeben.<br>
 
<br>
 
<br>
Momentan kann TPicture folgende Datei-Formate laden: '''BMP, GIF, JPG, PCX, PNG, P?M, PDS, TGA, TIF, XPM, ICO, CUR, ICNS'''.<br>
+
Das sieht man auch gut in der TTexturBuffer Class.<br>
<syntaxhighlight lang="pascal">procedure TForm1.InitScene;
+
<syntaxhighlight lang="pascal">procedure TTexturBuffer.ActiveAndBind(Nr: integer);
var
+
begin
   pic: TPicture;
+
   glActiveTexture(GL_TEXTURE0 + Nr);
   i: integer;
+
   glBindTexture(GL_TEXTURE_2D, FID);  // FID ist Textur-ID.
 +
end;</syntaxhighlight>
 +
<br>
 +
<syntaxhighlight lang="pascal">procedure TForm1.ogcDrawScene(Sender: TObject);
 
begin
 
begin
   glClearColor(0.6, 0.6, 0.4, 1.0);
+
   glClear(GL_COLOR_BUFFER_BIT);
  
   glBindVertexArray(VBO_Trapeze.VAO);
+
   Textur[0].ActiveAndBind(0); // Textur 0 mit Sampler 0 binden.
 
+
   Textur[1].ActiveAndBind(1); // Textur 1 mit Sampler 1 binden.</syntaxhighlight>
  // Vektoren Trapez
+
Die beiden Texturen am Ende wieder frei geben.<br>
  glBindBuffer(GL_ARRAY_BUFFER, VBO_Trapeze.VBO.Vertex);
+
<syntaxhighlight lang="pascal">procedure TForm1.FormDestroy(Sender: TObject);
  glBufferData(GL_ARRAY_BUFFER, sizeof(TrapezeVertex), @TrapezeVertex, GL_STATIC_DRAW);
+
begin
  glEnableVertexAttribArray(0);
+
   Textur[0].Free; // Texturen frei geben.
  glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, nil);
+
   Textur[1].Free;</syntaxhighlight>
 
 
  // Unkorrigierte Textur-Koordinaten
 
   glBindBuffer(GL_ARRAY_BUFFER, VBO_Trapeze.VBO.Textur[0]);
 
  glBufferData(GL_ARRAY_BUFFER, sizeof(TextureNormalVertex), @TextureNormalVertex, GL_STATIC_DRAW);
 
  glEnableVertexAttribArray(10);
 
  glVertexAttribPointer(10, 2, GL_FLOAT, False, 0, nil);
 
 
 
  // Perspektivenkorrigiert Variante 1
 
  glBindBuffer(GL_ARRAY_BUFFER, VBO_Trapeze.VBO.Textur[1]);
 
  glBufferData(GL_ARRAY_BUFFER, sizeof(TexturePerspVertex1), @TexturePerspVertex1, GL_STATIC_DRAW);
 
  glEnableVertexAttribArray(11);
 
   glVertexAttribPointer(11, 3, GL_FLOAT, False, 0, nil);
 
 
 
  // Perspektivenkorrigiert Variante 2
 
   glBindBuffer(GL_ARRAY_BUFFER, VBO_Trapeze.VBO.Textur[2]);
 
  glBufferData(GL_ARRAY_BUFFER, sizeof(TexturePerspVertex2), @TexturePerspVertex2, GL_STATIC_DRAW);
 
  glEnableVertexAttribArray(12);
 
  glVertexAttribPointer(12, 4, GL_FLOAT, False, 0, nil);</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 inUV0;    // Textur-Koordinaten
 
layout (location = 10) in vec2 inUV0;    // Textur-Koordinaten
layout (location = 11) in vec3 inUV1;    // Textur-Koordinaten
+
layout (location = 11) in vec2 inUV1;    // Textur-Koordinaten
layout (location = 12) in vec4 inUV2;    // Textur-Koordinaten
 
  
 
uniform mat4 mat;
 
uniform mat4 mat;
  
out Data {
+
out vec2 UV0;
  vec2 UV0;
+
out vec2 UV1;
  out vec3 UV1;
 
  out vec4 UV2;
 
} DataOut;
 
  
 
void main(void)
 
void main(void)
 
{
 
{
 
   gl_Position = mat * vec4(inPos, 1.0);
 
   gl_Position = mat * vec4(inPos, 1.0);
   DataOut.UV0 = inUV0;                          // Textur-Koordinaten weiterleiten.
+
   UV0 = inUV0;                          // Textur-Koordinaten weiterleiten.
   DataOut.UV1 = inUV1,                          // Textur-Koordinaten weiterleiten.
+
   UV1 = inUV1;                          // Textur-Koordinaten weiterleiten.
  DataOut.UV2 = inUV2;                          // Textur-Koordinaten weiterleiten.
 
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 
<br><br>
 
<br><br>
 
==Fragment-Shader:==
 
==Fragment-Shader:==
 +
<br>
 +
Bei diesem einfachen Beispiel werden einfach die Pixel der Textur addiert und anschliessend duch 2 geteilt.<br>
 
<syntaxhighlight lang="glsl">#version 330
 
<syntaxhighlight lang="glsl">#version 330
  
in Data {
+
in vec2 UV0;
  vec2 UV0;
+
in vec2 UV1;
  in vec3 UV1;
 
  in vec4 UV2;
 
} DataIn;
 
  
uniform sampler2D Sampler; // Textursampler
+
uniform sampler2D Sampler[2];                     // 2 Sampler deklarieren.
uniform int variante;      // Variante der Texturberechnung
 
  
 
out vec4 FragColor;
 
out vec4 FragColor;
Zeile 81: Zeile 87:
 
void main()
 
void main()
 
{
 
{
   switch (variante) {
+
   FragColor = (texture( Sampler[0], UV0 ) +        // Die beiden Farben zusammenzählen und anschliessend durch 2 teilen.
 
+
              texture( Sampler[1], UV1 )) / 2.0;
    // Unkorrigiert
 
    case 0: FragColor = texture( Sampler, DataIn.UV0 );
 
            break;
 
 
 
    // Korrigiert Variante 1
 
    case 1: FragColor = texture( Sampler, DataIn.UV1.xy / DataIn.UV1.z );
 
            break;
 
 
 
    // Korrigiert Variante 2
 
    case 2: FragColor = texture2DProj( Sampler, DataIn.UV2 );
 
  }
 
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
Zeile 100: Zeile 95:
 
<syntaxhighlight lang="cpp">/* XPM */
 
<syntaxhighlight lang="cpp">/* XPM */
 
static char *XPM_mauer[] = {
 
static char *XPM_mauer[] = {
  "8 8 2 1",
+
"8 8 2 1",
  "  c #882222",
+
"  c #AA2222",
  "* c #442222",
+
"* c #222222",
  "********",
+
"********",
   "*  *  ",
+
"*  *   ",
   "*  *  ",
+
"*  *  ",
   "*  *  ",
+
"*   *  ",
   "********",
+
"********",
  "  *  * ",
+
" * ",
  "  *  * ",
+
* ",
  "  *  * "
+
"  *   * "
 +
};
 +
</syntaxhighlight>
 +
<br><br>
 +
==licht.xpm:==
 +
<syntaxhighlight lang="cpp">/* XPM */
 +
static char *XPM_mauer[] = {
 +
"8 8 2 1",
 +
"  c #AA2222",
 +
"* c #222222",
 +
"********",
 +
"*  *  ",
 +
"*  *  ",
 +
"*  *   ",
 +
"********",
 +
"  *  * ",
 +
"  *  * ",
 +
"  *  * "
 
};
 
};
 
</syntaxhighlight>
 
</syntaxhighlight>

Version vom 21. Januar 2018, 19:06 Uhr

Lazarus - OpenGL 3.3 Tutorial - Texturen - Multitexturing.png

Texturen - Multitexturing

Einleitung

Multitexturing, tönt Anfangs sehr kompliziert, aber im Grunde ist es sehr einfach.
Der Unterschied zu einer einzelnen Textur ist, das man mehrere Texturen über die Mesh zieht.
Somit muss man auch mehrere Texturen beim Zeichenen mittels glActiveTexture(... aktivieren.

Hier im Beispiel, ist es ein Stück Mauer, welches mit einer farbigen Lampe angeleuchtet wird.


Die Textur-Puffer deklarieren, sehr einfach geht dies mit einer Array.

var
  Textur: array [0..1] of TTexturBuffer;

Textur-Puffer erzeugen und Shader vorbereiten.
Die Textur-Sampler muss man durchnummerieren.

procedure TForm1.CreateScene;
begin
  Textur[0] := TTexturBuffer.Create;
  Textur[1] := TTexturBuffer.Create;

  Shader := TShader.Create([FileToStr('Vertexshader.glsl'), FileToStr('Fragmentshader.glsl')]);
  with Shader do begin
    UseProgram;
    Matrix_ID := UniformLocation('mat');
    glUniform1i(UniformLocation('Sampler[0]'), 0);  // Dem Sampler[0] 0 zuweisen.
    glUniform1i(UniformLocation('Sampler[1]'), 1);  // Dem Sampler[1] 0 zuweisen.
  end;

Mit diesr Klasse geht das laden einer Bitmap sehr einfach.
Man kann die Texturen auch von einem TRawImages laden.

procedure TForm1.InitScene;
begin
  Textur[0].LoadTextures('mauer.xpm');
  Textur[1].LoadTextures('licht.xpm');

Da man bei Multitexturing mehrere Sampler braucht, muss man mitteilen, welche Textur zu welchen Sampler gehört.
Dies macht man mit glActiveTexture(..., Dazu muss man als Parameter die Sampler-Nr + GL_TEXTURE0 mitgeben.

Das sieht man auch gut in der TTexturBuffer Class.

procedure TTexturBuffer.ActiveAndBind(Nr: integer);
begin
  glActiveTexture(GL_TEXTURE0 + Nr);
  glBindTexture(GL_TEXTURE_2D, FID);  // FID ist Textur-ID.
end;


procedure TForm1.ogcDrawScene(Sender: TObject);
begin
  glClear(GL_COLOR_BUFFER_BIT);

  Textur[0].ActiveAndBind(0); // Textur 0 mit Sampler 0 binden.
  Textur[1].ActiveAndBind(1); // Textur 1 mit Sampler 1 binden.

Die beiden Texturen am Ende wieder frei geben.

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Textur[0].Free;  // Texturen frei geben.
  Textur[1].Free;



Vertex-Shader:

#version 330

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

uniform mat4 mat;

out vec2 UV0;
out vec2 UV1;

void main(void)
{
  gl_Position = mat * vec4(inPos, 1.0);
  UV0 = inUV0;                           // Textur-Koordinaten weiterleiten.
  UV1 = inUV1;                           // Textur-Koordinaten weiterleiten.
}



Fragment-Shader:


Bei diesem einfachen Beispiel werden einfach die Pixel der Textur addiert und anschliessend duch 2 geteilt.

#version 330

in vec2 UV0;
in vec2 UV1;

uniform sampler2D Sampler[2];                      // 2 Sampler deklarieren.

out vec4 FragColor;

void main()
{
  FragColor = (texture( Sampler[0], UV0 ) +        // Die beiden Farben zusammenzählen und anschliessend durch 2 teilen.
               texture( Sampler[1], UV1 )) / 2.0;
}



mauer.xpm:

/* XPM */
static char *XPM_mauer[] = {
"8 8 2 1",
"  c #AA2222",
"* c #222222",
"********",
"*   *   ",
"*   *   ",
"*   *   ",
"********",
"  *   * ",
"  *   * ",
"  *   * "
};



licht.xpm:

/* XPM */
static char *XPM_mauer[] = {
"8 8 2 1",
"  c #AA2222",
"* c #222222",
"********",
"*   *   ",
"*   *   ",
"*   *   ",
"********",
"  *   * ",
"  *   * ",
"  *   * "
};


Autor: Mathias

Siehe auch