Lazarus - OpenGL 3.3 Tutorial - Beleuchtung - Mehrere Directional Light Quellen: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
(Vertex-Shader:)
K (Fragment-Shader)
 
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 4: Zeile 4:
 
Wie schon beschrieben, sind auch mehrere Lichtquellen möglich.<br>
 
Wie schon beschrieben, sind auch mehrere Lichtquellen möglich.<br>
 
<br>
 
<br>
In diesem Beispiel gib es 3 Directionale Lichtquellen, welche sich bewegen.<br>
+
In diesem Beispiel habe ich 3 Directionale Lichtquellen eingefügt, welche sich bewegen.<br>
Das man dies besser sieht sind sie in 3 Farben dargestellt.<br>
+
Das man die einzelnen Lichquellen besser sieht, habe ich sie in 3 Farben dargestellt.<br>
 
<br>
 
<br>
Die Meshes besteht aus Kugeln, so sieht man die Übergänge von hell nach dunkel besser.<br>
+
Als Meshes habe ich Kugeln gewählt, so sieht man die Übergänge von hell nach dunkel besser.<br>
 
<br>
 
<br>
Das man die Lichteffekte besser sieht, kann man sie übers Menü ein und aus Schalten.<br>
+
Das man die Lichteffekte besser sieht, kann man sie über das Menü ein und aus schalten.<br>
Auch kann man die Rotierung anhalten und die Anzahl Kugeln verändern.<br>
+
Auch kann man die Rotierung anhalten und die Anzahl der Kugeln verändern.<br>
 
<br>
 
<br>
 
Wen man nur eine Kugel hat, sieht man die Bewegung des Lichtes sehr gut.<br>
 
Wen man nur eine Kugel hat, sieht man die Bewegung des Lichtes sehr gut.<br>
 +
Wen man alle 3 Lichter ausschaltet, dann sieht man die Ambiente Hintergrund-Beleuchtung sehr gut.<br>
 
<br>
 
<br>
Wen man alle 3 Lichter ausschaltet, dann sieht man die Ambiente Hintergrund-Beleuchtung sehr gut.<br>
+
Die Lichtposition ist nicht mehr im Shader als Konstante deklariert, sie wurde mit einer '''Uniform-Variable''' nach aussen verlagert.<br>
 
<br><br>
 
<br><br>
 +
Die Lichtpositionen als 3D-Vektorn definiert.<br>
 +
<syntaxhighlight lang="pascal">var
 +
  LightPos: record
 +
    Red, Green, Blue: TVector3f;
 +
  end;</syntaxhighlight>
 +
Hier werden die verschiedenen Parameter für die Lichtparamter über Uniform am Shader übergeben.<br>
 +
<syntaxhighlight lang="pascal">procedure TForm1.ogcDrawScene(Sender: TObject);
 +
var
 +
  x, y, z: integer;
 +
  scal, d: single;
 +
begin
 +
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);  // Frame und Tiefen-Buffer löschen.
 +
 +
  glEnable(GL_CULL_FACE);
 +
  glCullface(GL_BACK);
 +
 +
  Shader.UseProgram;
 +
 +
  // Lichtpositionen
 +
  with LightPos_ID do begin
 +
    glUniform3fv(Red, 1, @LightPos.Red);
 +
    glUniform3fv(Green, 1, @LightPos.Green);
 +
    glUniform3fv(Blue, 1, @LightPos.Blue);
 +
  end;
 +
 +
  // Licht Ein/Aus - Parameter
 +
  with ColorOn_ID do begin
 +
    glUniform1i(Red, GLint(MenuItemRedOn.Checked));
 +
    glUniform1i(Green, GLint(MenuItemGreenOn.Checked));
 +
    glUniform1i(Blue, GLint(MenuItemBlueOn.Checked));
 +
  end;</syntaxhighlight>
 +
Auf verlangen Würfel drehen und Lichtposition verändern.<br>
 +
<syntaxhighlight lang="pascal">procedure TForm1.Timer1Timer(Sender: TObject);
 +
