Computergrafik

Rendering-Pipeline
und Shader

Hintergrund

Was sind Vertices? (Vertex)

  • Stützpunkte eines Grafikobjekts
    (z.B. Linie, Dreieck, Polygon)
  • unsere Eingabe-Daten

 

Was sind Shader-Programme?

  • Früher: Gouraud-Shading
  • Heute: Programm, das durch Download auf GPU bestimmte feste Teile* ersetzt
  • Shader-Cores sind Hardware-Einheiten
    auf der GPU, wo Shader-Programme laufen

* fest bezieht sich hier auf die sog. Fixed Function Pipeline

Rendering-Pipeline (stark vereinfacht)

Bild: Gemeinfrei

Rendering-Pipeline (vereinfacht)

Vertex
Shader

Fragment
Shader

Rasterizer

Tests &
Blending

🖥️

Eingabe: Vertices

Ausgabe: Bild

programmierbare Funktion

feste Funktion

{...}
{...}

Vertices

Transformierte Vertices

Fragmente

Finalisierte
Fragmente

Pixel

Hinweis: Wir werden diese Pipeline später erweitern.

Vertex-Shader

  • jeder Eingabe-Vertex wird durch diesen individuell verarbeitet
  • berechnet die Position im Bildschirmraum (gl_Position)
  • Führt Transformationen durch
    • Modell-, View-, Projektion-Transformationen 🔜 
  • Übergibt Daten (z. B. Farbe) an den Fragment-Shader
  • Läuft vor der Rasterisierung 
    • bestimmt die Geometrie (Anordnung) auf dem Bildschirm

Fragment-Shader

  • Läuft für jeden Pixel (sog. Fragment), der ausgegeben wird

  • Bestimmt die endgültige Pixel-Farbe 

    • gl_FragColor 

  • Nutzt interpolierte Daten vom Vertex-Shader (Eingabe)

  • Berechnet Effekte pro Pixel, u.a.:

    • Licht, Texturen, Schatten, Nebel

  • Ist meist der rechenintensivste Teil der Grafik-Pipeline

🎯 Unser Fokus im Praktikum!

Einführung in GLSL

OpenGL Shading Language

< /  >

🎨

🖥️

< / >

GLSL-Syntax 

  • Syntax ist an Programmiersprache C angelehnt
  • Typische Konstrukte verfügbar​:
    • Bedingungen: if, if/else, switch
    • Schleifen: for
      • while ist häufig deaktiviert
    • Abbruch: return, break, continue

GLSL-Syntax (Beispiele)

void main() {
    float x = 0.3;

    if (x > 0.5) {
        gl_FragColor = vec4(1.0);
    } else {
        gl_FragColor = vec4(0.0);
    }
}
void main() {
    float sum = 0.0;

    for (int i = 0; i < 5; i++) {
        sum += 0.2;
    }

    gl_FragColor = vec4(sum);
}

Schleifen werden in der Regel vor Kompilierung "ausgerollt", d.h. Anzahl Durchläufe sollte vorher bekannt sein

GLSL-Datentypen (Auswahl)

Datentyp Beschreibung
vec2, vec3, vec4 float-Vektoren
ivec2, ivec3, ivec4 integer-Vektoren
bvec2, bvec3, bvec4 boolean-Vektoren
mat2 2x2 Matrix
mat3 3x3 Matrix
mat4 4x4 Matrix

Standard-Datentypen: float,  boolean,  int, uint

Einführung in GLSL

Beispiele

< /  >

🚀

< / >

Farbe

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

Testen!

Farbverlauf

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    vec2 uv = gl_FragCoord.xy / u_resolution;
    gl_FragColor = vec4(uv.x, 0.0, 0.0, 1.0);
}

Testen!

2D-Farbverlauf

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    vec2 uv = gl_FragCoord.xy / u_resolution;
    gl_FragColor = vec4(uv.x, uv.y, 0.5, 1.0);
}

Testen!

Pulsierende Farben

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    float t = sin(u_time) * 0.5 + 0.5;
    gl_FragColor = vec4(t, 0.0, 1.0 - t, 1.0);
}

Testen!

Kreis

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    vec2 uv = gl_FragCoord.xy / u_resolution - 0.5;
    float d = length(uv);
    float c = step(d, 0.2);
    gl_FragColor = vec4(vec3(c), 0.800);
}

Testen!

Kreis (mit weichen Übergängen)

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    vec2 uv = gl_FragCoord.xy / u_resolution - 0.5;
    float d = length(uv);
    float c = smoothstep(0.368, 0.19, d);
    gl_FragColor = vec4(vec3(c), 1.0);
}

Testen!

Rechteck

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    vec2 uv = gl_FragCoord.xy / u_resolution;
    float c = step(0.3, uv.x) * step(uv.x, 0.7) *
              step(0.3, uv.y) * step(uv.y, 0.7);
    gl_FragColor = vec4(vec3(c), 1.0);
}

Testen!

Schachbrett

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    vec2 uv = floor(gl_FragCoord.xy / 20.0);
    float c = mod(uv.x + uv.y, 2.0);
    gl_FragColor = vec4(vec3(c), 1.0);
}

Testen!

Wellenbewegungen

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    vec2 uv = gl_FragCoord.xy / u_resolution;
    float y = sin(uv.x * 10.0 + u_time);
    float c = step(uv.y, 0.5 + y * 0.1);
    gl_FragColor = vec4(vec3(c), 1.0);
}

Testen!

GLSL-Playground

CG2 Rendering Pipeline und Shader

By blackbill

CG2 Rendering Pipeline und Shader

  • 37