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

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

Version vom 21. Januar 2018, 19:05 Uhr

Lazarus - OpenGL 3.3 Tutorial - Texturen - Texturen Perspektiven-Korrektur.png

Texturen - Texturen Perspektiven-Korrektur

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.


Da etwas anderes als BMP gleaden wird, muss anstelle von TBitmap TPicture verwendet werden.

Momentan kann TPicture folgende Datei-Formate laden: BMP, GIF, JPG, PCX, PNG, P?M, PDS, TGA, TIF, XPM, ICO, CUR, ICNS.

procedure TForm1.InitScene;
var
  pic: TPicture;
  i: integer;
begin
  glClearColor(0.6, 0.6, 0.4, 1.0);

  glBindVertexArray(VBO_Trapeze.VAO);

  // Vektoren Trapez
  glBindBuffer(GL_ARRAY_BUFFER, VBO_Trapeze.VBO.Vertex);
  glBufferData(GL_ARRAY_BUFFER, sizeof(TrapezeVertex), @TrapezeVertex, GL_STATIC_DRAW);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, nil);

  // 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);



Vertex-Shader:

#version 330

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

uniform mat4 mat;

out Data {
  vec2 UV0;
  out vec3 UV1;
  out vec4 UV2;
} DataOut;

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



Fragment-Shader:

#version 330

in Data {
  vec2 UV0;
  in vec3 UV1;
  in vec4 UV2;
} DataIn;

uniform sampler2D Sampler; // Textursampler
uniform int variante;      // Variante der Texturberechnung

out vec4 FragColor;

void main()
{
  switch (variante) {

    // 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 );
  }
}



mauer.xpm:

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


Autor: Mathias

Siehe auch