Kapitel 9: Visualisierungstechniken

Vom exakten aber datenintensiven BRDF-Modell zum approximierenden Phong'schen Reflexionsmodell (ambient + diffus + spekular + optional emissiv), physikalisch hergeleitet (Reflexionsgesetz, Absorption, Rauheit, Lambertsches Kosinusgesetz), plus Shading-Verfahren (Flat/Gouraud/Phong), Normal Mapping, Lichtquellen und die konkrete GLSL-Umsetzung. Kernthema der Klausur.

Überblick

Dieses Kapitel behandelt, wie das Aussehen (appearance) eines Objektes berechnet und dargestellt wird. Drei Faktoren bestimmen das Aussehen:

  1. Position und Orientierung des Betrachters (viewer) relativ zum beleuchteten Objekt.
  2. Position, Orientierung und Typ der Lichtquelle (light source).
  3. Oberflächenmaterial (surface material) des Objektes.

Roter Faden:

  • Die BRDF beschreibt Reflexion exakt, ist aber zu datenintensiv zum Speichern.
  • Beleuchtungs-/Reflexionsmodelle approximieren die BRDF durch einfache mathematische Funktionen -> das Phong'sche Reflexionsmodell.
  • Physikalische Herleitung der Terme (Reflexionsgesetz, Absorption, Rauheit, Lambert).
  • Shading-Verfahren (Flat/Gouraud/Phong) unterscheiden sich in der Granularität der Normalen (Flächen-/Ecken-/Pixelnormalen).
  • Normal Mapping, Material als Texturen, Lichtquellentypen und die konkrete GLSL-Shader-Implementierung.

Hinweis (mögliche Unstimmigkeit): Das Klausur-Briefing nannte gluLookAt und depth test. Diese Themen kommen in Kapitel 9 laut Quellenextraktion NICHT vor (sie gehören zu Kamera-/Rasterisierungskapiteln). Aus diesem Kapitel prüfungsrelevant sind vor allem die GLSL/OpenGL-Shader und die Phong-Beleuchtung (beide unten ausführlich).

BRDF (Bidirectional Reflectance Distribution Function)

Die BRDF (bidirectional reflectance distribution function) beschreibt, wie viel des einfallenden Lichts in eine bestimmte Richtung reflektiert wird. Es ist eine 4D-Funktion: die Richtung des einfallenden Lichts ωi\omega_i und die Richtung des reflektierten Lichts ωo\omega_o, beide jeweils 2D in Kugelkoordinaten (spherical coordinates).

  • Nachteil: enorme Datenmengen.
  • Reale BRDFs werden mit einem Gonio-Reflektometer (gonioreflectometer) gemessen, das die Probe mit mehreren Bewegungsachsen aus verschiedenen Winkeln abtastet.

Raytracing liefert den physikalischen Kontext: Von der Kamera wird durch die Bildebene (image plane) ein Sehstrahl (view/eye ray) bis zum Objekt verfolgt; von dort geht ein Schattenstrahl (shadow ray) zur Lichtquelle, um Verschattung zu prüfen.

Motivation für Reflexionsmodelle

Die explizite Speicherung der BRDF für jede ein- und ausgehende Richtung ist zu speicherintensiv.

Worked Example (Speicherbedarf): Für nur 100×100100 \times 100 Richtungen benötigt EIN Material bereits ca. 1,2 GB. Deshalb sucht man eine einfache mathematische Funktion, die ähnliche Ergebnisse liefert. Solche Funktionen heißen Reflexionsmodelle bzw. Beleuchtungsmodelle (reflection / illumination model).

Phong'sches Reflexionsmodell (Überblick)

Nach Bui-Tuong Phong, "Illumination for Computer Generated Pictures" (Communications of the ACM, 1975). Die Lichtquelle wird als Punktlichtquelle (point light source) angenommen. Die in Richtung des Betrachters abgegebene Lichtintensität ist die Summe von drei Komponenten:

  1. Diffuse Reflexion (diffuse reflection)
  2. Ambiente Beleuchtung (ambient lighting)
  3. Spiegelnde / Spekulare Reflexion (specular reflection)