begin
 +
  if MenuItemRotateCube.Checked then begin
 +
    ModelMatrix.RotateA(0.0123);  // Drehe um X-Achse
 +
    ModelMatrix.RotateB(0.0234);  // Drehe um Y-Achse
 +
  end;
 +
 +
  with LightPos do begin
 +
    if MenuItemRotateRed.Checked then begin
 +
      Red.RotateA(0.031);
 +
      Red.RotateB(0.011);
 +
    end;
 +
 +
    if MenuItemRotateGreen.Checked then begin
 +
      Green.RotateB(0.021);
 +
      Green.RotateC(0.015);
 +
    end;
 +
 +
    if MenuItemRotateBlue.Checked then begin
 +
      Blue.RotateA(0.021);
 +
      Blue.RotateC(0.023);
 +
    end;
 +
  end;</syntaxhighlight>
 
<br><br>
 
<br><br>
Hier sieht man, das anstelle von arcos und Pi, '''clamp''' verwendet wurde.<br>
+
Wen man mehrere Lichtquellen hat, werden diese alle '''addiert'''.<br>
 +
Dies sieht man gut am Ende des Vertex-Shader, dort wo es die''' += '''hat.<br>
 +
<br>
 
==Vertex-Shader:==
 
==Vertex-Shader:==
 
<syntaxhighlight lang="glsl">#version 330
 
<syntaxhighlight lang="glsl">#version 330
  
 +
// Konstante für Abiente Hintergrundbeleuchung.
 
#define ambient vec3(0.2, 0.2, 0.2)
 
#define ambient vec3(0.2, 0.2, 0.2)
 +
 +
// Die Farben der Lichtstrahlen.
 
#define red    vec3(1.0, 0.0, 0.0)
 
#define red    vec3(1.0, 0.0, 0.0)
 
#define green  vec3(0.0, 1.0, 0.0)
 
#define green  vec3(0.0, 1.0, 0.0)
Zeile 31: Zeile 92:
 
out vec4 Color;                        // Farbe, an Fragment-Shader übergeben.
 
out vec4 Color;                        // Farbe, an Fragment-Shader übergeben.
  
uniform mat4 Matrix;                    // Matrix für die Drehbewegung und Frustum.
+
// Matrix des Modeles, ohne Frustum-Beeinflussung.
 +
uniform mat4 ModelMatrix;
  
 +
// Matrix für die Drehbewegung und Frustum.
 +
uniform mat4 Matrix;
 +
 +
// Einzelne Lichtquellen Ein/Aus.
 
uniform bool RedOn;
 
uniform bool RedOn;
 
uniform bool GreenOn;
 
uniform bool GreenOn;
 
uniform bool BlueOn;
 
uniform bool BlueOn;
  
 +
// Position der Lichtquellen.
 
uniform vec3 RedLightPos;
 
uniform vec3 RedLightPos;
 
uniform vec3 GreenLightPos;
 
uniform vec3 GreenLightPos;
 
uniform vec3 BlueLightPos;
 
uniform vec3 BlueLightPos;
  
float light(vec3 p, vec3 q){
+
// Berechnet die Ausleuchtung der einzelnen Faces.
   vec3 r1 = normalize(p);    // Vektoren normalisieren, so das die Länge des Vektors immer 1.0 ist.
+
float light(vec3 p, vec3 n) {
   vec3 r2 = normalize(q);
+
   vec3 v1 = normalize(p);    // Vektoren normalisieren,
   float d = dot(r1, r2);      // Skalarprodukt aus beiden Vektoren berechnen.
+
   vec3 v2 = normalize(n);     // so das es Einheitsvektoren gibt.
   return clamp(d, 0.0, 1.0);
+
   float d = dot(v1, v2);      // Skalarprodukt aus beiden Vektoren berechnen.
 +
   return clamp(d, 0.0, 1.0); // Bereich der Ausgabe einschränken.
 
}
 
}
  
