02 - Shader
14 - Punkte verschieden darstellen
Bis jetzt wurde alles mit kompletten Dreiecken gerendert und gezeichnet. Es gibt aber noch zwei andere Varianten um Dreiecke zu rendern.
Dies wurde beim Zeichnen mit glDrawArrays(GL_TRIANGLES, ... veranlasst. Diese Version wird in der Paraxis am meisten angewendet.
Man kann die Dreiecke auch als Streifen hintereinander rendern, dies gerschieht mit glDrawArrays(GL_TRIANGLES_STRIP, ....
Oder wie ein Wedel, dabei ist der erste Vektor die Mitte, und der Rest die Eckpunkte. Dies geschieht dann mit glDrawArrays(GL_TRIANGLES_FAN, ....
Das schreiben in die Grafikkarte, ist bei allen Varianten gleich, der Unterschied ist legendlich beim Zeichenen mit glDrawArrays(....
Die Deklaration der Vektor-Koordianten Konstanten, zur Vereinfachung habe ich nur 2D-Vektoren genommen. Natürlich können diese auch 3D sein.
var
// Normale Dreiecke ( Gelb )
Triangles: array of TVertex2f;
TrianglesSize: array of GLfloat;
Hier werden die Daten in die Grafikkarte geschrieben.
Es hat nichts besonderes.
procedure TForm1.InitScene;
begin
glClearColor(0.6, 0.6, 0.4, 1.0); // Hintergrundfarbe
// Daten für GL_TRIANGLE
glBindVertexArray(VBTriangle.VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBTriangle.VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(TVertex2f) * Length(Triangles), Pointer(Triangles), GL_STATIC_DRAW);
glEnableVertexAttribArray(10);
glVertexAttribPointer(10, 2, GL_FLOAT, False, 0, nil);
// Daten für GL_TRIANGLE
glBindVertexArray(VBTriangle.VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBTriangle.VBO_Size);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * Length(TrianglesSize), Pointer(TrianglesSize), GL_STATIC_DRAW);
glEnableVertexAttribArray(11);
glVertexAttribPointer(11, 1, GL_FLOAT, False, 0, nil);
end;
Bei glDrawArrays(... ist der erste Parameter das wichtigste, hier wird angegeben, wie die Vektor-Koordinaten gezeichnet werden.
procedure TForm1.ogcDrawScene(Sender: TObject);
const
ofs = 0.4;
begin
glEnable(GL_PROGRAM_POINT_SIZE);
glClear(GL_COLOR_BUFFER_BIT);
Shader.UseProgram;
glBindVertexArray(VBTriangle.VAO);
// Zeichne GL_TRIANGLE
glUniform1i(PointTyp_ID, 0);
glUniform3f(Color_ID, 1.0, 1.0, 0.0); // Gelb
glUniform1f(X_ID, -ofs);
glUniform1f(Y_ID, -ofs);
glDrawArrays(GL_POINTS, 0, Length(Triangles));
// Zeichne GL_TRIANGLE_STRIP
glUniform1i(PointTyp_ID, 1);
glUniform3f(Color_ID, 1.0, 0.0, 0.0); // Rot
glUniform1f(X_ID, ofs);
glUniform1f(Y_ID, -ofs);
glDrawArrays(GL_POINTS, 0, Length(Triangles));
// Zeichne GL_TRIANGLE_FAN
glUniform1i(PointTyp_ID, 2);
glUniform3f(Color_ID, 0.0, 1.0, 0.0); // Grün
glUniform1f(X_ID, ofs);
glUniform1f(Y_ID, ofs);
glDrawArrays(GL_POINTS, 0, Length(Triangles));
// Zeichne GL_TRIANGLE_FAN
glUniform1i(PointTyp_ID, 3);
glUniform3f(Color_ID, 0.0, 0.0, 1.0); // Blau
glUniform1f(X_ID, -ofs);
glUniform1f(Y_ID, ofs);
glDrawArrays(GL_POINTS, 0, Length(Triangles));
Vertex-Shader:
Da die Koordinaten nur als 2D gespeichert sind, wird im Vertex-Shader der Z-Wert auf 0.0 gesetzt.
#version 330
layout (location = 10) in vec2 inPos; // Vertex-Koordinaten in 2D
layout (location = 11) in float inSize; // Vertex-Koordinaten in 2D
uniform float x; // Richtung von Uniform
uniform float y;
void main(void)
{
vec2 pos = inPos;
pos.x = pos.x + x;
pos.y = pos.y + y;
gl_PointSize = inSize;
gl_Position = vec4(pos, 0.0, 1.0); // Der zweiter Parameter (Z) auf 0.0
}
Fragment-Shader:
#version 330
uniform vec3 Color ; // Farbe von Uniform
out vec4 outColor; // ausgegebene Farbe
uniform int PointTyp;
void main(void)
{
vec2 p = gl_PointCoord * 2.0 - vec2(1.0);
float r = sqrt(dot(p, p));
float theta = atan(p.y, p.x);
switch (PointTyp){
case 0: if(dot(gl_PointCoord - 0.5, gl_PointCoord - 0.5) > 0.25)
discard;
else
outColor = vec4(Color, 1.0);
break;
case 1: if(dot(p, p) > cos(theta * 5))
discard;
else
outColor = vec4(Color, 1.0);
break;
case 2: if(dot(p, p) > r || dot(p, p) < r * 0.75)
discard;
else
outColor = vec4(Color, 1.0);
break;
case 3: if(dot(p, p) > 5.0 / cos(theta - 20 * r))
discard;
else
outColor = vec4(Color, 1.0);
break;
default: discard;
}
}