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

Aus DGL Wiki
Wechseln zu: Navigation, Suche
(Vertex-Shader:)
Zeile 2: Zeile 2:
 
=Beleuchtung - Einfache Beleuchtung mit Clamp =
 
=Beleuchtung - Einfache Beleuchtung mit Clamp =
 
== Einleitung ==
 
== Einleitung ==
Ohne Beleuchtung sehen die Object statisch aus, wen man noch Beleuchtung ins Spiel bringt, wirkt eine OpenGL-Scene viel realistischer.<br>
+
Im ersten Beispiel wurde die Beleuchung mit Acos und Pi berechnet.<br>
Dabei gibt es verschiedene Arten von Beleuchtung. Das meist verwendete ist '''Directional Light''', dies entspricht dem Sonnenlicht.<br>
+
Für dies gibt es in GLSL eine fertige Funktion '''clamp'''.<br>
Dieses Beispiel zeigt eine ganz einfache Variante von diesem Licht. Je steiler das Licht auf ein Polygon einstrahlt, je heller wird das Polygon.<br>
+
Auserdem wird mit '''clamp''' berücksichtig, wen der Einstrahlwinkel < 0° ist, das dann kein Liche auf das Objekt kommt.<br>
 
<br>
 
<br>
Das man dies berechnen kann, braucht es für jede Ecke des Polygons eie Normale-Vektor.<br>
+
Der einzige Unterschied zu vorherigem Beispiel ist im Shader-Code.<br>
Eine Normale zeigt meistens senkrecht auf ein Polygon.<br>
 
<br>
 
Es gibt Ausnahmen, zB. bei runden Flächen. Dazu in einem späteren Beispiel.<br>
 
 
<br><br>
 
<br><br>
Die Konstanten der Würfel-Vektoren.<br>
 
<syntaxhighlight lang="pascal">const
 
  CubeVertex: TCube =
 
    (((-0.5, 0.5, 0.5), (-0.5, -0.5, 0.5), (0.5, -0.5, 0.5)), ((-0.5, 0.5, 0.5), (0.5, -0.5, 0.5), (0.5, 0.5, 0.5)),
 
    ((0.5, 0.5, 0.5), (0.5, -0.5, 0.5), (0.5, -0.5, -0.5)), ((0.5, 0.5, 0.5), (0.5, -0.5, -0.5), (0.5, 0.5, -0.5)),
 
    ((0.5, 0.5, -0.5), (0.5, -0.5, -0.5), (-0.5, -0.5, -0.5)), ((0.5, 0.5, -0.5), (-0.5, -0.5, -0.5), (-0.5, 0.5, -0.5)),
 
    ((-0.5, 0.5, -0.5), (-0.5, -0.5, -0.5), (-0.5, -0.5, 0.5)), ((-0.5, 0.5, -0.5), (-0.5, -0.5, 0.5), (-0.5, 0.5, 0.5)),
 
    // oben
 
    ((0.5, 0.5, 0.5), (0.5, 0.5, -0.5), (-0.5, 0.5, -0.5)), ((0.5, 0.5, 0.5), (-0.5, 0.5, -0.5), (-0.5, 0.5, 0.5)),
 
    // unten
 
    ((-0.5, -0.5, 0.5), (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5)), ((-0.5, -0.5, 0.5), (0.5, -0.5, -0.5), (0.5, -0.5, 0.5)));</syntaxhighlight>
 
Für die Normale wird nur eine Variable für Vektoren deklariert, da diese aus den Vektoren des Würfels berechnet werden.<br>
 
<syntaxhighlight lang="pascal">var
 
  CubeNormal: TCube;</syntaxhighlight>
 
Für die Normale braucht es noch eine VBO.<br>
 
<syntaxhighlight lang="pascal">type
 
  TVB = record
 
    VAO,
 
    VBOvert,            // VBO für Vektor.
 
    VBONormal: GLuint;  // VBO für Normale.
 
  end;</syntaxhighlight>
 
In der Unit Matrix hat es eine fertige Funktion, welche die Normale aus den Vertex-Koordinaten berechnet.<br>
 
<syntaxhighlight lang="pascal">procedure TForm1.CreateScene;
 
begin
 
  FaceToNormale(CubeVertex, CubeNormal);</syntaxhighlight>
 
Die Normale wird genau gleich in den VRAM geladen, wie die Vertex-Koordinaten.<br>
 
<syntaxhighlight lang="pascal">procedure TForm1.InitScene;
 
