Probeklausur 2 - Visual Computing

Zweite Übungsklausur (mock exam) zum Kurs "Visual Computing" (HS Darmstadt). Sie ist an Struktur, Themenmix, Schwierigkeit und Punktgewichtung der Original-Klausur WS 2025/2026 angelehnt, enthält aber ausschliesslich neue Aufgaben (weder aus der Original-Klausur noch aus Probeklausur 1 übernommen). Alle Lösungen sind ausklappbar mit vollem Rechenweg, Begründung und Kapitelbezug. Zum Vergleich: Klausur WS2025 (Lösungen) und Probeklausur 1.

Hinweise zur Klausur: Dauer 90 Minuten. Hilfsmittel: ein nicht-programmierbarer Taschenrechner (non-programmable calculator) und ein beschriebenes DIN-A4-Blatt. Insgesamt 100 Punkte.


1. Aufgabe: RGB und HSV Farbmodelle (13 Punkte)

Teil a (6 P): Rechnen Sie die folgenden drei Farben aus dem RGB-Modell (Wertebereich [0,1][0,1]) in das HSV-Modell um. Geben Sie jeweils HH (Hue = Farbton), SS (Saturation = Sättigung) und VV (Value = Hellwert) an und zeigen Sie den Rechenweg.

Farbe(R,G,B)(R, G, B)
Farbe 1(1,0, 0,5, 0,0)(1{,}0,\ 0{,}5,\ 0{,}0)
Farbe 2(0,4, 0,4, 0,4)(0{,}4,\ 0{,}4,\ 0{,}4)
Farbe 3(0,2, 0,8, 0,2)(0{,}2,\ 0{,}8,\ 0{,}2)

Teil b (7 P): Eine Grafik zeigt auf weissem Hintergrund drei gefüllte Quadrate: links Cyan (0,1,1)(0,1,1), mittig Magenta (1,0,1)(1,0,1), rechts Gelb (1,1,0)(1,1,0). Die Grafik wird einmal in ihre RGB-Kanäle und einmal in ihre HSV-Kanäle zerlegt (je drei Graustufenbilder, Leseregel: weiss = Maximalwert, schwarz = Minimalwert). Vervollständigen Sie beide Tabellen mit den Kanalwerten und begründen Sie, an welchem Merkmal man RGB von HSV am schnellsten unterscheidet.

Lösung anzeigen

Teil a - Umrechnung RGB nach HSV. Formeln (Kapitel 10): V=max(r,g,b)V = \max(r,g,b),   S=1min(r,g,b)max(r,g,b)\;S = 1 - \dfrac{\min(r,g,b)}{\max(r,g,b)} (falls max=0\max = 0, dann S=0S = 0),   H\;H = Farbwinkel auf dem Farbkreis (00^\circ Rot, 6060^\circ Gelb, 120120^\circ Grün, 180180^\circ Cyan, 240240^\circ Blau, 300300^\circ Magenta).

Hue-Formel (falls benötigt), mit Δ=maxmin\Delta = \max - \min:

H=60{gbΔmod6max=rbrΔ+2max=grgΔ+4max=bH = 60^\circ \cdot \begin{cases} \dfrac{g-b}{\Delta} \bmod 6 & \max = r \\[4pt] \dfrac{b-r}{\Delta} + 2 & \max = g \\[4pt] \dfrac{r-g}{\Delta} + 4 & \max = b \end{cases}

Farbe 1 (1,0, 0,5, 0,0)(1{,}0,\ 0{,}5,\ 0{,}0) - Orange:

  • V=max(1,0, 0,5, 0,0)=1,0V = \max(1{,}0,\ 0{,}5,\ 0{,}0) = 1{,}0
  • min=0,0S=10,01,0=1,0\min = 0{,}0 \Rightarrow S = 1 - \dfrac{0{,}0}{1{,}0} = 1{,}0
  • max=r\max = r, also H=60gbΔ=600,50,01,00,0=600,5=30H = 60^\circ \cdot \dfrac{g-b}{\Delta} = 60^\circ \cdot \dfrac{0{,}5 - 0{,}0}{1{,}0 - 0{,}0} = 60^\circ \cdot 0{,}5 = 30^\circ (Orange liegt zwischen Rot und Gelb).
  • Ergebnis: [30, 1,0, 1,0]HSV[30^\circ,\ 1{,}0,\ 1{,}0]_{\text{HSV}}

Farbe 2 (0,4, 0,4, 0,4)(0{,}4,\ 0{,}4,\ 0{,}4) - Grauton:

  • V=0,4V = 0{,}4
  • min=max=0,4S=10,40,4=0\min = \max = 0{,}4 \Rightarrow S = 1 - \dfrac{0{,}4}{0{,}4} = 0
  • Wegen S=0S = 0 ist HH undefiniert (unbunt / achromatic).
  • Ergebnis: [undef, 0, 0,4]HSV[\text{undef},\ 0,\ 0{,}4]_{\text{HSV}}

Farbe 3 (0,2, 0,8, 0,2)(0{,}2,\ 0{,}8,\ 0{,}2) - entsättigtes Grün:

  • V=max=0,8V = \max = 0{,}8
  • min=0,2S=10,20,8=10,25=0,75\min = 0{,}2 \Rightarrow S = 1 - \dfrac{0{,}2}{0{,}8} = 1 - 0{,}25 = 0{,}75
  • max=g\max = g, also H=60(brΔ+2)=60(0,20,20,6+2)=602=120H = 60^\circ \cdot \left(\dfrac{b-r}{\Delta} + 2\right) = 60^\circ \cdot \left(\dfrac{0{,}2 - 0{,}2}{0{,}6} + 2\right) = 60^\circ \cdot 2 = 120^\circ (reines Grün, Rot- und Blauanteil gleich).
  • Ergebnis: [120, 0,75, 0,8]HSV[120^\circ,\ 0{,}75,\ 0{,}8]_{\text{HSV}}

Teil b - Kanalzerlegung.

RGB-Kanäle (weiss = 1, schwarz = 0):

RegionRGB
Hintergrund (weiss)111
Cyan011
Magenta101
Gelb110

HSV-Kanäle:

RegionHSV
Hintergrund (weiss)undef (0)01
Cyan180180^\circ11
Magenta300300^\circ11
Gelb6060^\circ11

Begründung (schnellste Unterscheidung): Entscheidend ist der Hintergrund (Weiss). In RGB ist Weiss in jedem Kanal der Maximalwert, also haben alle drei RGB-Kanalbilder einen hellen (weissen) Hintergrund. In HSV gilt für Weiss V=1V = 1 (weiss), aber S=0S = 0 (schwarz) und HH undefiniert (als schwarz dargestellt). Die HSV-Zerlegung zeigt also einen Kanal (VV) mit weissem Hintergrund und zwei (HH, SS) mit schwarzem Hintergrund. Faustregel: alle drei Hintergründe hell -> RGB; zwei Hintergründe dunkel -> HSV.

Kapitelbezug: Kapitel 10: Farbräume.

Typischer Fehler: VV als Mittelwert der drei Kanäle berechnen. VV ist das Maximum max(r,g,b)\max(r,g,b), nicht der Durchschnitt. Ausserdem bei den drei vollgesättigten Sekundärfarben (Cyan, Magenta, Gelb) ist V=1V = 1 und S=1S = 1; nur der Farbton HH (Winkel) unterscheidet sie.


2. Aufgabe: OpenGL Shader (19 Punkte)

Gegeben ist das folgende Shader-Paar:

// Vertex Shader
#version 330
layout(location = 0) in vec3 vertex;
layout(location = 1) in vec3 vertex_normal;
layout(location = 2) in vec3 vertex_color;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projMatrix;
out vec3 normalVS;
out vec3 colorVS;
void main() {
    gl_Position = projMatrix * viewMatrix * modelMatrix * vec4(vertex, 1.0);
    normalVS = vertex_normal;
    colorVS = vertex_color;
}
// Fragment Shader
#version 330
in vec3 normalVS;
in vec3 colorVS;
out vec4 color;
uniform vec3 lightDir;
void main() {
    float diff = max(dot(normalize(normalVS), normalize(lightDir)), 0.0);
    color = vec4(colorVS * diff, 1.0);
}

a (3 P): Worauf verweist der index in layout(location = index)? Welche drei Attribute werden hier gebunden? b (3 P): Was ist eine uniform Variable und welche Zugriffsrechte (read/write) hat sie im Shader? Nennen Sie die uniforms dieses Programms. c (3 P): Erklären Sie den Unterschied zwischen in und out. Was passiert mit einem out-Wert des Vertex-Shaders (z.B. normalVS) auf dem Weg zum Fragment-Shader? d (4 P): Füllen Sie den Lückentext aus (Begriffe: Position, normalisiert, interpoliert, Skalarprodukt, Alpha, drei). e (3 P): Erklären Sie die Parameter von gluLookAt(ax,ay,az, bx,by,bz, cx,cy,cz). f (3 P): Was bewirken glEnable(GL_DEPTH_TEST), glDepthFunc(GL_LESS) und glClearDepth(1.0)?

Lückentext (zu d): Der Vertex-Shader liest drei ______ (a)-dimensionale Attribute pro Vertex und berechnet mit den drei Matrizen die finale Vertex-______ (b) in gl_Position. Die Normale und die Farbe werden unverändert als out weitergereicht und bei der Rasterisierung über das Dreieck ______ (c). Der Fragment-Shader ______ (d) Normale und Lichtrichtung, bildet mit dot(...) ihr ______ (e) und multipliziert die Farbe damit. Zuletzt wird der Farbe ein ______ (f)-Wert von 1.0 hinzugefügt.

Lösung anzeigen

a) Der index gibt die Vertex-Attribut-Position (vertex attribute index) an, aus der das Attribut im VAO/VBO gelesen wird. Er entspricht dem index in glVertexAttribPointer(index, ...) bzw. glEnableVertexAttribArray(index). Hier: 00 = Position (vertex), 11 = Normale (vertex_normal), 22 = Farbe (vertex_color).

b) Eine uniform Variable ist eine globale, für alle Vertices bzw. Fragmente eines Draw-Calls konstante Eingabe, die von der Anwendung (CPU) per glUniform* / glUniformMatrix*fv gesetzt und per Variablenname adressiert wird. Im Shader ist sie READ-ONLY (nur lesbar). Uniforms hier: modelMatrix, viewMatrix, projMatrix (Vertex-Shader) und lightDir (Fragment-Shader).

