Lazarus - OpenGL 3.3 Tutorial - Shader - Erste Bewegung
Inhaltsverzeichnis
Shader - Erste Bewegung
Einleitung
Ohne Bewegung ist OpenGL langweilig.
Hier werden dem Shader ein X- und ein Y-Wert übergeben. Diese Werte werden mit einem Timer verändert.
Damit die Änderung auch sichtbar wird, wird DrawScene danach manuell ausgelöst.
Hinzugekommen sind die Deklarationen der IDs für die X- und Y-Koordinaten.
TrianglePos bestimmt die Bewegung und Richtung des Dreiecks.
var
X_ID, Y_ID: GLint; // ID für X und Y.
Color_ID: GLint;
TrianglePos: record
x, y: GLfloat; // Position
xr, yr: boolean; // Richtung
end;
Den Timer immer erst nach dem Initialisieren starten!
Im Objektinspektor muss dessen Eigenschaft Enable=(False) sein!
Ansonsten ist ein SIGSEV vorprogrammiert, da Shader aktviert werden, die es noch gar nicht gibt.
procedure TForm1.FormCreate(Sender: TObject);
begin
ogc := TContext.Create(Self);
ogc.OnPaint := @ogcDrawScene;
CreateScene;
InitScene;
Timer1.Enabled := True; // Timer starten
end;
Dieser Code wurde um zwei UniformLocation-Zeilen erweitert.
Diese ermitteln die IDs, wo sich x und y im Shader befinden.
procedure TForm1.CreateScene;
begin
Shader := TShader.Create([FileToStr('Vertexshader.glsl'), FileToStr('Fragmentshader.glsl')]);
Shader.UseProgram;
Color_ID := Shader.UniformLocation('Color');
X_ID := Shader.UniformLocation('x'); // Ermittelt die ID von x.
Y_ID := Shader.UniformLocation('y'); // Ermittelt die ID von y.
Hier werden die Uniform-Variablen x und y dem Shader übergeben.
Beim Dreieck sind das die Positions-Koordinaten.
Beim Quad ist es 0, 0 und somit bleibt das Quadrat stehen.
Mit glUniform1f(... kann man einen Float-Wert dem Shader übergeben.
procedure TForm1.ogcDrawScene(Sender: TObject);
begin
glClear(GL_COLOR_BUFFER_BIT);
Shader.UseProgram;
// Zeichne Dreieck
glUniform3f(Color_ID, 1.0, 1.0, 0.0); // Gelb
with TrianglePos do begin // Beim Dreieck, die xy-Werte.
glUniform1f(X_ID, x);
glUniform1f(Y_ID, y);
end;
glBindVertexArray(VBTriangle.VAO);
glDrawArrays(GL_TRIANGLES, 0, Length(Triangle) * 3);
// Zeichne Quadrat
glUniform3f(Color_ID, 1.0, 0.0, 0.0); // Rot
glUniform1f(X_ID, 0.0); // Beim Quadrat keine Verschiebung, daher 0.0, 0.0 .
glUniform1f(Y_ID, 0.0);
glBindVertexArray(VBQuad.VAO);
glDrawArrays(GL_TRIANGLES, 0, Length(Quad) * 3);
Den Timer vor dem Freigeben anhalten.
procedure TForm1.FormDestroy(Sender: TObject);
begin
Timer1.Enabled := False;
Im Timer wird die Position berechnet, so dass sich das Dreieck bewegt.
Anschliessend wird neu gezeichnet.
procedure TForm1.Timer1Timer(Sender: TObject);
const
stepx: GLfloat = 0.010;
stepy: GLfloat = 0.0133;
begin
with TrianglePos do begin
if xr then begin
x := x - stepx;
if x < -0.5 then begin
xr := False;
end;
end else begin
x := x + stepx;
if x > 0.5 then begin
xr := True;
end;
end;
if yr then begin
y := y - stepy;
if y < -1.0 then begin
yr := False;
end;
end else begin
y := y + stepy;
if y > 0.3 then begin
yr := True;
end;
end;
end;
ogcDrawScene(Sender); // Neu zeichnen
end;
Vertex-Shader:
Hier sind die Uniform-Variablen x und y hinzugekommen.
Diese werden im Vertex-Shader deklariert. Bewegungen kommen immer in diesen Shader.
#version 330
layout (location = 10) in vec3 inPos; // Vertex-Koordinaten
uniform float x; // Richtung von Uniform
uniform float y;
void main(void)
{
vec3 pos;
pos.x = inPos.x + x;
pos.y = inPos.y + y;
pos.z = inPos.z;
gl_Position = vec4(pos, 1.0);
}
Fragment-Shader:
#version 330
uniform vec3 Color; // Farbe von Uniform
out vec4 outColor; // ausgegebene Farbe
void main(void)
{
outColor = vec4(Color, 1.0);
}
Autor: Mathias
Siehe auch
- Übersichtseite Lazarus - OpenGL 3.3 Tutorial