begin
 
  glClearColor(0.6, 0.6, 0.4, 1.0); // Hintergrundfarbe
 
 
  // --- Daten für Würfel
 
  glBindVertexArray(VBCube.VAO);
 
 
  // Vektor
 
  glBindBuffer(GL_ARRAY_BUFFER, VBCube.VBOvert);
 
  glBufferData(GL_ARRAY_BUFFER, sizeof(CubeVertex), @CubeVertex, GL_STATIC_DRAW);
 
  glEnableVertexAttribArray(0);
 
  glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, nil);
 
 
  // Normale
 
  glBindBuffer(GL_ARRAY_BUFFER, VBCube.VBONormal);
 
  glBufferData(GL_ARRAY_BUFFER, sizeof(CubeNormal), @CubeNormal, GL_STATIC_DRAW);
 
  glEnableVertexAttribArray(1);
 
  glVertexAttribPointer(1, 3, GL_FLOAT, False, 0, nil);
 
 
end;</syntaxhighlight>
 
 
<br><br>
 
<br><br>
Einfachere Beleuchtungen macht man im Vertex-Shader.<br>
+
Hier sieht man, das anstelle von arcos und Pi, '''clamp''' verwendet wurde.<br>
Will man aber komplexer Beleuchtungen, nimmt man dazu den Fragment-Shader, das dieser Pixelgenau ist.<br>
 
Dafür wird aber mehr Berechnugszeit benötigt.<br>
 
 
==Vertex-Shader:==
 
==Vertex-Shader:==
<br>
 
Die Berechnug für das Licht des einfachen Beispieles ist hier im Vetex-Shader.<br>
 
 
<syntaxhighlight lang="glsl">#version 330
 
<syntaxhighlight lang="glsl">#version 330
 
#define PI 3.1415926535897932384626433832795
 
  
 
layout (location = 0) in vec3 inPos;    // Vertex-Koordinaten
 
layout (location = 0) in vec3 inPos;    // Vertex-Koordinaten
Zeile 77: Zeile 22:
 
vec3 LightPos = vec3(1.0, 0.0, 0.0);
 
vec3 LightPos = vec3(1.0, 0.0, 0.0);
  
float angele(vec3 p, vec3 q){
+
float angeleClamp(vec3 p, vec3 q){
 
   vec3  r1 = normalize(p);    // Vektoren normalisieren, so das die Länge des Vektors immer 1.0 ist.
 
   vec3  r1 = normalize(p);    // Vektoren normalisieren, so das die Länge des Vektors immer 1.0 ist.
 
   vec3  r2 = normalize(q);
 
   vec3  r2 = normalize(q);
Zeile 88: Zeile 33:
 
   vec3 Normal = mat3(Matrix) * inNormal;
 
   vec3 Normal = mat3(Matrix) * inNormal;
  
   float col = angele(LightPos, Normal);
+
   float col = angeleClamp(LightPos, Normal);
  
 
   gl_Position = Matrix * vec4(inPos, 1.0);
 
   gl_Position = Matrix * vec4(inPos, 1.0);
Zeile 95: Zeile 40:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
<br><br>
 
<br><br>
 
 
==Fragment-Shader==
 
==Fragment-Shader==
 
<syntaxhighlight lang="glsl">#version 330
 
<syntaxhighlight lang="glsl">#version 330

Version vom 21. Dezember 2017, 00:12 Uhr

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

Beleuchtung - Einfache Beleuchtung mit Clamp

Einleitung

Im ersten Beispiel wurde die Beleuchung mit Acos und Pi berechnet.
Für dies gibt es in GLSL eine fertige Funktion clamp.
Auserdem wird mit clamp berücksichtig, wen der Einstrahlwinkel < 0° ist, das dann kein Liche auf das Objekt kommt.

Der einzige Unterschied zu vorherigem Beispiel ist im Shader-Code.




Hier sieht man, das anstelle von arcos und Pi, clamp verwendet wurde.

Vertex-Shader:

#version 330

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

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

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

vec3 LightPos = vec3(1.0, 0.0, 0.0);

float angeleClamp(vec3 p, vec3 q){
  vec3  r1 = normalize(p);     // Vektoren normalisieren, so das die Länge des Vektors immer 1.0 ist.
  vec3  r2 = normalize(q);
  float d  = dot(r1, r2);      // Skalarprodukt aus beiden Vektoren berechnen.
  return clamp(d, 0.0, 1.0);
}

void main(void)
{
  vec3 Normal = mat3(Matrix) * inNormal;

  float col = angeleClamp(LightPos, Normal);

  gl_Position = Matrix * vec4(inPos, 1.0);
  Color = vec4(col, col, col, 0.0);
}



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