c) in ist eine Eingabevariable (read-only): im Vertex-Shader die Vertex-Attribute, im Fragment-Shader die Ausgabe der vorherigen Stufe. out ist eine Ausgabevariable, die an die nächste Pipeline-Stufe weitergereicht wird. Ein out-Wert des Vertex-Shaders (hier normalVS, colorVS) wird bei der Rasterisierung automatisch über das Primitiv interpoliert (perspektivkorrekt), bevor er als gleichnamige in-Variable im Fragment-Shader ankommt. Kopplung über gleichen Namen und gleichen Typ.

d) Lückentext: Der Vertex-Shader liest drei drei-dimensionale Attribute pro Vertex und berechnet mit den drei Matrizen die finale Vertex-Position in gl_Position. Die Normale und die Farbe werden unverändert als out weitergereicht und bei der Rasterisierung über das Dreieck interpoliert. Der Fragment-Shader normalisiert Normale und Lichtrichtung, bildet mit dot(...) ihr Skalarprodukt und multipliziert die Farbe damit. Zuletzt wird der Farbe ein Alpha-Wert von 1.0 hinzugefügt.

(Begründung diff: dot(N^,L^)=cosα\texttt{dot}(\hat{N}, \hat{L}) = \cos\alpha ist der Lambert-Term, das max(..., 0.0) verhindert negative Helligkeit auf der lichtabgewandten Seite.)

e) gluLookAt definiert die View-Matrix über drei Vektoren:

  • a = Augpunkt / Kameraposition (eye) - wo die Kamera steht.
  • b = Blickpunkt / Zielpunkt (center) - wohin die Kamera schaut.
  • c = Up-Vektor (up) - welche Richtung "oben" ist.

f)

  1. glEnable(GL_DEPTH_TEST) schaltet den Tiefentest (z-Buffer-Test) ein.
  2. glDepthFunc(GL_LESS) legt fest, dass ein Fragment nur gezeichnet wird, wenn sein Tiefenwert kleiner (also näher an der Kamera) ist als der bereits gespeicherte.
  3. glClearDepth(1.0) setzt den Wert, mit dem der Tiefenpuffer beim Löschen gefüllt wird (1,01{,}0 = maximale, weiteste Entfernung), damit jedes reale Fragment den Test zunächst besteht.

Kapitelbezug: Kapitel 6: Shaderprogrammierung, Kapitel 7: Kameras, Kapitel 8: Rendering-Pipeline.

Tipp: normalize(...) vor dem dot-Produkt ist wichtig: Nach der Interpolation ist normalVS in der Regel nicht mehr genau die Einheitslänge 11; nur normierte Vektoren liefern mit dot wirklich cosα\cos\alpha.


3. Aufgabe: Affine Transformationen (16 Punkte)

Teil a (6 P): Eine 2D-Szene "Schneemann" (snowman) soll aus zwei Basiselementen aufgebaut werden: Kreis (Einheitskreis / unit circle, Radius 11, Zentrum Ursprung) und Dreieck (Basis von 1-1 bis 11 auf der x-Achse, Spitze bei (0,1)(0,1)). Zielszene:

  • Bauch (unterer Kreis): Kreis mit Radius 1,51{,}5, Zentrum im Ursprung (0,0)(0,0).
  • Kopf (oberer Kreis): Kreis mit Radius 0,70{,}7, Zentrum bei (0, 2,5)(0,\ 2{,}5).
  • Nase: ein kleines Dreieck, um 9090^\circ im Uhrzeigersinn gedreht (Spitze zeigt danach nach rechts), auf 20%20\% verkleinert, Zentrum bei (0,3, 2,5)(0{,}3,\ 2{,}5).

Geben Sie für jedes der drei Blätter (leaves) die nötigen Transformationen samt Parametern und in der richtigen Reihenfolge an. Erläutern Sie kurz die Vererbung (inheritance) im Szenegraphen. Skalierung (1, 1)(1,\ 1) ist unzulässig (keine Wirkung).

Teil b (10 P): Ein Punkt P=(2, 1)P = (2,\ 1) soll erst um 9090^\circ im Uhrzeigersinn (clockwise, also φ=90\varphi = -90^\circ) um den Ursprung gedreht und danach um t=(1, 5)\vec{t} = (1,\ 5) verschoben werden.

  1. Stellen Sie die Rotationsmatrix RR und die Translationsmatrix TT in homogenen Koordinaten (3×33\times3) auf.
  2. Berechnen Sie die kombinierte Matrix M=TRM = T \cdot R und wenden Sie sie auf PP an (mit Probe).
  3. Zeigen Sie, dass die umgekehrte Reihenfolge RTR \cdot T ein anderes Ergebnis liefert (Nicht-Kommutativität / non-commutativity).
Lösung anzeigen

