Universität Leipzig Institut für Informatik Abteilung Bild- und Signalverarbeitung Sommersemester 2007 Computergrafik-Praktikum Betreuer: Heike Jänicke 5. Übungsblatt (Computergrafik-Praktikum) Raytracing einer triangulierten Szene Aufgabe 1 (Raytracing triangulierter Szenen) Raytracing ist ein hochentwickeltes Renderingverfahren das zur Erzeugung photorealistischer Bilder eingesetzt wird. Im Gegensatz zu dem effizienteren z-Buffer Algorithmus, der meistens in Graphikhardware implementiert ist, ermöglicht Raytracing das Modellieren vieler Spezialeffekte, wie z.B. die Berücksichtigung von spiegelndem und gebrochenem Licht an transparenten Materialübergängen. Abbildung 1: Raytracing einer Szene. Raytracing verfolgt das Licht entgegen seiner Ausbreitungsrichtung vom Betrachter zurück zu den Lichtquellen. Für jeden Bildpunkt (Pixel) wird ein Strahl ausgehend vom Augpunkt mit der Szene geschnitten. Am ersten Schnittpunkt wird mit Hilfe eines Beleuchtungsmodells die Farbe des Pixels ermittelt. Dazu benötigen wir die Flächennormale und Materialeigenschaften am Schnittpunkt, sowie die Position und Sichtbarkeit (vom Schnittpunkt) aller Lichtquellen, siehe Abbildung 1. Im Falle einer partiell durchsichtigen oder spiegelnden Fläche wird der Strahl gebrochen bzw. reflektiert und rekursiv weiter verfolgt. 1 Spezifikation Implementieren Sie einen Raytracer zum realistischen Rendering triangulierter Szenen mit folgenden Features: • Vorgabe der Kameraperspektive und Beleuchtungssituation durch eine manuell erstellbare Definitionsdatei. • Ermittlung der Flächennormalen mit Hilfe von Phong Shading. • Auswertung des (modifizierten) Beleuchtungsmodells von Phong für RGB Farbanteile mit korrekter Ermittlung der Schatten. • Rekursive Strahlverfolgung bei spiegelnden und transparenten Flächen. • (freiwillige Zusatzaufgabe): Beschleunigung des Rendering Verfahrens mit Hilfe einer uniformen Partitionierung des Raumes und entsprechender Zerlegung einer Szene. Der Raytracer beginnt mit dem Einlesen der Definitionsdatei, die dem hier beschriebenen Format entsprechen sollte: • Dateiname der triangulierten Szene. • Fenstergröße (Höhe und Breite in Pixels). • Augpunkt (drei Koordinaten). • Mittelpunkt der Bildebene (drei Koordinaten). • Brennweite (reell). • Rotationswinkel der Kamera um die Sichtrichtungsachse. • RGB-Anteile der Hintergrundfarbe. • RGB-Anteile der Ambienten Helligkeit. • Anzahl der Partitionierungen für den Beschleunigungsansatz. Die Bedeutung dieser Dateieinträge wird in den folgenden Abschnitten erläutert. Es ist zu beachten, daß das Rendering eines Bildes (je nach Bildauflösung und Komplexität der Szene) mehrere Minuten dauert. Die Ausgabe sollte daher während der Berechnung erfolgen (Single-Buffering mit OpenGL). Sichtdefinition Für das Raytracing muß für jeden Pixel ein Strahl berechnet werden. Dazu benötigen wir eine Funktion, welche die Bildkoordinaten in Weltkoordinaten unter Berücksichtigung der Kameraperspektive umrechnet. Um diese Funktion aufzustellen, ermitteln wir zwei orthogonale Basisvektoren x und y, welche die 2 Abbildung 2: Sichtdefinition Bildebene ausgehend vom Bildmittelpunkt aufspannen, siehe Abbildung 2. Der Vektor x soll zunächst horizontal ausgerichtet sein: x = b × ey und y = x × b, (1) wobei b den Sichtrichtungsvektor bezeichnet und ey den vertikalen Einheitsvektor (b und ey dürfen nicht die gleiche bzw. entgegengesetzte Richtung haben). Die Vektoren x und y sind noch zu normalisieren. Um nicht nur horizontale Kameraeinstellungen zuzulassen, wird in der Definitionsdatei ein Rotationswinkel angegeben, um den das System {x, y} entgegen dem Uhrzeigersinn gedreht wird. Die Brennweite α ist das Verhältnis aus der Entfernung d des Augpunktes von der Bildebene zur (virtuellen) Bildhöhe h. Bei großer Brennweite erhalten wir näherungsweise eine Parallelprojektion, kleine Brennweiten führen hingegen zu größeren Verzerrungen, wie bei einem “Fischauge” als Kameraobjektiv. Aus der Brennweite werden die Bildhöhe h = αd und die Bildbreite w berechnet, so daß deren Verhältnis mit dem der Fensterausmaße aus der Definitionsdatei übereinstimmt. Schnittpunktberechnung Alle Primitive (Dreiecke) einer Szene werden zunächst mit dem Strahl ray(t) = e + tb (2) geschnitten. Hierbei bezeichnet e den Augpunkt und b die Richtung des Strahls. Von allen Schnittpunkten wird derjenige ermittelt, der dem Augpunkt am nächsten ist, d.h. derjenige mit kleinstem (positivem) Parameter t. Wurde kein Schittpunkt gefunden, so erhält der zugehörige Pixel die Hintergrundfarbe. Um den Schnittpunkt des Strahls mit einem Dreieck, gegeben durch die Punkte p1 , p2 , p3 , zu ermitteln, wird zunächst die Ebene des Dreiecks in Normalenform 3 aufgestellt: (x − p1 ) · n = 0, (3) wobei n die Normale des Dreiecks ist. Durch Einsetzen des Strahls für x erhalten wir den Parameter t des Schnittpunktes mit der Ebene, t = (p1 − e) · n , b·n (4) sofern Strahl und Ebene nicht parallel sind (b · n 6= 0). Abbildung 3: Baryzentrische Koordinaten. Mit dem Parameter t ist auch der Schnittpunkt p ermittelt, der jedoch nur dann gültig ist, wenn er innerhalb des Dreiecks liegt und wenn t positiv ist. Ersteres kann mit Hilfe der baryzentrischen Koordinaten αi festgestellt werden: der Punkt p besitzt die Darstellung X p = α1 p1 + α2 p2 + α3 p3 , mit αi = 1. (5) Liegt p außerhalb des Dreiecks, so ist mindestens eine der baryzentrischen Koordinaten negativ. Die baryzentrischen Koordinaten entsprechen den Flächenanteilen der in Abbildung 3 dargestellten Teildreiecke und können wie folgt berechnet werden: area(p, pi+1 , pi+2 ) , area(p1 , p2 , p3 ) area(a, b, c) = 12 k(b − a) × (c − a)k, kαi k = (6) mit Indizes modulo 3. Die Vorzeichen der baryzentrischen Koordinaten können durch Vergleichen der Orientierungen der Vektoren n und (b − a) × (c − a) ermittelt werden. Eine andere Möglichkeit festzustellen, ob der Punkt p innerhalb des Dreiecks liegt, besteht darin, die (nicht orientierten) Flächen der Teildreiecke zu addieren und mit der Gesamtfläche des Dreiecks zu vergleichen. Ist die Summe der einzelnen Teilflächen größer, so liegt der Punkt außerhalb. Bei diesem Test sollte jedoch eine kleine Diskrepanz ε zugelassen sein, um numerische Fehler auszuschließen. 4 Abbildung 4: Winkel zur Auswertung des Beleuchtungsmodells. Das Beleuchtungsmodell von Phong Wurde ein gültiger Schnittpunkt p des Sichtstrahles mit der Szene ermittelt, so ist nun noch die Farbe des entsprechenden Pixels zu berechnen, unter Berücksichtigung der Materialeigenschaften und der Beleuchtungssituation. Die Farbe wird mit Hilfe eines Beleuchtungsmodells wie folgt ermittelt. Zunächst benötigen wir die Flächennormale n im Punkt p. Um den Eindruck einer glatten Fläche zu erwecken, verwenden wir Phong Shading, d.h. n = α1 n1 + α2 n2 + α3 n3 , (7) wobei ni die Normalen der Eckpunkte pi des Dreiecks und αi die baryzentrischen Koordinaten von p bezeichnen. Sei a der Vektor zum Augpunkt (umgekehrte Blickrichtung). Falls der Winkel zwischen a und n mehr als 90◦ beträgt, so ist die Orientierung von n umzukehren. Angenommen, es existiert nur eine einzige (punktförmige) Lichtquelle, die vom Punkt p aus in Richtung des Vektors l sichtbar ist. Dann würde gespiegeltes Licht entlang der Richtung r, wie in Abbildung 4 dargestellt, reflektiert, r = 2(n · l) n − l. (8) Hierbei wurde vorausgesetzt, daß die Vektoren a, n und l normalisiert sind. Die entscheidenden Größen für das Beleuchtungsmodell sind die Winkel θ (zwischen n und l) und α (zwischen a und r). Die zu berechnende Farbintensität setzt sich aus drei Termen zusammen: • Die ambiente Intensität ist ein (in der Regel schwacher) Anteil des Lichtes, das von anderen Flächenkomponenten diffus reflektiert wird und im Punkt p eintrifft. Der Einfachheit halber wird dieser Term als konstant (unabhängig von p) angenommen. (Eine genaue Berechnung dieser Intensität ist mit dem Radiosity Verfahren möglich.) • Als diffus bezeichnen wir das Licht, welches von einer oder mehreren Lichtquellen ausgehend am Punkt p eintrifft und von dort (wie das ambiente 5 Licht) gleichmäßig in alle Richtungen abgestrahlt wird. Die diffuse Intensität hängt daher nicht von der Position des Augpunktes, wohl aber von der Beleuchtungssituation ab. • Spiegelndes Licht ist genau dann anzutreffen, wenn sich, vom Augpunkt gesehen, eine Lichtquelle in p spiegelt. In diesem Fall ergibt sich in der Umgebung von p ein (meistens sehr intenses) “Highlight”, dessen Größe auch von der Glänzigkeit (Shininess) des Materials abhängt. Diese drei Terme sind in dem Beleuchtungsmodell von Phong zusammengefaßt, das die Intensität für eine bestimmte Wellenlänge λ liefert: Iλ = Iaλ ka Odλ + fatt (dl )Ilλ (kd Odλ cosθ + w(θ)coss α) . (9) Das Beleuchtungsmodell kann z.B. für rote, grüne und blaue Farbanteile berechnet werden, d.h. λ ∈ {λR , λG , λB }. Die einzelnen Konstanten und Funktionen haben folgende Bedeutung: • Iaλ beschreibt die Intensität des ambienten Lichtes (konstant für jede einzelne Wellenlänge). • Ilλ ist die Intensität der Lichtquelle (für jede Wellenlänge). • Odλ ist die Materialfarbe (Intensität diffus reflektierten Lichtes für jede Wellenlänge). • ka und kd sind zusätzliche Materialkonstanten (wellenlängenunabhängig) zur Gesamteinstellung der ambienten und diffusen Intensität. • fatt (dl ) ist eine Funktion der Entfernung dl der Lichtquelle zum Punkt p, zum Modellieren der Abschwächung (Attenuation) während der Ausbreitung des Lichtes. • w(θ) ist eine materialabhängige Funktion. • s ist eine Konstante für die Glänzigkeit des Materials. Der Term coss α modelliert das Abfallen des spiegelnden Highlights entlang der Fläche und hat empirischen Charakter (keine theoretische Grundlage). Die Abschwächung des Lichtes fatt ist in der Natur quadratisch proportional zum Ausbreitungsweg d, d.h. fatt (d) = d12 . Dies führt jedoch beim Rendering nicht immer zu zufriedenstellenden Resultaten. Wir verwenden daher eine Allgemeinere Form dieser Funktion, fatt (d) = 1 . c0 + c1 d + c2 d2 (10) Die Konstanten ci befinden sich in der Definitionsdatei und erlauben es, quadratische, lineare, und konstante Abschwächung oder jede gewünschte Kombination zu modellieren. 6 Das Beleuchtungsmodell für den Praktikumsraytracer hat noch einige (kleine) Besonderheiten: die Konstanten ka und kd , sowie die Funktion w(θ) werden durch Eins ersetzt. Statt dessen sind die ambienten, diffusen, und spiegelnden RGB-Farbanteile des Materials voneinander unabhängig und werden mit Oaλ , Odλ und Osλ bezeichnet. Die diffusen und spiegelnden Terme sind für jede vom Punkt p aus sichtbare Lichtquelle l aufzuaddieren. Das zu implementierende Beleuchtungsmodell hat diese Form: X Iλ = Iaλ Oaλ + fatt (dl )Ilλ (Odλ (n · l) + Osλ (max{0, r · a})s ) . (11) l sichtbar Hier wurde bereits n·l für cosθ und r·a für cosα eingesetzt. Der spiegelnde Term verschwindet für Winkel α ≥ 90◦ . Eine Lichtquelle l ist vom Flächenpunkt p (mit Normale n) aus sichtbar, wenn θ < 90◦ und wenn das Geradensegment von p bis zur Position der Lichtquelle keine anderen Objekte (Dreiecke) schneidet. Freiwillige Zusatzaufgabe (Beschleunigung) Der Zeitaufwand für das Rendering wird im Wesentlichen dadurch bestimmt, daß jeder Strahl mit allen Dreiecken einer Szene geschnitten werden muß. Da die meisten Strahlen jedoch nur geringe Teile der Szene durchdringen, ist eine räumliche Partitionierung der Szene und eine darauf basierende Vorauswahl der zu verschneidenden Dreiecke sinnvoll. Abbildung 5: Drei Unterschiedliche Fälle des Hineinragens eines Dreiecks in einen Voxel. Zuerst bestimmen wir die kleinste Bounding Box (umschließenden Quader) der Szene. Diese wird in n3 Voxels (Quader gleicher Größe) unterteilt. Die Konstante n befindet sich in der Definitionsdatei. Unmittelbar nach dem Einlesen der Szene wird für jeden Voxel eine Liste mit Dreiecken angelegt, die in diesen Voxel hineinragen (es empfiehlt sich, Zeiger auf die Dreiecksobjekte zu verwalten, da einzelne Dreiecke häufig in mehrere Voxels hineinragen). Ein Dreieck, gegeben durch die Punkte p1 , p2 , p3 , ragt in einen Voxel hinein, wenn mindestens einer der folgenden drei Tests positiv ist (siehe auch Abbildung 5): 1. Einer der Eckpunkte pi liegt innerhalb des Voxels. 7 2. Eine der drei Kanten p1 p2 , p2 p3 und p3 p1 schneidet die Oberfläche des Voxels. 3. Eine der vier Hauptdiagonalen des Voxels schneidet das Dreieck. Bei der Strahlverfolgung wird nun zuerst ermittelt, welche Voxels ein bestimmter Strahl durchdringt. Dieser wird dann nur noch mit denjenigen Dreiecken geschnitten, welche sich in den zugehörigen Listen befinden. Insbesondere bei komplizierten Szenen bestehend aus sehr vielen Dreiecken erhöht dieses Vorauswahlverfahren erheblich die Effizienz des Raytracers. Spiegelnde Flächen Für die Materialfarbe sind im Dateiformat jeweils vier Komponenten (RGBA) vorgesehen. Der Wert von A, der (eigentlich) die Transparenz eines Materials darstellt, wurde bislang ignoriert. Wir verwenden hier die Komponente A der spiegelnden Farbeigenschaft um partiell spiegelnde Flächen zu rendern. Ein Wert von Eins bedeutet, daß das Material matt ist, wie bisher angenommen. Ein kleinerer, positiver Wert bedeutet, daß das Material partiell spiegelnd ist. in diesem Fall wird die Farbe nur zu einem Anteil von A durch Iλ aus dem Beleuchtungsmodell bestimmt. Der verbleibende Anteil von (1-A) wird durch rekursive Verfolgung des reflektierten Strahls ermittelt. Die Rekursionstiefe ist zu begrenzen. Abbildung 6: Brechung eines Strahls am Materialübergang. Transparente Flächen In der Natur stellen Flächen Übergänge unterschiedlicher Materialien dar. In diesem Fall verringert oder erhöht sich der Winkel β eines Strahls zur Flächennormalen beim Austreten auf der anderen Flächenseite, siehe Abbildung 6. Je nach Richtung des Strahls, bezogen auf die ursprüngliche Orientierung der Flächennormale, wird der Winkel β mit einem Brechungsfaktor multipliziert oder durch selbigen geteilt. (Der Brechungsfaktor kann z.B. in der ambienten Komponente A gespeichert werden.) Erhöht sich der Winkel β auf über 90◦ , so wird der Strahl reflektiert statt gebrochen. (Für ein korrektes Rendering müßte die Brechung auch bei der Auswertung des Beleuchtungsmodells berücksichtigt werden, was nicht zu realisieren ist, da die Strahlen immer in einer Lichtquelle enden müssen. Hier helfen andere Verfahren, wie z.B. Radiosity.) 8 Um transparente Flächen zu rendern, verwenden wir die Komponente A der diffusen Farbeigenschaft (Eins bedeutet undurchsichtig und Null bedeutet voll transparent). Wie im spiegelnden Fall wird der gebrichene Strahl fortgesetzt und rekursiv weiter verfolgt. Die zurückgelieferte Farbe des rekursiven Strahls bestimmt zu einem Anteil von (1-A) die aktuelle Pixelfarbe. Um nur jeweils einen Strahl verfolgen zu müssen, wird angenommen, daß die Flächen entweder spiegelnd oder transparent sind, aber nicht beides zugleich. Auch hier ist die Rekursionstiefe zu begrenzen. 9