From CoGr@Ohm
Starten Sie mit Ihrem Code aus der vorhergehenden Übung #07.
Ergänzen Sie den Code um einen Shader bzw. bauen Sie in Ihren Code einen Shader-Editor ein. Dazu benötigen Sie die folgenden zusätzliche Zeilen:
Im Globalen Namensraum:
GLuint prog_id; const char shader[] = "";
In der Methode initializeOpenGL():
prog_id = lglCompileGLSLProgram(shader); create_lgl_Qt_ShaderEditor("shader", &prog_id);
In der Methode renderOpenGL():
lglUseProgram(prog_id, false);
Sie sollten nun eine unbeleuchtete (und untexturierte) Szene sehen. Der Vertex Shader multipliziert nur die Vertices mit der MVP (die mit lglModelView
gesetzt wurde). Und der Fragment Shader verwendet nur die aktuell spezifizierte Farbe (die zuletzt mit lglColor
gesetzt wurde).
D.h. es wird der einfachste denkbare Shader - der sog. Plain-Shader - verwendet (siehe Cheat Sheet → Shaders).
Im Folgenden werden wir nun Schritt für Schritt diesen Shader weiterentwickeln, so dass die Szene wieder beleuchtet dargestellt wird. Editieren des Shaders im Editor Fenster erfolgt wie folgt:
Zur Erinnerung vorher noch ein paar Verständnisfragen:
Material und Links:
Wir steigen mit einem weiteren einfachen GLSL Shader ein: Fogging! D.h. verwenden Sie den folgenden Fragment Shader:
#version 120 uniform vec4 color; void main() { const float density = 0.01f; float z = 1.0f / gl_FragCoord.w; float f = 1.0f - exp(-3 * density * z*z*z); gl_FragColor = (1.0f-f)*color + f*vec4(1); }
Ändern Sie die Hintergrundfarbe, damit diese zur Darstellung durch den Shader passt. Ändern Sie die Dichte density so dass sie einen passenden Farbverlauf erhalten.
Ersetzen Sie die Konstante density im GLSL Shader durch einen uniformen Parameter, den Sie im C++ Hauptprogramm bestimmen können (via lglUniformf(“density”, value)). Verwenden Sie wie in Übung #06 passende Tasten, um den Parameter zu verändern.
Momentan wird die Szene noch einfarbig pro Objekt gezeichnet, d.h. es gibt keinerlei Farbvariation. Diese bringen wir jetzt ins Spiel:
Transportieren Sie die Vertices aus dem Vertex- in den Fragment-Shader, indem Sie die Koordinaten im Vertex-Shader in ein sog. Varying schreiben. Wir verwenden die unveränderten Objekt-Koordinaten, d.h. es wird nicht mit der MVP multipliziert!
Diese Objekt-Koordinaten lesen wir nun im Fragment-Shader aus dem Varying aus und verwenden sie als Fragment-Farbe.
Eventuell müssen die Farbwerte etwas angepasst werden, um eine leicht psychedelische Darstellung (wie rechts beispielhaft abgebildet) zu erreichen. Dazu multipliziert man die einzelnen Komponenten mit einer Konstante und verwendet nur den Nachkommaanteil (GLSL: fract).
Hinweis: Für diese und die folgenden Aufgaben sind keine Änderungen am C++ Programm erforderlich, lediglich der GLSL Shader ist anzupassen.
Transportieren Sie nun nicht nur die Vertices sondern auch die Normalen aus dem Vertex- in den Fragment-Shader. D.h. schreiben Sie das Attribut vertex_normal in ein zusätzliches Varying.
Jetzt wird es noch psychedelischer: Verwenden Sie die Normalen für die Fragment-Farbe. Aber nicht die tatsächlichen Normalen, sondern wir verwenden die folgende Abbildung:
Auf diese Weise können wir die Normalen “lesen” und Fehler erkennen → Graphisches Debugging.
Wir erkennen dadurch, dass die Normalen nicht konsistent zwischen den einzelnen Robotersegmenten sind: Welche Normale bzw. welche Farbe müsste eine Fläche tatsächlich haben, auf die der Betrachter frontal schaut? Bestimmen Sie den konkreten RGB-Farbwert! Tipp: himmelblau.
Erinnern Sie Sich, dass die Normalen im Vertex-Shader mit einer speziellen Matrix multipliziert werden müssen? Verwenden Sie diese (siehe Cheat Sheet → GLSL)!
Renormalisieren Sie außerdem die Normalen im Fragment-Shader (GLSL: normalize)!
Zum Abschluß können wir die Normalen nun für die Beleuchtung der Objekte verwenden. Die am einfachsten zu berechnende Beleuchtung ist die diffuse lokale Beleuchtung:
Die diffuse Beleuchtung verwendet den Cosinus des Zwischenwinkels von Lichtvektor $\vec{l}$ und Normale $\vec{n}$ als Beleuchtungsintensität bzw Helligkeit. Dazu muss das Skalarprodukt der Normalen mit dem Lichtvektor berechnet werden. Als Lichtvektor wählen wir einen beliebigen normalisierten Lichtrichtungsvektor als Beleuchtungsrichtung in Augenkoordinaten für eine rein direktionale Lichtquelle. Das Ergebnis der Berechung ist die Helligkeit $h_d = \vec{n} \cdot \vec{l}$ des diffusen Anteils des lokalen Blinn-Phong Beleuchtungsmodells ($I_d = h_dI_L$). Mit dieser Helligkeit modulieren (d.h. multiplizieren) wir nun die bisherige Vertex-Farbe (color). Achtung: $h_d$ sollte nicht negativ werden (GLSL: max)!
Verwenden Sie außerdem einen ambienten bzw. konstanten Beleuchtungsanteil $I_a = const$. Für einen warmen Beleuchtungston, wie er z.B. durch die Sonne erzeugt wird, verwendet man $I_a$ = (0.2, 0.1, 0), den man hinzuaddiert.
Anstelle einer physikalisch motivierten, diffusen Beleuchtung erzeugen wir jetzt einen Comic-Look.
Beim so genannten Toon Shading (Cell bzw. Tone Shading oder eben auch Comic Shading) werden nur wenige Farben einer festen Farbpalette benutzt, um die Beleuchtungsintensität darzustellen.
Am Roboter ist das eventuell nicht so schön zu erkennen. Stellen Sie daher neben den Roboter noch einen Teapot (lglTeapot).
Benutzen Sie jetzt das Skalarprodukt (die vorher berechnete Helligkeit $h_d$), um anhand einer Fallunterscheidung (if-else-Kaskade) folgende Farben zu verwenden:
1. BRDF:
Zeichnen Sie die BRDF von einer Spiegelkugel, einer Plastikkugel und einer schwarzen und einer weißen matten Kugel (analog zu den Illustrationen in der Vorlesung)!
2. Lokale Beleuchtung:
3. Globale Beleuchtung:
Zeichnen Sie beispielhaft die Lichtwege, die für die folgenden globalen Beleuchtungsmodelle relevant sind:
Nehmen Sie an, dass Ihre Szene aus einem Raum mit zwei Plastikwürfeln besteht und zeichnen Sie jeweils die entsprechenden Lichtpfade. Zeichnen Sie der Einfachheit halber nicht dreidimensional.
4. Optional: Kaustik
Ganz dumm gefragt: Wieso lassen sich Kaustiken weder mit Raytracing noch mit Radiosity darstellen? Was ist überhaupt eine Kaustik [1]? Begründen Sie Ihre Antwort zeichnerisch!
Retrieved from http://schorsch.efi.fh-nuernberg.de/cogr/index.php/CGExercises/Exercise08
Page last modified on December 22, 2020, at 02:40 PM