Teil a - Transformationen pro Blatt (Basiselemente: Einheitskreis r=1r=1 und Standarddreieck):

  • Bauch: Einheitskreis (r=1r=1) auf r=1,5r=1{,}5 vergrössern, Zentrum bleibt im Ursprung -> nur Skalierung(1,5, 1,5)(1{,}5,\ 1{,}5).
  • Kopf: Einheitskreis auf r=0,7r=0{,}7 verkleinern und nach oben schieben -> erst Skalierung(0,7, 0,7)(0{,}7,\ 0{,}7), dann Translation(0, 2,5)(0,\ 2{,}5). Reihenfolge beachten: erst skalieren (um den Ursprung), dann verschieben, sonst würde der Abstand vom Ursprung mitskaliert.
  • Nase: Standarddreieck erst verkleinern -> Skalierung(0,2, 0,2)(0{,}2,\ 0{,}2), dann Rotation(90)(-90^\circ) (im Uhrzeigersinn, Spitze zeigt danach nach rechts), zuletzt Translation(0,3, 2,5)(0{,}3,\ 2{,}5). Also Reihenfolge: Skalierung, dann Rotation, dann Translation.

Vererbung: Im Szenegraphen erben Kind-Knoten (children) die Transformationen ihres Elternknotens (parent). Eine Transformation, die auf alle Teile wirken soll (z.B. den ganzen Schneemann drehen), notiert man einmal am Wurzelknoten Schneemann; sie wird mit den blattspezifischen Transformationen zur akkumulierten Matrix (accumulated matrix) verkettet. Bei Spaltenvektoren steht die Wurzel-Transformation dabei ganz links (wirkt als äusserste, zuletzt angewandte Transformation).

Teil b - homogene Transformation.

1. Matrizen aufstellen. Für φ=90\varphi = -90^\circ gilt cos(90)=0\cos(-90^\circ) = 0, sin(90)=1\sin(-90^\circ) = -1:

R=(cosφsinφ0sinφcosφ0001)=(010100001),T=(101015001)R = \begin{pmatrix} \cos\varphi & -\sin\varphi & 0 \\ \sin\varphi & \cos\varphi & 0 \\ 0 & 0 & 1 \end{pmatrix} = \begin{pmatrix} 0 & 1 & 0 \\ -1 & 0 & 0 \\ 0 & 0 & 1 \end{pmatrix}, \qquad T = \begin{pmatrix} 1 & 0 & 1 \\ 0 & 1 & 5 \\ 0 & 0 & 1 \end{pmatrix}

Kontrolle der Rotationswirkung: RR bildet (x,y)(x,y) auf (y, x)(y,\ -x) ab, das ist genau eine 9090^\circ-Drehung im Uhrzeigersinn.

2. Kombinierte Matrix M=TRM = T \cdot R. Zuerst rotieren, dann verschieben, also steht RR rechts (direkt am Punkt):

M=TR=(101015001)(010100001)=(011105001)M = T \cdot R = \begin{pmatrix} 1 & 0 & 1 \\ 0 & 1 & 5 \\ 0 & 0 & 1 \end{pmatrix}\begin{pmatrix} 0 & 1 & 0 \\ -1 & 0 & 0 \\ 0 & 0 & 1 \end{pmatrix} = \begin{pmatrix} 0 & 1 & 1 \\ -1 & 0 & 5 \\ 0 & 0 & 1 \end{pmatrix}

Anwendung auf P=(2, 1, 1)T\vec{P} = (2,\ 1,\ 1)^T:

MP=(011105001)(211)=(02+11+1112+01+511)=(231)M\,\vec{P} = \begin{pmatrix} 0 & 1 & 1 \\ -1 & 0 & 5 \\ 0 & 0 & 1 \end{pmatrix}\begin{pmatrix} 2 \\ 1 \\ 1 \end{pmatrix} = \begin{pmatrix} 0\cdot2 + 1\cdot1 + 1\cdot1 \\ -1\cdot2 + 0\cdot1 + 5\cdot1 \\ 1 \end{pmatrix} = \begin{pmatrix} 2 \\ 3 \\ 1 \end{pmatrix}

Also P=(2, 3)P' = (2,\ 3).

Probe (schrittweise): Rotation zuerst: (2,1)(2,1) um 9090^\circ im Uhrzeigersinn ergibt (y, x)=(1, 2)(y,\ -x) = (1,\ -2). Dann Translation +(1,5)+(1,5): (1+1, 2+5)=(2, 3)(1+1,\ -2+5) = (2,\ 3) ✓ - stimmt mit MPM\,\vec{P} überein.

3. Umgekehrte Reihenfolge RTR \cdot T:

RT=(010100001)(101015001)=(015101001)R \cdot T = \begin{pmatrix} 0 & 1 & 0 \\ -1 & 0 & 0 \\ 0 & 0 & 1 \end{pmatrix}\begin{pmatrix} 1 & 0 & 1 \\ 0 & 1 & 5 \\ 0 & 0 & 1 \end{pmatrix} = \begin{pmatrix} 0 & 1 & 5 \\ -1 & 0 & -1 \\ 0 & 0 & 1 \end{pmatrix} (RT)P=(015101001)(211)=(1+5211)=(631)(R\cdot T)\,\vec{P} = \begin{pmatrix} 0 & 1 & 5 \\ -1 & 0 & -1 \\ 0 & 0 & 1 \end{pmatrix}\begin{pmatrix} 2 \\ 1 \\ 1 \end{pmatrix} = \begin{pmatrix} 1 + 5 \\ -2 - 1 \\ 1 \end{pmatrix} = \begin{pmatrix} 6 \\ -3 \\ 1 \end{pmatrix}

