Lazarus - OpenGL 3.3 Tutorial - Shader - Uniform Variablen

Aus DGL Wiki
Wechseln zu: Navigation, Suche

Lazarus - OpenGL 3.3 Tutorial - Shader - Uniform Variablen.png

Shader - Uniform Variablen

Einleitung

Hier wird die Farbe des Meshes über eine Unifom-Variable an den Shader übergeben, somit kann die Farbe zur Laufzeit geändert werden.
Unifom-Variablen dienen dazu, um Parameter den Shader-Objecte zu übergeben. Meistens sind dies Matrizen, oder wie hier im Beispiel die Farben.
Oder auch Beleuchtung-Parameter, zB. die Position des Lichtes.


Deklaration der ID, welche auf die Unifom-Variable im Shader zeigt, und die Variable, welche die Farbe für den Vektor enthält.
Da man die Farbe als Vektor übergibt, habe ich dafür den Typ TVertex3f gewählt. Seine Komponenten beschreiben den Rot-, Grün- und Blauanteil der Farbe.

var
  Color_ID: GLint;      // ID
  MyColor: TVertex3f;   // Farbe

Dieser Code wurde um eine Zeile UniformLocation erweitert.
Diese ermittelt die ID, wo sich Color im Shader befindet.

Vor dem Ermitteln muss mit UseProgram der Shader aktviert werden, von dem man lesen will.
Im Hintergrund wird dabei glGetUniformLocation(ProgrammID,... aufgerufen.
Der Vektor von MyColor ist in RGB (Rot, Grün, Blau).

Der String in UniformLocation muss identisch mit dem Namen der Uniform-Variable im Shader sein. Wichtig: Es muss auf Gross- und Kleinschreibung geachtet werden.

procedure TForm1.CreateScene;
begin
  Shader := TShader.Create([FileToStr('Vertexshader.glsl'), FileToStr('Fragmentshader.glsl')]);
  Shader.UseProgram;
  Color_ID := Shader.UniformLocation('Color'); // Ermittelt die ID von "Color".
  // MyColor Blau zuweisen.
  MyColor[0] := 0.0;
  MyColor[1] := 0.0;
  MyColor[2] := 1.0;

Hier wird die Uniform-Variable übergeben. Für diese vec3-Variable gibt es zwei Möglichkeiten.
Mit glUniform3fv... kann man sie als ganzen Vektor übergeben.
Mit glUniform3f(... kann man die Komponenten der Farben auch einzeln übergeben.

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

  // Zeichne Dreieck
  glUniform3fv(Color_ID, 1, @MyColor);   // Als Vektor
  glBindVertexArray(VBTriangle.VAO);
  glDrawArrays(GL_TRIANGLES, 0, Length(Triangle) * 3);

  // Zeichne Quadrat
  glUniform3f(Color_ID, 1.0, 0.0, 0.0);  // Einzel
  glBindVertexArray(VBQuad.VAO);
  glDrawArrays(GL_TRIANGLES, 0, Length(Quad) * 3);

  ogc.SwapBuffers;
end;

Folgende Prozedur weist dem Vektor <b<MyColor eine andere Farbe zu.
Dafür wird ein einfaches Menü verwendet.

procedure TForm1.MenuItemClick(Sender: TObject);
begin
  case TMainMenu(Sender).Tag of
    0: begin   // Rot
      MyColor[0] := 1.0;
      MyColor[1] := 0.0;
      MyColor[2] := 0.0;
    end;
    1: begin   // Grün
      MyColor[0] := 0.0;
      MyColor[1] := 1.0;
      MyColor[2] := 0.0;
    end;
    2: begin   // Blau
      MyColor[0] := 0.0;
      MyColor[1] := 0.0;
      MyColor[2] := 1.0;
    end;
  end;
  ogc.Invalidate;   // Manuelle Aufruf von DrawScene.
end;



Vertex-Shader:

#version 330

layout (location = 10) in vec3 inPos; // Vertex-Koordinaten
 
void main(void)
{
  gl_Position = vec4(inPos, 1.0);
}



Fragment-Shader:


Hier ist die Uniform-Variable Color hinzugekommen.
Diese habe ich nur im Fragment-Shader deklariert, da diese nur hier gebraucht wird.

#version 330

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

void main(void)
{
  outColor = vec4(Color, 1.0); // Das 1.0 ist der Alpha-Kanal, hat hier keine Bedeutung.
}


Autor: Mathias

Siehe auch