Optional erweitert um einen vierten Term: Emission (self-emission).

Physikalische Herleitung

Licht als elektromagnetische Wellen: Farbe entsteht durch die Wellenlänge (wavelength); sichtbares Licht liegt etwa zwischen 390 und 760 nm.

Reflexionsgesetz (law of reflection): Einfallswinkel = Ausfallswinkel; beide Winkel α\alpha werden zur Oberflächennormale n\vec{n} gemessen. Annahmen: Punktlichtquelle und reflektierende Oberfläche.

Absorption: Es werden nicht alle Wellenlängen reflektiert. Dadurch ändert sich die Farbe des reflektierten Lichts (reflektiert z.B. eine Fläche nur grün, absorbiert sie den Rest).

Rauheit / Mikrogeometrie (roughness / microgeometry): Bei nicht ideal spiegelnden Oberflächen streut die Mikrogeometrie das Licht. Das reflektierte Licht nimmt mit zunehmender Abweichung vom Reflexionswinkel α\alpha ab (Reflexionskeule / lobe um die ideale Reflexionsrichtung).

Lambertsches Kosinusgesetz

Für perfekt diffus reflektierendes Material sieht die Oberfläche aus allen Richtungen gleich hell aus. Die Intensität ist direkt proportional zum Kosinus des Winkels zwischen Normale und Lichtvektor.

Begründung (zwei Interpretationen desselben Effekts):

  • Die beleuchtete Fläche nimmt mit dem Neigungswinkel zu -> die gleiche Photonenanzahl verteilt sich auf eine größere Fläche -> die Fläche wird dunkler.
  • Alternativ: die projizierte Fläche (projected area) nimmt mit dem Neigungswinkel ab.
Aproj=cosαAA_{proj} = \cos\alpha \cdot A
  • AprojA_{proj}: projizierte (wirksam beleuchtete) Fläche
  • AA: tatsächliche Oberflächenfläche
  • α\alpha: Winkel zwischen Oberflächennormale und Lichtvektor

Typischer Fehler: Die Begründung ist NICHT "es kommt weniger Licht an", sondern die gleiche Photonenzahl trifft auf eine größere bzw. projizierte Fläche (cosαA\cos\alpha \cdot A).

Diffuse Reflexion

Die diffuse Reflexion hängt ab von: Lichtfarbe, Materialfarbe und dem Winkel α\alpha zwischen der Oberflächennormale und dem Lichtaustrittsvektor (dem Vektor zur Lichtquelle). Farben werden komponentenweise (component-wise, Hadamard-Produkt) multipliziert.

Komponentenweise Formulierung (RGB):

(MrMgMb)(LrLgLb)cosα\begin{pmatrix} M_r \\ M_g \\ M_b \end{pmatrix} \cdot \begin{pmatrix} L_r \\ L_g \\ L_b \end{pmatrix} \cdot \cos\alpha
  • Mr,Mg,MbM_r, M_g, M_b: Materialfarbe (rot/grün/blau)
  • Lr,Lg,LbL_r, L_g, L_b: Lichtfarbe (rot/grün/blau)
  • cosα\cos\alpha: Lambert-Faktor
  • Der Punkt zwischen den Farbvektoren ist die komponentenweise Multiplikation, kein Skalarprodukt.

Diffuses Reflexionsmodell (Summe über alle nn Lichtquellen):

Lo=i=1nMdLicosαL_o = \sum_{i=1}^{n} M_d \cdot L_i \cdot \cos\alpha
  • LoL_o: resultierende Farbe (outgoing radiance)
  • MdM_d: diffuses Material (Materialfarbe)
  • LiL_i: Lichtfarbe der ii-ten Lichtquelle
  • α\alpha: Winkel zwischen Oberflächennormale und Lichtaustrittsvektor
  • Die Summe läuft über jede Lichtquelle.

Skalarprodukt als Grundlage für cos alpha

Das cosα\cos\alpha wird rechnerisch über das Skalarprodukt (dot product) bestimmt:

ab=abcosα=axbx+ayby+azbz\vec{a}\circ\vec{b} = |\vec{a}| \cdot |\vec{b}| \cdot \cos\alpha = a_x b_x + a_y b_y + a_z b_z

Sind beide Vektoren normiert, vereinfacht sich das zu:

wenn a=1 und b=1    ab=cosα\text{wenn } |\vec{a}| = 1 \text{ und } |\vec{b}| = 1 \;\Rightarrow\; \vec{a}\circ\vec{b} = \cos\alpha
  • a,b\vec{a}, \vec{b}: die beiden Vektoren (im Shading: Normale NN und Lichtvektor LL)
  • a,b|\vec{a}|, |\vec{b}|: ihre Längen (Beträge)
  • α\alpha: eingeschlossener Winkel

Deshalb müssen NN und LL im Shader normalisiert werden, damit dot(N,L) direkt cosα\cos\alpha liefert.

Spekulare Reflexion

Die spekulare (spiegelnde) Reflexion erzeugt das spekulare Glanzlicht (specular highlight). Sie hängt ab von:

  • Lichtfarbe
  • Materialfarbe (kann von der diffusen Materialfarbe abweichen, ist oft weiß)
  • Winkel β\beta zwischen dem Sichtvektor und dem reflektierten Lichtvektor
  • Glanzfaktor / Shininess kk

Die Vektoren und Winkel im Überblick

Für die Beleuchtungsberechnung an einem Oberflächenpunkt braucht man vier Vektoren (alle als Einheitsvektoren):

  • NN: Oberflächennormale (surface normal), senkrecht zur Fläche.
  • LL: Lichtvektor, zeigt vom Oberflächenpunkt zur Lichtquelle.
  • RR: reflektierter Lichtvektor, Spiegelung von LL an NN.
  • VV: Sichtvektor (view direction), zeigt vom Oberflächenpunkt zur Kamera.

Die zwei zentralen Winkel:

  • α\alpha = Winkel zwischen NN und LL -> steuert die diffuse Reflexion (cosα=NL\cos\alpha = N \circ L).
  • β\beta = Winkel zwischen RR und VV -> steuert die spekulare Reflexion (cosβ=RV\cos\beta = R \circ V).

Spekulare Reflexion, komponentenweise:

(MrMgMb)(LrLgLb)coskβ\begin{pmatrix} M_r \\ M_g \\ M_b \end{pmatrix} \cdot \begin{pmatrix} L_r \\ L_g \\ L_b \end{pmatrix} \cdot \cos^{k}\beta
  • Mr,Mg,MbM_r, M_g, M_b: spekulare Materialfarbe
  • Lr,Lg,LbL_r, L_g, L_b: Lichtfarbe
  • β\beta: Winkel zwischen Sichtvektor VV und reflektiertem Lichtvektor RR
  • kk: Shininess (Glanzfaktor)
  • coskβ\cos^{k}\beta: Potenzierung mit kk macht das Highlight schmaler

Shininess k

Der Exponent kk parametrisiert die spiegelnde Reflexion:

  • Hohe Shininess -> kleinere, härtere Highlights (Eindruck eines "harten" Materials).
  • Niedrige Shininess -> großes, weiches Highlight.

Worked Example (Shininess-Reihe): Für k{5,20,45,100}k \in \{5, 20, 45, 100\} wird das Glanzlicht mit steigendem kk zunehmend kleiner und härter: k=5k=5 ergibt ein großes, weiches Highlight, k=100k=100 ein kleines, hartes.

Diffuses + spekulares Modell

Kombiniert man beide Terme innerhalb der Summe über die Lichtquellen:

Lo=i=1n(Mdcosα+Mscoskβ)LiL_o = \sum_{i=1}^{n} \left( M_d \cdot \cos\alpha + M_s \cdot \cos^{k}\beta \right) \cdot L_i
  • LoL_o: resultierende Farbe
  • MdM_d: diffuses Material
  • MsM_s: spekulares Material
  • α\alpha: Winkel zwischen NN und LL (diffus)
  • β\beta: Winkel zwischen RR und VV (spekular)
  • kk: Shininess
  • LiL_i: Lichtfarbe der ii-ten Lichtquelle