Also P=(6, 3)(2, 3)P'' = (6,\ -3) \neq (2,\ 3). Die Matrixmultiplikation ist nicht kommutativ: TRRTT\cdot R \neq R\cdot T. Anschaulich: bei RTR\cdot T wird zuerst verschoben und dann der schon verschobene Punkt um den Ursprung gedreht.

Kapitelbezug: Kapitel 5: Transformationen (homogene Koordinaten, Rotationsmatrix, Szenegraph, Nicht-Kommutativität).

Typischer Fehler: Bei der Drehung im Uhrzeigersinn das Vorzeichen von sin\sin vergessen. Für φ=90\varphi = -90^\circ ist sinφ=1\sin\varphi = -1, deshalb landet die 1-1 unten links in RR (nicht oben rechts wie bei +90+90^\circ). Und: die zuerst anzuwendende Transformation steht bei Spaltenvektoren ganz rechts (direkt am Punkt).


4. Aufgabe: Beleuchtung nach Phong (16 Punkte)

An einem Oberflächenpunkt PP steht eine Punktlichtquelle (point light), eine Kamera blickt auf PP. Gerechnet wird einkanalig (single channel) auf einer Skala 00 bis 11.

Teil a (4 P): Nennen Sie die vier für das Phong-Reflexionsmodell nötigen (normierten) Vektoren an PP und geben Sie an, zwischen welchen Vektoren die Winkel α\alpha und β\beta gemessen werden.

Teil b (6 P): Berechnen Sie die Helligkeit der diffusen und der spekularen Reflexion an PP für α=45\alpha = 45^\circ, β=60\beta = 60^\circ und Glanzexponent (shininess) k=3k = 3. Alle Material- und Lichtkonstanten sind hier 11. Zeigen Sie den Rechenweg.

Teil c (6 P): Nun mit realistischen Konstanten: diffuses Material Md=0,8M_d = 0{,}8, spekulares Material Ms=0,5M_s = 0{,}5, Lichtfarbe Li=1,0L_i = 1{,}0, globales Ambient (ambient light) La=0,2L_a = 0{,}2. Berechnen Sie die Gesamthelligkeit an PP mit der vollständigen Phong-Formel (einkanalig). Was bewirkt ein grösserer Exponent kk?

Lösung anzeigen

Teil a - benötigte Vektoren (alle normiert) an PP:

  • N\vec{N} = Normale (normal) der Oberfläche.
  • L\vec{L} = Lichtvektor (light vector), zeigt von PP zur Lichtquelle.
  • R\vec{R} = Reflexionsvektor (reflection vector), Spiegelung von L\vec{L} an N\vec{N}.
  • V\vec{V} = Sicht-/Blickvektor (view vector), zeigt von PP zur Kamera.

Winkel: α\alpha liegt zwischen N\vec{N} und L\vec{L} (steuert die diffuse Reflexion, cosα=NL\cos\alpha = \vec{N}\circ\vec{L}); β\beta liegt zwischen R\vec{R} und V\vec{V} (steuert die spekulare Reflexion, cosβ=RV\cos\beta = \vec{R}\circ\vec{V}).

Teil b - diffuse und spekulare Helligkeit (Konstanten =1= 1):

Diffuse Reflexion (Lambert):

Idiff=cosα=cos45=220,707I_{diff} = \cos\alpha = \cos 45^\circ = \frac{\sqrt{2}}{2} \approx \mathbf{0{,}707}

Spekulare Reflexion (Phong):

Ispec=coskβ=cos3(60)I_{spec} = \cos^{k}\beta = \cos^{3}(60^\circ)

Rechenweg: cos60=0,5\cos 60^\circ = 0{,}5, also

cos3(60)=(0,5)3=18=0,125\cos^{3}(60^\circ) = (0{,}5)^3 = \frac{1}{8} = \mathbf{0{,}125}

Teil c - vollständige Phong-Formel (einkanalig, eine Lichtquelle):

I=MdLa+(Mdcosα+Mscoskβ)LiI = M_d \cdot L_a + \left(M_d \cdot \cos\alpha + M_s \cdot \cos^{k}\beta\right)\cdot L_i

Einsetzen mit cosα=0,707\cos\alpha = 0{,}707 und cos3β=0,125\cos^{3}\beta = 0{,}125:

I=0,80,2+(0,80,707+0,50,125)1,0I = 0{,}8 \cdot 0{,}2 + \left(0{,}8 \cdot 0{,}707 + 0{,}5 \cdot 0{,}125\right)\cdot 1{,}0 I=0,16+(0,5657+0,0625)=0,16+0,6282=0,788I = 0{,}16 + \left(0{,}5657 + 0{,}0625\right) = 0{,}16 + 0{,}6282 = \mathbf{0{,}788}

Die Gesamthelligkeit an PP beträgt also rund 0,79\mathbf{0{,}79} (ambienter Sockel 0,160{,}16, diffus 0,5660{,}566, spekular 0,0630{,}063).

