Native Standard-Codesequenz
← Einfache Standard-Codesequenz | ● | 2D Texturen im Shader →
Annahme: die Framework-Funktionen werden nicht verwendet, aber es gibt eine Initialisierungs-Funktion und eine Render-Funktion, die für jeden Frame aufgerufen wird.
Der folgende Code dient nur zur Erläuterung, was hinter den Kulissen passiert. Speziell im Praktikum benutzen wir aus offensichtlichen Gründen lieber die Framework-Funktionen!!!
Shader
Gespeichert in getrennten String-Variablen.
- Vertex-Shader
uniform mat4 mvp; // ModelViewProjection-Matrix
attribute vec4 vert; // Der zu transformierende Vertex
attribute vec4 col; // Ein Per-Vertex Attribut
varying vec4 c; // Um Farbe an Fragment-Shader zu übergeben
void main ()
{
gl_Position = mvp * vert;
c = col;
}
- Fragment-Shader
varying vec4 c; // *Exakt* gleich wie im Vertex-Shader
void main ()
{
gl_FragColor = c; // Interpolation der pro Vertex angegebenen Farbe
}
VBO
Daten für den VBO bereithalten - hier im Beispiel interleaved.
- Der Stride ist für beide Attribute
sizeof(float)*(3+4)
- es sind 3 vertex und 4 color Werte im Array, jeweils imfloat
Format. - Der Offset für die Vertices ist natürlich 0
- Der Offset für die Farbinformation ist
sizeof(float)*3
- da die 3 Werte des ersten Vertex übersprungen werden müssen!
+0.75, +0.75, 0.0, // vertex
1, 0, 0, 1, // color
+0.75, -0.75, 0.0, // vertex
0, 1, 0, 1, // color
-0.75, -0.75, 0.0, // vertex
0, 0, 1, 1 // color
};
Global
Variablen anlegen für:
- Shader-Programm und VBO
GLuint program, vbo;
- Locations für Uniforms
GLint uniform_mvp;
- Konstanten für Attribute
enum { ATTRIB_VERT, ATTRIB_COL };
Init-Funktion
1) Erzeugen des Shader-Programms, inkl. Attribute
GLuint vs = glCreateShader (GL_VERTEX_SHADER);
glShaderSource (vs, 1, &vertex_shader, NULL);
glCompileShader (vs);
// Erzeuge und compiliere Fragment Shader
GLuint fs = glCreateShader (GL_FRAGMENT_SHADER);
glShaderSource (fs, 1, &fragment_shader, NULL);
glCompileShader (fs);
// Erzeuge Programm
program = glCreateProgram();
glAttachShader (program, vs);
glAttachShader (program, fs);
// Location der Attribute setzen - VOR dem Linken!
glBindAttribLocation (program, ATTRIB_VERT, "vert");
glBindAttribLocation (program, ATTRIB_COL, "col");
lglGetError();
// Linke Programm
glLinkProgram (program);
// Aktiviere Programm
glUseProgram (program);
2) Nachschlagen sämtlicher Uniforms
if (uniform_mvp < 0)
lglError ("uniform 'mvp' nicht gefunden");
3) VAO und VBO erstellen und mit Daten füllen
glGenVertexArrays (1, &vao);
glBindVertexArray (vao);
glGenBuffers (1, &vbo);
glBindBuffer (GL_ARRAY_BUFFER, vbo);
glBufferData (GL_ARRAY_BUFFER, sizeof(vecData), vecData, GL_STATIC_DRAW);
4) Weitere Initialisierungen
glEnable (GL_DEPTH_TEST);
Render-Funktion
1) Bildschirm löschen
2) Uniforme Attribute setzen
Die Syntax ist hier relativ eklig, gerade bei Matrizen… Die MVP-Matrix muss hier selbstständig berechnet werden, da wir ja das Framework nicht nutzen!
glUniformMatrix4fv (uniform_mvp, 1, GL_FALSE, (const float *)(mvp));
4) Endlich: VBO selektieren, konfigurieren und zeichnen
Die Syntax ist noch ekliger, da eine Funktion (glVertexAttribPointer) nicht für den ursprünglichen Zweck der Funktion benutzt (missbraucht) wurde. Deshalb muss der Offset (eigentlich ein Ganzzahlwert) als Pointer übergeben werden…
glEnableVertexAttribArray (ATTRIB_VERT);
glVertexAttribPointer (ATTRIB_VERT, 3, GL_FLOAT, GL_FALSE,
sizeof(float) * (3+4),
NULL);
glEnableVertexAttribArray (ATTRIB_COL);
glVertexAttribPointer (ATTRIB_COL, 4, GL_FLOAT, GL_FALSE,
sizeof(float) * (3+4),
(void*) (sizeof(float) * 3));
glDrawArrays (GL_TRIANGLES, 0, 3);
← Einfache Standard-Codesequenz | ● | 2D Texturen im Shader →