void main(void)
+
void main(void) {
{
+
  // Vektoren mit komplette vorberechneter Matrix multipizieren.
 
   gl_Position = Matrix * vec4(inPos, 1.0);
 
   gl_Position = Matrix * vec4(inPos, 1.0);
  
   vec3 Normal = mat3(Matrix) * inNormal;
+
  // Normale nur mit lokaler Matrix Multipizieren.
 +
   vec3 Normal = mat3(ModelMatrix) * inNormal;
  
   vec3 colRed  = light(RedLightPos,  Normal) * red;
+
   // Ambiente Lichtquelle
  vec3 colGreen = light(GreenLightPos, Normal) * green;
+
   Color = vec4(ambient, 1.0);
   vec3 colBlue  = light(BlueLightPos, Normal) * blue;
 
  
   Color = vec4(ambient, 1.0);
+
   // Lichtquellen auf verlangen berechnen und addieren.
 
   if (RedOn) {
 
   if (RedOn) {
 +
    vec3 colRed = light(RedLightPos, Normal) * red;
 
     Color.rgb += colRed;
 
     Color.rgb += colRed;
 
   }
 
   }
 
   if (GreenOn) {
 
   if (GreenOn) {
 +
    vec3 colGreen = light(GreenLightPos, Normal) * green;
 
     Color.rgb += colGreen;
 
     Color.rgb += colGreen;
 
   }
 
   }
 
   if (BlueOn) {
 
   if (BlueOn) {
 +
    vec3 colBlue = light(BlueLightPos, Normal) * blue;
 
     Color.rgb += colBlue;
 
     Color.rgb += colBlue;
 
   }
 
   }
Zeile 75: Zeile 146:
 
<syntaxhighlight lang="glsl">#version 330
 
<syntaxhighlight lang="glsl">#version 330
  
in vec4 Color;     // interpolierte Farbe vom Vertexshader
+
in vec4 Color;     // interpolierte Farbe vom Vertexshader
 
out vec4 outColor;  // ausgegebene Farbe
 
out vec4 outColor;  // ausgegebene Farbe
  
void main(void)
+
void main(void) {
{
 
 
   outColor = Color; // Die Ausgabe der Farbe
 
   outColor = Color; // Die Ausgabe der Farbe
 
}
 
}
Zeile 85: Zeile 155:
  
 
<br>Autor: [[Mathias]]
 
<br>Autor: [[Mathias]]
 +
 
== Siehe auch ==
 
== Siehe auch ==
 
* Übersichtseite [[Lazarus - OpenGL 3.3 Tutorial]]
 
* Übersichtseite [[Lazarus - OpenGL 3.3 Tutorial]]

Aktuelle Version vom 22. Juli 2018, 21:07 Uhr

Lazarus - OpenGL 3.3 Tutorial - Beleuchtung - Mehrere Directional Light Quellen.png

Beleuchtung - Mehrere Directional Light Quellen

Einleitung

Wie schon beschrieben, sind auch mehrere Lichtquellen möglich.

In diesem Beispiel habe ich 3 Directionale Lichtquellen eingefügt, welche sich bewegen.
Das man die einzelnen Lichquellen besser sieht, habe ich sie in 3 Farben dargestellt.

Als Meshes habe ich Kugeln gewählt, so sieht man die Übergänge von hell nach dunkel besser.

Das man die Lichteffekte besser sieht, kann man sie über das Menü ein und aus schalten.
Auch kann man die Rotierung anhalten und die Anzahl der Kugeln verändern.

Wen man nur eine Kugel hat, sieht man die Bewegung des Lichtes sehr gut.
Wen man alle 3 Lichter ausschaltet, dann sieht man die Ambiente Hintergrund-Beleuchtung sehr gut.

Die Lichtposition ist nicht mehr im Shader als Konstante deklariert, sie wurde mit einer Uniform-Variable nach aussen verlagert.


Die Lichtpositionen als 3D-Vektorn definiert.

var
  LightPos: record
    Red, Green, Blue: TVector3f;
  end;

Hier werden die verschiedenen Parameter für die Lichtparamter über Uniform am Shader übergeben.

procedure TForm1.ogcDrawScene(Sender: TObject);
var
  x, y, z: integer;
  scal, d: single;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);  // Frame und Tiefen-Buffer löschen.

  glEnable(GL_CULL_FACE);
  glCullface(GL_BACK);

  Shader.UseProgram;

  // Lichtpositionen
  with LightPos_ID do begin
    glUniform3fv(Red, 1, @LightPos.Red);
    glUniform3fv(Green, 1, @LightPos.Green);
    glUniform3fv(Blue, 1, @LightPos.Blue);
  end;

  // Licht Ein/Aus - Parameter
  with ColorOn_ID do begin
    glUniform1i(Red, GLint(MenuItemRedOn.Checked));
    glUniform1i(Green, GLint(MenuItemGreenOn.Checked));
    glUniform1i(Blue, GLint(MenuItemBlueOn.Checked));
  end;

Auf verlangen Würfel drehen und Lichtposition verändern.

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if MenuItemRotateCube.Checked then begin
    ModelMatrix.RotateA(0.0123);  // Drehe um X-Achse
    ModelMatrix.RotateB(0.0234);  // Drehe um Y-Achse
  end;

  with LightPos do begin
    if MenuItemRotateRed.Checked then begin
      Red.RotateA(0.031);
      Red.RotateB(0.011);
    end;

    if MenuItemRotateGreen.Checked then begin
      Green.RotateB(0.021);
      Green.RotateC(0.015);
    end;

    if MenuItemRotateBlue.Checked then begin
      Blue.RotateA(0.021);
      Blue.RotateC(0.023);
    end;
  end;



Wen man mehrere Lichtquellen hat, werden diese alle addiert.
Dies sieht man gut am Ende des Vertex-Shader, dort wo es die += hat.

Vertex-Shader:

#version 330

// Konstante für Abiente Hintergrundbeleuchung.
#define ambient vec3(0.2, 0.2, 0.2)

// Die Farben der Lichtstrahlen.
#define red     vec3(1.0, 0.0, 0.0)
#define green   vec3(0.0, 1.0, 0.0)
#define blue    vec3(0.0, 0.0, 1.0)

layout (location = 0) in vec3 inPos;    // Vertex-Koordinaten
layout (location = 1) in vec3 inNormal; // Normale

out vec4 Color;                         // Farbe, an Fragment-Shader übergeben.

// Matrix des Modeles, ohne Frustum-Beeinflussung.
uniform mat4 ModelMatrix;

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

// Einzelne Lichtquellen Ein/Aus.
uniform bool RedOn;
uniform bool GreenOn;
uniform bool BlueOn;

// Position der Lichtquellen.
uniform vec3 RedLightPos;
uniform vec3 GreenLightPos;
uniform vec3 BlueLightPos;

// Berechnet die Ausleuchtung der einzelnen Faces.
float light(vec3 p, vec3 n) {
  vec3 v1 = normalize(p);     // Vektoren normalisieren,
  vec3 v2 = normalize(n);     // so das es Einheitsvektoren gibt.
  float d = dot(v1, v2);      // Skalarprodukt aus beiden Vektoren berechnen.
  return clamp(d, 0.0, 1.0);  // Bereich der Ausgabe einschränken.
}

void main(void) {
  // Vektoren mit komplette vorberechneter Matrix multipizieren.
  gl_Position = Matrix * vec4(inPos, 1.0);

  // Normale nur mit lokaler Matrix Multipizieren.
  vec3 Normal = mat3(ModelMatrix) * inNormal;

  // Ambiente Lichtquelle
  Color = vec4(ambient, 1.0);

  // Lichtquellen auf verlangen berechnen und addieren.
  if (RedOn) {
    vec3 colRed = light(RedLightPos, Normal) * red;
    Color.rgb += colRed;
  }
  if (GreenOn) {
    vec3 colGreen = light(GreenLightPos, Normal) * green;
    Color.rgb += colGreen;
  }
  if (BlueOn) {
    vec3 colBlue = light(BlueLightPos, Normal) * blue;
    Color.rgb += colBlue;
  }
}



Fragment-Shader

#version 330

in  vec4 Color;     // interpolierte Farbe vom Vertexshader
out vec4 outColor;  // ausgegebene Farbe

void main(void) {
  outColor = Color; // Die Ausgabe der Farbe
}


Autor: Mathias

Siehe auch