Wirkung von kk: Ein grösserer Glanzexponent kk macht das spekulare Glanzlicht (highlight) kleiner und härter (schärferer, konzentrierterer Glanzpunkt), weil coskβ\cos^{k}\beta mit steigendem kk ausserhalb von β=0\beta = 0 schneller gegen null fällt. Kleines kk ergibt ein grosses, weiches Highlight (matte, glänzende Oberfläche vs. spiegelnde).

Kapitelbezug: Kapitel 9: Visualisierungstechniken (Phong-Reflexionsmodell).

Typischer Fehler: α\alpha und β\beta vertauschen (α\alpha misst N\vec{N} zu L\vec{L}, β\beta misst R\vec{R} zu V\vec{V}) oder den Exponenten kk fälschlich auf den diffusen Term anwenden. kk gehört ausschliesslich zum spekularen Term. Ausserdem: der ambiente Term MdLaM_d\cdot L_a steht ausserhalb der Summe und hat keinen cos\cos-Faktor.


5. Aufgabe: Farbinterpolation im Dreieck (10 Punkte)

Ein Dreieck hat die Vertices v1=(0,0)v_1 = (0,0) mit Farbe Rot [1,0,0][1,0,0], v2=(8,0)v_2 = (8,0) mit Farbe Grün [0,1,0][0,1,0] und v3=(0,4)v_3 = (0,4) mit Farbe Blau [0,0,1][0,0,1]. Gesucht ist der interpolierte RGB-Farbwert im Punkt p=(2, 1)p = (2,\ 1).

Teil 1 (4 P): Beschreiben Sie das Vorgehen (baryzentrische Interpolation / barycentric interpolation). Teil 2 (6 P): Berechnen Sie den Farbwert nachvollziehbar. Führen Sie die Probe w1+w2+w3=1w_1 + w_2 + w_3 = 1 durch.

Lösung anzeigen

Teil 1 - Vorgehen. Innerhalb eines Dreiecks werden die Vertexfarben über baryzentrische Gewichte (barycentric weights = Flächenverhältnisse) interpoliert. Für jeden Vertex ist das Gewicht der Anteil der gegenüberliegenden Teildreiecksfläche an der Gesamtfläche:

wi=AiAges,w1+w2+w3=1w_i = \frac{A_i}{A_{ges}}, \qquad w_1 + w_2 + w_3 = 1

Der Farbwert ist dann die gewichtete Summe c(p)=w1c1+w2c2+w3c3\vec{c}(p) = w_1\,\vec{c}_1 + w_2\,\vec{c}_2 + w_3\,\vec{c}_3. Die Dreiecksfläche berechnet man mit

A=12xa(ybyc)+xb(ycya)+xc(yayb).A = \tfrac12\,\bigl|x_a(y_b - y_c) + x_b(y_c - y_a) + x_c(y_a - y_b)\bigr|.

Teil 2 - Rechnung.

Gesamtfläche mit v1=(0,0)v_1=(0,0), v2=(8,0)v_2=(8,0), v3=(0,4)v_3=(0,4):

Ages=120(04)+8(40)+0(00)=1232=16A_{ges} = \tfrac12\,|\,0(0-4) + 8(4-0) + 0(0-0)\,| = \tfrac12 \cdot 32 = 16
  • A1=(p,v2,v3)A_1 = \triangle(p, v_2, v_3) mit p=(2,1)p=(2,1), v2=(8,0)v_2=(8,0), v3=(0,4)v_3=(0,4):
A1=122(04)+8(41)+0(10)=128+24=1216=8w1=816=12A_1 = \tfrac12\,|\,2(0-4) + 8(4-1) + 0(1-0)\,| = \tfrac12\,|-8 + 24| = \tfrac12\cdot 16 = 8 \Rightarrow w_1 = \tfrac{8}{16} = \tfrac12
  • A2=(v1,p,v3)A_2 = \triangle(v_1, p, v_3) mit v1=(0,0)v_1=(0,0), p=(2,1)p=(2,1), v3=(0,4)v_3=(0,4):
A2=120(14)+2(40)+0(01)=128=4w2=416=14A_2 = \tfrac12\,|\,0(1-4) + 2(4-0) + 0(0-1)\,| = \tfrac12\cdot 8 = 4 \Rightarrow w_2 = \tfrac{4}{16} = \tfrac14
  • A3=(v1,v2,p)A_3 = \triangle(v_1, v_2, p) mit v1=(0,0)v_1=(0,0), v2=(8,0)v_2=(8,0), p=(2,1)p=(2,1):
A3=120(01)+8(10)+2(00)=128=4w3=416=14A_3 = \tfrac12\,|\,0(0-1) + 8(1-0) + 2(0-0)\,| = \tfrac12\cdot 8 = 4 \Rightarrow w_3 = \tfrac{4}{16} = \tfrac14

Probe: 12+14+14=1\dfrac12 + \dfrac14 + \dfrac14 = 1

Farbwert:

c(p)=12[1,0,0]+14[0,1,0]+14[0,0,1]=[12, 14, 14]=[0,50, 0,25, 0,25]\vec{c}(p) = \tfrac12[1,0,0] + \tfrac14[0,1,0] + \tfrac14[0,0,1] = \left[\tfrac12,\ \tfrac14,\ \tfrac14\right] = [0{,}50,\ 0{,}25,\ 0{,}25]