Ambiente Beleuchtung

Die ambiente Beleuchtung (ambient lighting) imitiert grob die indirekte Beleuchtung, also Licht, das von anderen Oberflächen reflektiert wird. Ohne Ambient bleiben nicht direkt beleuchtete Bereiche komplett schwarz. Ambient ist richtungsunabhängig (kein cos\cos-Faktor).

Vollständiges Phong'sches Reflexionsmodell

Lo=MdLa+i=1n(Mdcosα+Mscoskβ)LiL_o = M_d \cdot L_a + \sum_{i=1}^{n} \left( M_d \cdot \cos\alpha + M_s \cdot \cos^{k}\beta \right) \cdot L_i
  • LoL_o: resultierende Farbe in Richtung des Betrachters
  • MdLaM_d \cdot L_a: ambienter Term, steht außerhalb der Summe (wird einmal global addiert)
  • MdM_d: diffuses Material
  • LaL_a: globale ambiente Lichtfarbe
  • cosα=NL\cos\alpha = N \circ L: diffuser Lambert-Faktor
  • MsM_s: spekulares Material
  • coskβ\cos^{k}\beta mit β\beta zwischen RR und VV: spekularer Faktor
  • kk: Shininess
  • LiL_i: Lichtfarbe der ii-ten Lichtquelle
  • Summe: über alle nn Lichtquellen

Worked Example (Wirkung des Ambient-Terms): Ohne Ambient (nur diffus + spekular) ist die abgewandte Schattenseite eines Objekts komplett schwarz. Mit Ambient (MdLaM_d \cdot L_a) wird die Schattenseite gleichmäßig aufgehellt.

Emissive Oberflächen (Phong + Emission)

Selbstleuchtende Oberflächen tragen einen zusätzlichen Term MeM_e bei, der unabhängig von externen Lichtquellen ist:

Lo=Me+MdLa+i=1n(Mdcosα+Mscoskβ)LiL_o = M_e + M_d \cdot L_a + \sum_{i=1}^{n} \left( M_d \cdot \cos\alpha + M_s \cdot \cos^{k}\beta \right) \cdot L_i
  • MeM_e: emissiver Term (selbstleuchtend)
  • alle übrigen Symbole wie oben

Transformation der Normalen (Normalmatrix)

Nach einer nicht-uniformen Modelltransformation ist eine einfach mittransformierte Normale falsch: sie steht nicht mehr senkrecht auf der transformierten Fläche.

Zahlenbeispiel für die falsche (naive) Transformation mit der Modellmatrix bei Skalierung um Faktor 2 in x-Richtung:

n=(2000010000100001)(1100)=(2100)(Falsche Normale!)\vec{n}' = \begin{pmatrix} 2&0&0&0\\0&1&0&0\\0&0&1&0\\0&0&0&1 \end{pmatrix}\begin{pmatrix}1\\1\\0\\0\end{pmatrix} = \begin{pmatrix}2\\1\\0\\0\end{pmatrix} \quad(\text{Falsche Normale!})

Korrektheitsbedingung: die Normale muss senkrecht auf der transformierten Fläche bleiben, d.h. das Skalarprodukt aus transformierter Normale und transformiertem Flächenvektor bleibt null:

(Mn)(Mp)=0(M' \cdot \vec{n}) \circ (M \cdot \mathbf{p}) = 0

Über np=np\vec{n}\circ\mathbf{p} = \vec{n}^\top \cdot \mathbf{p}, I=M1M\mathbf{I} = M^{-1}\cdot M und (AB)=BA(A\cdot B)^\top = B^\top \cdot A^\top folgt:

np=((M1)n)(Mp)\vec{n}\circ\mathbf{p} = \left((M^{-1})^\top \cdot \vec{n}\right) \circ (M \cdot \mathbf{p})

Ergebnis: die Normale wird korrekt mit der Normalmatrix

M=(M1)M' = (M^{-1})^\top

(inverse transponierte Matrix) transformiert.

  • MM: Modelltransformation (bzw. viewMatrix * modelMatrix)
  • MM': Normalmatrix
  • n\vec{n}: Normale, p\mathbf{p}: Flächen-/Tangentenvektor
  • I\mathbf{I}: Identitätsmatrix
I=(1000010000100001)I = \begin{pmatrix} 1&0&0&0\\0&1&0&0\\0&0&1&0\\0&0&0&1 \end{pmatrix}

Hinweis: Die Herleitung der Normalmatrix ist laut Vorlesung ausdrücklich "Nicht klausurrelevant!" markiert. Die praktische Anwendung transpose(inverse(viewMatrix * modelMatrix)) erscheint dagegen im Shader-Code und ist klausurrelevant.

Weitere Reflexionsmodelle

Über Phong hinaus (nur zur Einordnung):

  • Ward (1992): isotrope und anisotrope BRDF (z.B. Metall, poliertes Holz).
  • LaFortune (1993): komplexe Reflexionseigenschaften, Retro-Reflexion.
  • Cook-Torrance (1982): physikalisch basierte Mikrofacetten (microfacets) mit Fresnel-Term und Abschattungsfaktor (shadowing-masking).

Shading-Verfahren

Ohne Normalen ist keine Beleuchtungsberechnung möglich. Die drei Verfahren unterscheiden sich in der Granularität der Normalen:

  • Flächennormalen (face normals): eine Normale pro Fläche, steht senkrecht auf der Fläche.
  • Eckennormalen (vertex normals): stehen senkrecht auf der Tangentialebene (NICHT auf der Fläche); berechnet durch Interpolation der Flächennormalen der benachbarten Flächen.
  • Pixelnormalen (per-pixel normals): für jeden Pixel eine eigene Normale.

Flat Shading

Für jede Fläche gibt es genau eine Normale -> jede Facette erhält eine einheitliche Beleuchtung / nur eine Farbe.

  • Vorteil: sehr einfach und schnell.
  • Nachteil: bei gekrümmten Oberflächen oft schlechte, facettierte Qualität.

Gouraud Shading

Beleuchtungsberechnung pro Eckpunkt -> pro Dreieck drei Farben; die Farben der Pixel innerhalb des Dreiecks werden durch bilineare Interpolation ermittelt.

  • Vorteil: optische Glättung ohne Geometrieänderung.
  • Nachteil: kaschiert Kanten, die nicht zur Kontur gehören; Glanzlichter innerhalb eines Dreiecks können verloren gehen.

Worked Example (Grenze von Gouraud): Trifft ein Glanzlicht die Mitte eines Dreiecks, geht es verloren, weil die Beleuchtung nur an den Ecken berechnet wird. Erst mit sehr feiner Tessellierung (Reihe 2 -> 8 -> 18 -> 50 -> 200 -> 3200 Dreiecke) wird das Highlight korrekt sichtbar. Das zeigt die Kosten-/Qualitätsabwägung von Gouraud.

Phong Shading

Beleuchtungsberechnung pro Pixel/Fragment; für jeden Pixel wird eine Normale benötigt (aus Eckennormalen interpoliert oder aus einer Normal Map).

  • Vorteil: korrekte Glanzlichter und gutes visuelles Ergebnis ohne zusätzliche Tessellierung.
  • Nachteil: teuer (Normale pro Pixel interpolieren).

Wichtig (typische Falle): Phong Shading \neq Phong's Reflexionsmodell. Das Reflexionsmodell beschreibt, was berechnet wird (ambient + diffus + spekular). Shading beschreibt, wo bzw. wie oft (pro Fläche / pro Vertex / pro Pixel). Man kann das Phong-Reflexionsmodell mit Flat-, Gouraud- oder Phong-Shading auswerten.

Normal Mapping

Baut auf Phong Shading auf. Ziel: Simulation von Unebenheiten (Bumps) durch reine Anpassung der Oberflächennormalen - die Geometrie bleibt unverändert (flach).

  • Normalen werden pro Pixel als RGB-Farben in einer Textur gespeichert (typisch bläulich-violett).
  • Grenze: Kippfiguren (ambiguous / reversible figures) wie der Necker-Würfel oder "junges Mädchen oder alte Frau"; der wahrgenommene Eindruck kann kippen.

Worked Example (Klausur WS 16/17, Phong-Shading-Querschnitte): Aus eingezeichneten Pixel-/Flächennormalen soll der visuelle Eindruck abgeleitet werden. Musterlösung:

  1. Normalen alle gerade nach oben -> "Geometrie erscheint eben".
  2. Normalen nach innen gekippt -> "Geometrie hat Schlaglöcher".
  3. Normalen gleichmäßig geneigt -> "Geometrie bildet eine Treppe". Sehr wahrscheinlicher Aufgabentyp.

Materialbeschreibung als Textur

Jede Materialeigenschaft kann in einer eigenen Textur gespeichert werden: Diffus, Ambient, Spiegelnd/Spekular, Emissiv, Normalen-/Tiefenkarte.

  • Vorteil: entkoppelt Materialeigenschaften von den Geometriedaten.
  • Nachteil: evtl. erhöhter Speicherbedarf.

Beispiel (Teekanne): eine Spekular-Maske in Smiley-Form erzeugt Glanzlicht nur an den Smiley-Pixeln; grüne Emissiv-Punkte leuchten auch ohne externe Beleuchtung.

Lichtquellen

  • Gerichtete Lichtquelle (directional light): unendlich weit entfernt, parallel einfallende Strahlen.
  • Punktlichtquelle (point light): lokalisierter Punkt strahlt in alle Richtungen; unterschiedliche Einfallswinkel auf einer ebenen Fläche.
  • Spotlichtquelle (spotlight): Licht nur innerhalb eines bestimmten Winkels um eine angegebene Richtung; je weiter von der Achse entfernt, desto schwächer.
  • Lichtabschwächung (light attenuation): Die Intensität nimmt mit der Entfernung ab (die Kurve fällt von 1 gegen 0).

Beispielprogramm: GLSL-Beleuchtungsshader

Per-Vertex vs. Per-Fragment

Die blickabhängige Beleuchtungsberechnung sollte im Fragment-Shader erfolgen: Per-Fragment liefert scharfe, korrekte Highlights, während Per-Vertex sie durch die Interpolation verschmiert.

Basis-Shader: Ohne Beleuchtung

// Vertex Shader
#version 330
layout(location = 0) in vec3 vertex;
layout(location = 1) in vec3 vertex_color;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projMatrix;

out vec3 colorVS;

void main() {
    gl_Position = projMatrix * viewMatrix * modelMatrix * vec4(vertex, 1.0);
    colorVS = vertex_color;
}
// Fragment Shader
#version 330
in vec3 colorVS;
out vec4 color;
void main() {
    color = vec4(colorVS, 1.0);
}

Reihenfolge der Matrizen: proj * view * model * vertex (von rechts nach links angewendet).

Diffuser Term

// Vertex Shader
[...]
layout(location = ...) in vec3 vertex_normal;
uniform vec3 lightPos;
out vec3 normal, lightDir;

void main() {
    [...]
    // Normale in den View Space transformieren //
    vec4 n = vec4(vertex_normal, 0.0);                              // w=0: Richtungsvektor
    mat4 normalMat = transpose(inverse(viewMatrix * modelMatrix));  // Normalmatrix
    normal = (normalMat * n).xyz;

    // Lichtrichtung im View Space //
    vec4 lp = vec4(viewMatrix * vec4(lightPos, 1.0));              // lightPos in view space
    vec4 P  = vec4(viewMatrix * modelMatrix * vec4(vertex, 1.0));  // Vertexpos in view space
    lightDir = (lp - P).xyz;                                       // Richtung P -> Licht
}
// Fragment Shader
[...]
in vec3 normal, lightDir;
uniform vec3 lightColor;

void main() {
    [...]
    // alles Nötige normalisieren //
    vec3 N = normalize(normal);
    vec3 L = normalize(lightDir);

    // diffuse component //
    float cosa = max(0.0, dot(N,L));            // cos(alpha), abgeschnitten bei 0
    vec3 diffuseTerm = colorVS * lightColor;    // komponentenweise
    color = vec4(diffuseTerm * cosa, 1.0);
}

Entspricht MdLicosαM_d \cdot L_i \cdot \cos\alpha. Das max(0.0, ...) verhindert negative Beleuchtung (Licht von der Rückseite).

Interpolation der Normalen

Da es weniger Vertices als Fragmente gibt, werden die Normalen zwischen den Vertices interpoliert. Die interpolierten Vektoren sind nicht mehr normalisiert. Deshalb muss normalize() erneut im Fragment-Shader aufgerufen werden, nicht schon im Vertex-Shader.

Spekularer Term

// Vertex Shader
[...]
uniform vec3 lightPos;
out vec3 Normal, LightDir, viewDir;

void main() {
    [...]
    // specular term //
    viewDir = -P.xyz;   // Blickrichtung = negative Vertexposition im View Space
}

Frage/Antwort: "Warum ist die Blickrichtung die negative Vertexposition im View Space? -> Weil sich die Kamera im View Space im Ursprung befindet!"

// Fragment Shader
[...]
in vec3 normal, lightDir, viewDir;
uniform vec3 matSpecular;
uniform float matShininess;

void main() {
    [...]
    // specular component //
    vec3 V = normalize(viewDir);
    vec3 R = normalize(reflect(-L, N));          // reflektierter Lichtvektor

    float cosBeta  = max(0.0, dot(R, V));        // cos(beta)
    float cosBetak = pow(cosBeta, matShininess); // cos^k(beta)

    vec3 specularTerm = matSpecular * lightColor;
    color += vec4(specularTerm * cosBetak, 1.0); // additiv zum diffusen Term
}

Entspricht MsLicoskβM_s \cdot L_i \cdot \cos^{k}\beta. Wichtig: reflect(-L, N), weil das GLSL-Builtin reflect den einfallenden Vektor erwartet (LL zeigt zur Lichtquelle, also L-L).

Ambienter Term

// Vertex Shader
[...]
uniform vec3 lightPos;
out vec3 normal, lightDir;
void main() {
    [...]
}
// Fragment Shader
[...]
in vec3 normal, lightDir;
uniform vec3 lightColor;

void main() {
    [...]
    // ambient component //
    float ambientStrength = 0.2;
    vec3 ambientColor = colorVS;   // koennte auch eine globale Ambient-Farbe sein
    vec3 ambientTerm  = ambientColor * lightColor * ambientStrength;

    color += vec4(ambientTerm, 1.0);  // additiv
}

Ambient wird konstant addiert (unabhängig von NN/LL, kein Winkel); hier mit ambientStrength = 0.2.

Worked Example (kompletter Phong-Shader): Im Fragment-Shader werden die Terme schrittweise aufsummiert: color = diffus; dann color += spekular; dann color += ambient; (Per-Fragment). So "wächst" die Teekanne von der schwarzen Silhouette (ohne Beleuchtung) über diffus und + spekular (Glanzlicht) bis + ambient (aufgehellte Schattenseite).

Prüfungsrelevanz

  • Phong-Beleuchtung (alle Terme + vollständige Formel): sicher beherrschen inkl. Bedeutung von Md,Ms,Me,Li,La,α,β,kM_d, M_s, M_e, L_i, L_a, \alpha, \beta, k und der vier Vektoren N,L,R,VN, L, R, V.
  • GLSL/OpenGL-Shader: Struktur von Vertex-/Fragment-Shader, #version 330, layout(location=...), uniform/in/out, gl_Position = proj*view*model*vec4(vertex,1.0).
  • Shading-Verfahren unterscheiden (Flat/Gouraud/Phong) und mit der Granularität der Normalen (Flächen-/Ecken-/Pixelnormalen) verknüpfen.
  • Phong-Shading-Querschnitts-Aufgabe (Altklausur WS 16/17) - sehr wahrscheinlicher Aufgabentyp.
  • Warum Per-Fragment und warum erneut normalisieren im Fragment-Shader.
  • Lambertsches Kosinusgesetz und seine Begründung (cosαA\cos\alpha \cdot A).

Typische Fehler

  • Phong-Shading mit Phong's Reflexionsmodell verwechseln. Reflexionsmodell = was (ambient+diffus+spekular); Shading = wo/wie oft (pro Fläche/Vertex/Pixel).
  • Normale nach Modelltransformation naiv mit MM transformieren statt mit (M1)(M^{-1})^\top (falsch bei nicht-uniformer Skalierung).
  • cosα\cos\alpha negativ zulassen: im Shader max(0.0, dot(N,L)) nicht vergessen (sonst "negatives" Licht von der Rückseite).
  • Normalisierung im Vertex-Shader statt Fragment-Shader: interpolierte Normalen sind keine Einheitsvektoren mehr -> normalize() gehört in den Fragment-Shader.
  • reflect(-L, N) mit falschem Vorzeichen: GLSL reflect erwartet den einfallenden Vektor; LL zeigt zur Lichtquelle, also L-L verwenden.
  • Blickrichtung falsch: im View Space ist die Kamera im Ursprung -> viewDir = -P.xyz.
  • Farben skalar statt komponentenweise multiplizieren (Material x Licht ist das Hadamard-Produkt).
  • Ambient mit cos\cos-Faktor versehen: Ambient ist richtungsunabhängig (MdLaM_d \cdot L_a, kein Winkel).
  • Gouraud + kleines Glanzlicht in Flächenmitte: geht ohne feine Tessellierung verloren; Phong Shading löst das.
  • Lambert-Begründung verwechseln: nicht "weniger Licht", sondern gleiche Photonenzahl auf größere/projizierte Fläche (cosαA\cos\alpha \cdot A).

Glossar

DeutschEnglish
Aussehenappearance
Betrachterviewer
Lichtquellelight source
Oberflächenmaterialsurface material
BRDFbidirectional reflectance distribution function
Kugelkoordinatenspherical coordinates
Gonio-Reflektometergonioreflectometer
Reflexionsmodell / Beleuchtungsmodellreflection / illumination model
Phong'sches ReflexionsmodellPhong reflection model
Raytracingray tracing
Sehstrahlview / eye ray
Schattenstrahlshadow ray
Bildebeneimage plane
Reflexionsgesetzlaw of reflection
Oberflächennormalesurface normal
Absorptionabsorption
Wellenlängewavelength
Rauheit / Mikrogeometrieroughness / microgeometry
Lambertsches KosinusgesetzLambert's cosine law
projizierte Flächeprojected area
diffuse Reflexiondiffuse reflection
spekulare / spiegelnde Reflexionspecular reflection
Glanzlichtspecular highlight
Shininess / Glanzfaktorshininess
ambiente Beleuchtungambient lighting
Emissionemissive term
Skalarproduktdot product
komponentenweise Multiplikationcomponent-wise (Hadamard) multiplication
Normalmatrixnormal matrix
Identitätsmatrixidentity matrix
Mikrofacetten / Fresnel / Abschattungsfaktormicrofacets / Fresnel / shadowing-masking
Shadingshading
Flächennormaleface normal
Eckennormalevertex normal
Pixelnormaleper-pixel normal
Tangentialebenetangent plane
Flat Shadingflat shading
Gouraud ShadingGouraud shading
Phong ShadingPhong shading
bilineare Interpolationbilinear interpolation
Tessellierungtessellation
Normal Mappingnormal mapping
Unebenheit / Bumpbump
Kippfigurambiguous / reversible figure
Material als Texturtexture-based material
gerichtete Lichtquelledirectional light
Punktlichtquellepoint light
Spotlichtquellespotlight
Lichtabschwächunglight attenuation
Vertex Shader / Fragment Shadervertex shader / fragment shader
Per-Vertex vs. Per-Fragmentper-vertex vs. per-fragment lighting
View Space / Kamerakoordinatensystemview space