Lazarus - OpenGL 3.3 Tutorial - Instancing - Instancen nur in einer Array
Aus DGL Wiki
Version vom 28. Juli 2018, 18:09 Uhr von Mathias (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „200px<br><br> =Instancing - Instancen nur in einer Array = == Einleitun…“)
Inhaltsverzeichnis
Instancing - Instancen nur in einer Array
Einleitung
Vorher hatte es für jedes Instance-Attribut eine eigene Array gehabt.
Jetzt sind alle Attribute in einer Array, dies macht den Code einiges übersichtlicher.
Dafür ist die Übergabe mit glVertexAttribPointer(... ein weniig komplizierter.
Siehe Vertex-Puffer - Nur eine Array.
Die Deklaration der Array. Es ist nur noch eine Array.
type
TData = record
Scale: GLfloat;
Matrix: TMatrix;
Color: TVector3f;
end;
var
Data: array[0..InstanceCount - 1] of TData;
Das es ein wenig einfacher wird, habe ich ofs verwendet.
procedure TForm1.InitScene;
var
ofs, i: integer;
begin
glClearColor(0.6, 0.6, 0.4, 1.0); // Hintergrundfarbe
glBindVertexArray(VBQuad.VAO);
// --- Normale Vektordaten
// Daten für Vektoren
glBindBuffer(GL_ARRAY_BUFFER, VBQuad.VBO.Vertex);
glBufferData(GL_ARRAY_BUFFER, sizeof(Quad), @Quad, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, False, 0, nil);
// --- Instancen
ofs := 0;
// Instance Size
glBindBuffer(GL_ARRAY_BUFFER, VBQuad.VBO.I_Size);
glBufferData(GL_ARRAY_BUFFER, SizeOf(Data), @Data, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 1, GL_FLOAT, False, SizeOf(TData), nil);
glVertexAttribDivisor(1, 1);
Inc(ofs, SizeOf(GLfloat));
// Instance Matrix
glBindBuffer(GL_ARRAY_BUFFER, VBQuad.VBO.I_Matrix);
glBufferData(GL_ARRAY_BUFFER, SizeOf(Data), nil, GL_STATIC_DRAW); // Nur Speicher reservieren
for i := 0 to 3 do begin
glEnableVertexAttribArray(i + 2);
glVertexAttribPointer(i + 2, 4, GL_FLOAT, False, SizeOf(TData), Pointer(ofs));
glVertexAttribDivisor(i + 2, 1);
Inc(ofs, SizeOf(TVector4f));
end;
// Instance Color
glBindBuffer(GL_ARRAY_BUFFER, VBQuad.VBO.I_Color);
glBufferData(GL_ARRAY_BUFFER, SizeOf(Data), @Data, GL_STATIC_DRAW);
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 3, GL_FLOAT, False, SizeOf(TData), Pointer(ofs));
glVertexAttribDivisor(6, 1);
end;
An der Zeichenroutine ändert sich nichts.
procedure TForm1.ogcDrawScene(Sender: TObject);
begin
glClear(GL_COLOR_BUFFER_BIT);
Shader.UseProgram;
glBindBuffer(GL_ARRAY_BUFFER, VBQuad.VBO.I_Matrix);
glBufferSubData(GL_ARRAY_BUFFER, 0, SizeOf(Data), @Data);
glBindVertexArray(VBQuad.VAO);
glDrawArraysInstanced(GL_TRIANGLES, 0, Length(Quad) * 3, InstanceCount);
ogc.SwapBuffers;
end;
Matrizen neu berechnen.
procedure TForm1.Timer1Timer(Sender: TObject);
var
i: integer;
begin
for i := 0 to Length(Data) - 1 do begin
Data[i].Matrix.RotateC(0.02);
end;
glBindVertexArray(VBQuad.VAO);
ogcDrawScene(Sender); // Neu zeichnen
end;
Vertex-Shader:
Am Shader hat sich nicht geändert.
#version 330
#define Instance_Count 200
// Vektor-Daten
layout (location = 0) in vec2 inPos;
// Instancen
layout (location = 1) in float Size;
layout (location = 2) in mat4 mat;
layout (location = 6) in vec3 Color;
out vec3 col;
void main(void)
{
gl_Position = mat * vec4((inPos * Size), 0.0, 1.0);
col = Color;
}
Fragment-Shader:
#version 330
out vec4 outColor; // ausgegebene Farbe
in vec3 col;
void main(void)
{
outColor = vec4(col, 1.0);
}
Autor: Mathias
Siehe auch
- Übersichtseite Lazarus - OpenGL 3.3 Tutorial