Der Punkt liegt am nächsten an v1v_1 (Rot), daher überwiegt der Rotanteil (w1=12w_1 = \tfrac12).

Kapitelbezug: Kapitel 8: Rendering-Pipeline (lineare Farbinterpolation im Dreieck).

Tipp: Immer die Probe wi=1\sum w_i = 1 machen. Das Gewicht wiw_i gehört zur gegenüberliegenden Teilfläche AiA_i (nicht zu der Teilfläche, die den Vertex viv_i enthält). Liegt pp nahe an viv_i, muss wiw_i gross sein.


6. Aufgabe: Bildverarbeitung, lokale Operatoren (16 Punkte)

a (4 P): Was versteht man unter einer Faltung (convolution) in der Bildverarbeitung? Warum muss die Kernelgrösse (kernel size) aus ungeraden Zahlen (3×33\times3, 5×55\times5, ...) bestehen?

b (6 P): Wenden Sie den Laplace-Operator auf die folgende Rastergrafik an. Der Kernel lässt sich nur auf die inneren Pixel (inner pixels) anwenden; geben Sie die Ergebnismatrix mit Rechenweg an.

10101010
10508010
10805010
10101010

c (6 P): Berechnen Sie den Median für das folgende 3×33\times3-Fenster und vergleichen Sie ihn mit dem Mittelwert (mean). Was zeigt das Beispiel über Impulsrauschen (salt-and-pepper noise)?

606261
63564
626063
Lösung anzeigen

a - Faltung und ungerade Kernelgrösse. Eine Faltung legt einen Kernel (Filtermaske, Gewichtsmatrix) über jedes Pixel, multipliziert die überdeckten Grauwerte mit den zugehörigen Kernelgewichten und summiert sie zum neuen Wert des Zentralpixels auf. Der Kernel wird dabei über das ganze Bild geschoben (sliding window).

Ein ungerader Kernel (3×33\times3, 5×55\times5, ...) hat ein eindeutiges Zentrum (genau ein Mittelpixel). Nur so kann das Faltungsergebnis genau einem Ausgangspixel zugeordnet werden, und die Nachbarschaft ist symmetrisch um dieses Zentrum (kein halbpixel-Versatz / half-pixel shift). Bei gerader Kantenlänge läge das Zentrum zwischen vier Pixeln und das Ergebnis wäre nicht eindeutig positionierbar.

b - Laplace-Operator.

FL=(010141010),g(i,j)=4g(i,j)gobenguntenglinksgrechtsF_L = \begin{pmatrix} 0 & -1 & 0 \\ -1 & 4 & -1 \\ 0 & -1 & 0 \end{pmatrix}, \qquad g'(i,j) = 4\,g(i,j) - g_{\text{oben}} - g_{\text{unten}} - g_{\text{links}} - g_{\text{rechts}}

(Zentrum mit 44 gewichtet, die vier direkten Nachbarn mit 1-1.) Bei einem 3×33\times3-Kernel auf einem 4×44\times4-Bild bleiben die 2×22\times2 inneren Pixel. Die Grauwerte der inneren Pixel sind g(1,1)=50g(1,1)=50, g(1,2)=80g(1,2)=80, g(2,1)=80g(2,1)=80, g(2,2)=50g(2,2)=50 (Zeilen/Spalten ab 00 gezählt):

  • Pixel (1,1)=50(1,1) = 50: oben 1010, unten 8080, links 1010, rechts 8080
45010801080=200180=204\cdot50 - 10 - 80 - 10 - 80 = 200 - 180 = \mathbf{20}
  • Pixel (1,2)=80(1,2) = 80: oben 1010, unten 5050, links 5050, rechts 1010
48010505010=320120=2004\cdot80 - 10 - 50 - 50 - 10 = 320 - 120 = \mathbf{200}
  • Pixel (2,1)=80(2,1) = 80: oben 5050, unten 1010, links 1010, rechts 5050
48050101050=320120=2004\cdot80 - 50 - 10 - 10 - 50 = 320 - 120 = \mathbf{200}
  • Pixel (2,2)=50(2,2) = 50: oben 8080, unten 1010, links 8080, rechts 1010
45080108010=200180=204\cdot50 - 80 - 10 - 80 - 10 = 200 - 180 = \mathbf{20} Ergebnis=(2020020020)\text{Ergebnis} = \begin{pmatrix} 20 & 200 \\ 200 & 20 \end{pmatrix}

Die grossen Beträge (200200) markieren die hellen 8080-Pixel, an denen der Grauwertsprung (grey-level jump) gegenüber dem dunklen Rand am stärksten ist; die 5050-Pixel liegen je zwischen zwei 8080-Nachbarn und einem dunklen Rand und ergeben nur 2020.

c - Median vs. Mittelwert.

Die 9 Werte sortiert (sorted): 5, 60, 60, 61, 62, 62, 63, 63, 645,\ 60,\ 60,\ 61,\ 62,\ 62,\ 63,\ 63,\ 64.

Der Median ist der 5. Wert (g4g_4, der mittlere der 9 sortierten Werte): 62\mathbf{62}.

Der Mittelwert ist

60+62+61+63+5+64+62+60+639=500955,6\frac{60+62+61+63+5+64+62+60+63}{9} = \frac{500}{9} \approx 55{,}6

Aussage: Das Störpixel 55 (dunkles Impuls-/Pfefferrauschen, pepper noise) zieht den Mittelwert deutlich nach unten (56\approx 56, obwohl fast alle Nachbarn um 6161 liegen), während der Median mit 6262 dem tatsächlichen lokalen Grauwert entspricht und den Ausreisser (outlier) vollständig ignoriert. Der Median erzeugt zudem keine neuen Grauwerte (er wählt einen vorhandenen Wert), während der Mittelwert den neuen, im Original nicht vorkommenden Wert 56\approx 56 erzeugt. Für Salz-und-Pfeffer-Rauschen ist der Median klar überlegen.

Kapitelbezug: Kapitel 12: Bildverarbeitung - Lokale Operatoren.

Typischer Fehler: Beim Median den Durchschnitt statt des sortierten Mittelwerts bilden - der Median ist der Rang g4g_4, keine Rechnung. Beim Laplace das Randproblem übersehen: ein 3×33\times3-Kernel ohne Randbehandlung liefert aus einem 4×44\times4-Bild eine 2×22\times2-Ergebnismatrix.


7. Aufgabe (Zusatz): Grauwerttransformation und Projektion (10 Punkte)

Nach einer Faltung liegen die Pixelwerte im Intervall [6, 6][-6,\ 6]. Gesucht sind lineare Grauwerttransformationen (grey-level transformation) der Form g(i,j)=e(i,j)mult+addg'(i,j) = e(i,j)\cdot \text{mult} + \text{add}.

a (4 P): Bilden Sie [6, 6][-6,\ 6] auf den Grauwertbereich [0, 48][0,\ 48] ab. Wie verändert sich das Histogramm? b (4 P): Bilden Sie [6, 6][-6,\ 6] auf [2, 8][2,\ 8] ab. Ist das Ergebnis kontrastreicher oder kontrastärmer? Begründung. c (2 P): Nennen Sie die Parameter von glm::perspective(a, b, c, d).

Lösung anzeigen

Allgemein: mult=gmaxgminemaxemin\text{mult} = \dfrac{g'_{max} - g'_{min}}{e_{max} - e_{min}}; add\text{add} so wählen, dass emine_{min} auf gming'_{min} fällt (bekannten Punkt einsetzen und auflösen).

a) [6, 6][0, 48][-6,\ 6] \to [0,\ 48]:

mult=4806(6)=4812=4,add=04(6)=24\text{mult} = \frac{48 - 0}{6 - (-6)} = \frac{48}{12} = 4, \qquad \text{add} = 0 - 4\cdot(-6) = 24 g=4e+24\boxed{g' = 4\,e + 24}

Probe: 64(6)+24=0-6 \mapsto 4\cdot(-6)+24 = 0 ✓,   646+24=48\;6 \mapsto 4\cdot6+24 = 48 ✓.

Histogramm: Wegen mult=4>1\text{mult} = 4 > 1 wird der Wertebereich gespreizt (stretched). Die Balkenform bleibt erhalten, es entstehen aber Lücken (Kammform / comb pattern), weil benachbarte ganzzahlige Eingabewerte auf um 44 auseinanderliegende Ausgabewerte abgebildet werden. Der Kontrast steigt.

b) [6, 6][2, 8][-6,\ 6] \to [2,\ 8]:

mult=826(6)=612=0,5,add=20,5(6)=2+3=5\text{mult} = \frac{8 - 2}{6 - (-6)} = \frac{6}{12} = 0{,}5, \qquad \text{add} = 2 - 0{,}5\cdot(-6) = 2 + 3 = 5 g=0,5e+5\boxed{g' = 0{,}5\,e + 5}

Probe: 60,5(6)+5=2-6 \mapsto 0{,}5\cdot(-6)+5 = 2 ✓,   60,56+5=8\;6 \mapsto 0{,}5\cdot6+5 = 8 ✓.

Kontrast: Wegen mult=0,5<1\text{mult} = 0{,}5 < 1 wird der Wertebereich gestaucht (compressed), das Ergebnis ist kontrastärmer (die Grauwertspanne schrumpft von 1212 auf 66).

c) glm::perspective(a, b, c, d):

  • a = fovy (vertikaler Öffnungswinkel / field of view in y)
  • b = aspect (Seitenverhältnis Breite/Höhe / aspect ratio)
  • c = zNear (Abstand der nahen Clipping-Ebene / near clipping plane)
  • d = zFar (Abstand der fernen Clipping-Ebene / far clipping plane)

Kapitelbezug: Kapitel 11: Bildbearbeitung - Punktoperatoren (lineare Grauwerttransformation, Histogramm), Kapitel 7: Kameras (perspektivische Projektion).

Typischer Fehler: add falsch bestimmen. Sichere Methode: mult\text{mult} aus den Intervallbreiten berechnen, dann einen bekannten Punkt (z.B. emine_{min}) einsetzen und nach add auflösen. Faustregel: mult>1\text{mult} > 1 spreizt (mehr Kontrast), mult<1\text{mult} < 1 staucht (weniger Kontrast).


Klausur WS2025 (Lösungen) · Probeklausur 1 · Kapitelübersicht