Computergraphik II
Transcrição
Computergraphik II
Computergraphik II Susanne Krömker Sommersemester 2010 Skript zur Vorlesung, Stand 9. April 2010 Inhaltsverzeichnis 1 Einführung ins Rendering 1 1.1 OpenGL und was es sonst noch so alles gibt . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Blinn-Phong, ein lokales Lichtmodell . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2.1 Gerichtete Lichtquellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Cook & Torrance Modell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.3.1 Bidirektionale Reflexivität . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.3.2 Distributionsfunktion des Mikrofacettenmodells . . . . . . . . . . . . . . . . 6 1.3.3 Geometrische Abschwächung durch Mikrofacetten . . . . . . . . . . . . . . 8 1.3.4 Fresnelterm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.3 1.4 2 Graphikkarten Programmierung 17 2.1 Shader Programmierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.2 Shade trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.2.1 Reyes-Pipeline und Renderman Interface . . . . . . . . . . . . . . . . . . . 21 2.2.2 Dicing oder Würfelalgorithmus . . . . . . . . . . . . . . . . . . . . . . . . 21 C for graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.3.1 24 2.3 Cg - Historische Entwicklung . . . . . . . . . . . . . . . . . . . . . . . . . iii iv INHALTSVERZEICHNIS 2.4 3 Programmierbarer Vertex Prozessor . . . . . . . . . . . . . . . . . . . . . . 24 2.3.3 Programmierbarer Fragment Prozessor . . . . . . . . . . . . . . . . . . . . 25 2.3.4 CgFX Toolkit und Austauschformat . . . . . . . . . . . . . . . . . . . . . . 25 2.3.5 Compiler und Bibliotheken . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.3.6 Ähnlichkeit mit C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.3.7 Besonderheiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 2.3.8 Fehlerbehandlung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 2.3.9 Parameter, Texturen und mathematische Ausdrücke . . . . . . . . . . . . . . 37 Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Volume Rendering 45 3.1 Herleitung der Gleichung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.1.1 Energieerhaltungsgleichung . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.2 Vereinfachungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.3 Einfacher Ray Casting Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.3.1 Klassifizierung und Transferfunktion . . . . . . . . . . . . . . . . . . . . . 50 Beschleunigungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 3.4.1 Early Ray Termination – Abbruchkriterien . . . . . . . . . . . . . . . . . . 52 3.4.2 Ausnutzen kohärenter Strukturen . . . . . . . . . . . . . . . . . . . . . . . 52 3.4.3 Shear-Warp Faktorisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 3.4.4 Texturbasiertes Volume Rendering . . . . . . . . . . . . . . . . . . . . . . . 54 Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 3.4 3.5 4 2.3.2 Radiosity 57 4.1 59 Herleitung des Verfahrens und Modellgleichung . . . . . . . . . . . . . . . . . . . . INHALTSVERZEICHNIS 4.2 Diskrete Radiositygleichung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 4.3 Berechnung der Formfaktoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 4.3.1 Brute Force Ansatz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.3.2 Methode nach Nusselt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.3.3 Hemicube Verfahren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 4.3.4 Sillions Verbesserung und weitere Methoden . . . . . . . . . . . . . . . . . 67 Berechnung der Radiosity-Werte . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4.4.1 Allgemeine Iterationsverfahren . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.4.2 Jacobiverfahren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 4.4.3 Gauß-Seidel Verfahren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 4.4.4 SOR-Verfahren (Successive Overrelaxation) bzw. Relaxationsverfahren . . . 72 4.4.5 Anwendbarkeit der Iterationsverfahren auf Radiosity . . . . . . . . . . . . . 73 4.4.6 Progressive Verfeinerungen . . . . . . . . . . . . . . . . . . . . . . . . . . 73 4.4.7 Gathering Verfahren (= Einsammeln) . . . . . . . . . . . . . . . . . . . . . 75 4.4.8 Shooting Verfahren (= Aussenden) . . . . . . . . . . . . . . . . . . . . . . . 76 Rendern mit Radiosity-Werten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 4.5.1 Lichtlecks und Diskontinuitäten . . . . . . . . . . . . . . . . . . . . . . . . 79 Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 4.4 4.5 4.6 5 v Photon Mapping 81 5.1 Die Spur der Photonen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 5.1.1 Photonemission . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 5.1.2 Photonenverfolgung mit russischem Roulette . . . . . . . . . . . . . . . . . 85 5.1.3 Speichern von Photonen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Photonen im Rendering Pass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 5.2 vi INHALTSVERZEICHNIS 5.3 6 5.2.1 Abschätzung der Strahlung an einer Oberfläche . . . . . . . . . . . . . . . . 90 5.2.2 Filter für die Abschätzung . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 5.2.3 Strahlungsabschätzung im Volumenfall . . . . . . . . . . . . . . . . . . . . 94 5.2.4 Auffinden der n nächsten Photonen . . . . . . . . . . . . . . . . . . . . . . 95 5.2.5 Auswertung der Strahlungsabschätzung: Rendering . . . . . . . . . . . . . . 96 Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 Nichtphotorealistisches Rendering 101 6.1 Zweidimensionale NPR-Techniken, Bildbearbeitung . . . . . . . . . . . . . . . . . 102 6.2 Dreidimensionale NPR-Techniken . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 6.3 Konturlinien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 6.4 6.5 6.6 6.7 6.3.1 Silhouetten mit OpenGL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 6.3.2 Exaktes Verfahren für Dreiecksgitter . . . . . . . . . . . . . . . . . . . . . . 104 6.3.3 Bildbasierter Konturalgorithmus . . . . . . . . . . . . . . . . . . . . . . . . 106 Nichtphotorealistisches Shading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 6.4.1 Cel-Shading oder Toon-Shading . . . . . . . . . . . . . . . . . . . . . . . . 110 6.4.2 Gooch Shading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Line-Art Rendering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 6.5.1 Kreuzschraffur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 6.5.2 Krümmungsangepasste Schraffur . . . . . . . . . . . . . . . . . . . . . . . 113 Transformationen der Geometrie . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 6.6.1 Blickpunktsänderung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 6.6.2 Animationen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 INHALTSVERZEICHNIS 7 Splines 7.1 7.2 7.4 121 Splinekurven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 7.1.1 Kubisch hermitesche Splines . . . . . . . . . . . . . . . . . . . . . . . . . . 123 7.1.2 Bézier-Splines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 7.1.3 Konstruktionsalgorithmus nach Casteljau . . . . . . . . . . . . . . . . . . . 125 7.1.4 B-Splines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 7.1.5 Konstruktion der Basisfunktionen . . . . . . . . . . . . . . . . . . . . . . . 129 7.1.6 Verfeinerbarkeit von B-Splines . . . . . . . . . . . . . . . . . . . . . . . . . 130 7.1.7 Subdivision für Spline-Kurven . . . . . . . . . . . . . . . . . . . . . . . . . 131 7.1.8 Nichtuniforme rationale B-Splines . . . . . . . . . . . . . . . . . . . . . . . 133 Flächen als bivariate Splines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 7.2.1 7.3 vii NURBS-Flächen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Subdivisionflächen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 7.3.1 Subdivision Schemata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 7.3.2 Catmull-Clark Subdivision . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 7.3.3 Subdivision nach Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 7.3.4 Weiche und scharfe Kanten . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 Übungsaufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Literaturverzeichnis 148 viii INHALTSVERZEICHNIS Kapitel 1 Einführung ins Rendering Mit dem Begriff Echtzeit Rendering verbindet man immer noch geringere Qualität und schnelle, aber nicht unbedingt realistische Spielegraphik. Inzwischen sind aber auch Verfahren wie Raytracing auf gutem Wege, in Echtzeit darstellbare Bilder zu liefern. Hierfür ist noch immer speziell entwickelte Hardware nötig, die die Parallelisierbarkeit des Algorithmus optimal ausnutzt (siehe beispielsweise die Arbeiten von Philipp Slusallek, Universität Saarbrücken [SWW+ 04]). Eine weitere Entwicklung setzt auf die Auslagerung vieler einfacher Operationen auf die Graphikprozessoren (GPU) und erzielt damit einen großen Geschwindigkeitsvorteil im Renderprozess. Diese Vorlesung wird sich mit den möglichen Qualitätssteigerungen im Rendering auseinandersetzen und dabei den algorithmischen Teil und mathematische Verfahren betonen. Damit ein Quereinstieg möglich ist, wiederholt dieses Eingangskapitel einige Themen aus dem ersten Teil der Vorlesung. 1.1 OpenGL und was es sonst noch so alles gibt Die Open Graphics Library (OpenGL) ist eine architektur- und programmiersprachenunabhängige Implementierung eines Application Programming Interface (API) zum Erzeugen von 3D-Computergraphik. Sie wird als Teil der Graphikkarten-Treiber ausgeliefert, wobei auf der Graphikkarte fehlende Funktionen von der CPU emuliert werden können. Die gängigste Open-Source-Implementierung annähernd gleicher Mächtigkeit und nachprogrammierter Struktur ist die Mesa-Bibliothek. Auf dieser Basis haben weitere Entwicklungen aufgesetzt, wie beispielsweise das Visualization Toolkit (VTK). Es wurde für spezielle Anforderungen im wissenschaftlichen Bereich entwickelt, hat daher seine Stärken im Bereich der Darstellung von Messdaten und Simulationsdaten, Strömungs- und Vektorfeldern. Die Virtual Reality Markup Language (VRML) ist ein Standard zur Beschreibung von 3D-Graphiken mit einfachen geometrischen Objekten und Beleuchtungsmodellen. Erweitert um Interaktionen und 1 2 KAPITEL 1. EINFÜHRUNG INS RENDERING mit der Möglichkeit, über Plugins im Browser darstellbar zu sein, ist diese 3D-Beschreibungssprache von entprechenden z.B. auf Basis von OpenGL geschriebenen Viewern abhängig. Sie dient auch vielen Programmen als 3D-Austauschformat. Java ist ebenfalls plattformunabhängig und eine Entwicklung von Sun Microsystems. Es lassen sich damit 3D-Graphiken erstellen und animieren, und vor allem in Browsern interaktiv steuern. Java hat dazu eine eigene Skriptsprache JavaScript, die von fast allen Browsern unterstützt wird. DirectX ist eine Entwicklung von Microsoft speziell für multimediale Interaktion. Es bietet viele Vorteile beim Einbinden von Audiofunktionen in 3D-Graphiken, ist auf dem Spielesektor weit verbreitet, aber von der Plattform auf Microsoft-Betriebssysteme eingeschränkt. 1.2 Blinn-Phong, ein lokales Lichtmodell Die lokalen Lichtmodelle gehen einzig von einem Punkt auf der Oberfläche eines Objekts aus und ermitteln die Lokalfarbe aus den an diesem Punkt bekannten Vektoren und den Eigenschaften dieser Objekte und der Lichter. Sie lassen sich sehr gut mit dem z-Buffer Algorithmus kombinieren, denn auch dieser Algorithmus arbeitet mit lokalen Werten: Über den z-Wert eines Punktes wird entschieden, ob dieser Punkt im Colorbuffer dargestellt wird. Für beide Algorihmen ist das Wissen um die räumlichen Beziehungen zwischen Objekten nicht notwendig. Verdeckungen aus Betrachtersicht sind effizient darstellbar, aber Verdeckungen aus Sicht einer Lichtquelle, die kein Headlight ist und daher einen Schatten eines der Lichtquelle näheren Objekts auf andere Objekte wirft, benötigen weitere Tricks. Man wird mit diesen eingeschränkten Verfahren keine photorealistischen Effekte erreichen können. Um dennoch eine hohe reale Wirkung zu erzielen, setzt man auf den Oberflächen Texturen ein, die mit lokalen Lichtmodellen überblendet werden, so dass auch bewegte Lichtquellen oder sich im Lichtkegel bewegende Objekte realistisch wirken. Zur Erinnerung: Lokale Lichtmodelle definieren an einem Punkt der Oberfläche Komponenten aus Umgebungslicht, das mit Ambient bezeichnet wird, diffusem Streulicht und spiegelndem Spekularlicht. I = Iambient + Idif f us + Ispecular Das ambiente Licht stellt einen durch Streuung an allen Objekten im Raum vorhandenen Grundpegel an diffusem Licht dar, das keiner speziellen Lichtquelle und damit keiner Richtung zugeordnet ist. Der diffuse Anteil bezieht sich jetzt auf die Summe aller Lichtquellen, deren einstrahlende Intensität mit der diffusen Oberflächeneigenschaft, einer Materialkonstante kd , gewichtet werden. Richtung der Lichtquelle Li und die Normale N gehen in diesen Term ein. Das spiegelnde Licht ist außer von der Materialkonstante ks noch vom Standpunkt des Betrachters abhängig. Hier unterscheidet man im 1.2. BLINN-PHONG, EIN LOKALES LICHTMODELL 3 Wesentlichen das Phong Modell von 1975 I = Ia ka + Ii [kd (L · N ) + ks (R · V )n ] und die Weiterentwicklung zum Blinn-Phong Modell von 1977, dass mit dem Halfway Vektor H auf Hälfte zwischen L und V arbeitet. Dieser Vektor lässt sich einfacher als die Reflexionsrichtung R berechnen. I = Ia ka + Ii [kd (L · N ) + ks (N · H)m ] N H 6 R L (cosϕ)m I @ @ ϕ (cosφ)n @ I φ : @θ V @ Abbildung 1.1. Der diffuse Anteil des abstrahlenden Lichts (grüne Linie) geschieht gleichmäßig in alle Richtungen, der dazu addierte spiegelnde Anteil berechnet sich aus der Betrachterposition V . Das Phong Modell (blaue Linie) benutzt dazu den Reflexionsvektor R, das Blinn-Phong Modell (rote Linie) den Halfway Vektor H auf Hälfte zwischen L und V . 1.2.1 Gerichtete Lichtquellen Als sogenanntes Warn Modell (1983) bezeichnet man ein mit geringem Rechenaufwand erweitertes Phong Modell, bei dem die Quellenintensität zusätzlich vom Winkel ϑ zwischen den Vektoren LN und (−L) abhängt. Der cos ϑ kann wieder über ein Skalarprodukt ausgedrückt werden, mit dem die Intensität gewichtet wird. Dabei sorgt der Exponent s für ein Fokussieren des Lichts: Je größer der Exponent, desto konzentrierter fällt das Licht nur in die ausgezeichnete Richtung LN . I = Ia ka + Ii (LN · (−L))s [kd (L · N ) + ks (N · H)n ] 4 KAPITEL 1. EINFÜHRUNG INS RENDERING Der konische Spot ist eine gerichtete Lichtquelle, bei der ein maximaler Winkel δ angegeben wird. Außerhalb dieses Winkels wird diese Lichtquelle nicht berücksichtigt. HH H @ N 6 ϑ@ @ LN I @ @L @ @θ @ Abbildung 1.2. Quellenintensität hängt von der Richtung ab, in die die Lichtquelle strahlt. 1.3 Cook & Torrance Modell Mit dem Phong-Modell lassen sich plastikartige Oberflächen gut modellieren, es zeigt aber deutliche Mängel bei hochglänzenden, metallischen Oberflächen. Das von Cook und Torrance vorgeschlagene Beleuchtungsmodell von 1982 (siehe [CT82]) ist die physikalisch begründete Vereinfachung der Auswirkungen von Mikrofacetten einer Oberfläche. Die Hauptunterschiede zum Phong-Modell bestehen in der Berücksichtigung der einfallenden Strahlungsenergie, dem Mikrofacetten-Modell für das Spiegellicht, Farbabstufungen im Highlight und die Berücksichtigung des Fresnelschen Gesetzes. Für dieses Modell typische Intensitätsverteilungen wirken sich insbesondere für nahezu tangentiale Einfalls- oder Betrachterwinkel aus. Das maximale Highlight ist dann nämlich NICHT identisch mit der Reflexionsrichtung. Wie sich das an den Rändern einer spiegelnden Kugel auswirkt, wird in Abb. 1.10 illustriert. 1.3.1 Bidirektionale Reflexivität Die einfallende Beleuchtungsstärke Ei = Ii cosθi dωi = Ii (N ·L)dωi wird mit einem Faktor ρ gewichtet zur abstrahlenden Strahldichte Ir = ρIi (N · L)dωi . Dieser Faktor ρ = EIri wird als bidirektionale Reflexivität bezeichnet. Dabei hat ρ = kd ρd + ks ρs mit kd + ks = 1 einen diffusen und einen spiegelnden Anteil. Das ambiente Umgebungslicht wird ebenfalls aus dem gesamten einfallenden Licht berechnet. Daraus ergibt sich 1.3. COOK & TORRANCE MODELL Ir = ρa Ia + 5 X Iij (N · Lj )dωij [kd ρd + ks ρs ] 1≤j≤n In diese von Cook und Torrance angegebene Formel geht der Einfallswinkel (φi , θi ) jeder Lichtquelle Lj ein. Sofern in der bidirektionalen Reflexivität ρ anisotrope Oberflächen modelliert werden, trägt auch der Ausfallswinkel (φr , θr ) zur Veränderung der abstrahlenden Strahldichte Ir bei. Daher ist diese Gleichung eine vierdimensionale sogenannte BRDF. Abbildung 1.3. Geometrie von einfallenden und reflektierten Elementarstrahlen auf der Oberflächeneinheit dA . Mit der Bidirectional Reflectance Distribution Function (BRDF) bezeichnet man allgemein die Modellierung, bei der die einfallende Energiemenge und die abstrahlende Intensität in einen funktionalen Zusammenhang gesetzt werden. Symbolisch notiert man die BRDF als fr fr (θi , φi ; θr , φr ) ≡ dLr (θi , φi ; θr , φr ; Ei ) dEi (θi , φi ) 6 KAPITEL 1. EINFÜHRUNG INS RENDERING wobei θ und φ zusammen eine Richtung, der tiefgestellte Index i die Größen für den einfallenden Strahlungsfluss, der tiefgestellte Index r die Größen für den reflektierten Strahlungsfluss bezeichnen. Ei ist die Bestrahlungsstärke (oder einfallende Strahlungsintensität), Lr ist die reflektierte Strahlung (Remission). Mit d wird das Differential bezeichnet. Damit ist eine BRDF eine Verteilungsfunktion, die die Bestrahlungsstärke aus einer bestimmten Richtung und ihren Anteil an der Remission in eine andere Richtung in Beziehung setzt. Diese Funktion wird in der reziproken SI-Einheit Steradiant gemessen, [sr−1 ]. Zur Erinnerung: Mit Radiant [rad] bezeichnet man den ebenen Winkel, bei dem ein Vollkreis = 2π [rad] sind, mit Steradiant [sr] bezeichnet man den Raumwinkel, bei dem eine volle Sphäre = 4π [sr] sind. Für den ganz allgemeinen Fall betrachtet man auch die in das Material eindringende Strahlung und modelliert das Streuen aus tieferen Schichten (subsurface scattering). Diese Funktion ist entsprechend höherdimensional und wird mit BSSRDF bezeichnet. Für unsere Zwecke reicht aber zunächst ein verbessertes Oberflächenmodell, um den spekularen Anteil ρs an der bidirektionalen Reflexivität zu modellieren. ρs = F DG π(N · V )(N · L) (1.1) Dieser Anteil setzt sich aus dem Fresnelterm F , einer Verteilungsfunktion D und einer geometrischen Abschwächung G zusammen, wobei eine Wichtung mit den Proportionalitätsfaktoren (N · V ) (Was sieht der Betrachter von der Oberfläche?) und (N · L) (Was sieht“ das Licht von der Oberfläche?) ” sowie π (Maß für die Hemisphäre) vorgenommen wird. 1.3.2 Distributionsfunktion des Mikrofacettenmodells Torrance and Sparrow haben 1967 ein verbessertes Oberflächenmodell, das sogenannte Mikrofacettenmodell vorgestellt, das von Cook und Torrance schließlich in das Lichtmodell integriert wurde. Dabei wird angenommen, dass die Oberfläche eines glatt erscheinenden, matten Objekts aus perfekt spiegelnden Mikrofacetten zusammengesetzt ist. Eine Verteilungsfunktion D gibt dabei an, wie groß der Anteil der Facetten ist, deren Normale um den Winkel β von der mittleren Normale der Oberfläche abweicht. Torrance and Sparrow verwendeten eine einfache Gaußverteilung für den Anteil der in Betrachterrichtung reflektierenden Facetten: D = k exp(−(β/m)2 ) Dabei ist β = arc cos (N · H) die mittlere Winkelabweichung von der mittleren Flächennormale N bei einer mittleren Steigung von m. Hiermit wird also der Anteil der Mikrofacetten ermittelt, 1.3. COOK & TORRANCE MODELL 7 Abbildung 1.4. Mikrofacettenmodell: Links auf Abstand betrachtet, in der Mitte ist die Spiegelung und damit Streuung an den einzelnen Facetten skizziert, rechts die Verschattung durch V-förmige Kerben. deren Normale genau in Betrachterrichtung V weist, also einer Normalen H entspricht. Die mittlere Steigung m wird als root mean square (rms) bestimmt, d.h. als mittleres arithmetisches Mittel aller quadrierten infinitesimal kleinen Steigungen, wobei aus diesem Term dann die Wurzel gezogen wird. Somit ist m (ob gemessen oder abgeschätzt) ein Maß für die Rauigkeit der Oberfläche und m = 0 entspricht einem perfekt spiegelnden Objekt (wobei man dann keine Verteilungsfunktion braucht, da hierfür die mittlere Normale gleich der eigentlichen Normalen ist. Zudem darf nicht durch 0 geteilt werden!), m >> 0 einem matten Objekt. Eine geeignete Materialkonstante k kann experimentell ermittelt und linear an das Modell angepasst werden. Abbildung 1.5. Links Gaußverteilung und rechts Beckmannverteilung für oben m = 0.2 und unten m = 0.6 Beckmann schlägt dagegen eine verbesserte Modellierung vor, die im Cook-Torrance Modell benutzt wird: 8 KAPITEL 1. EINFÜHRUNG INS RENDERING 1 tan2 β D= exp − 2 . 4m2 cos4 β m Diese Beckmannverteilung kommt ohne eigene Materialkonstante aus, da ihr Vorfaktor bereits aus den Parametern m und β berechnet wird, die die Oberflächenbeschaffenheit beschreiben. Nicht jede Oberfläche hat Facetten von immer annähernd gleicher Größe, sondern zeigt auf jeder Facette nochmal kleinskaligere Unterteilungen. Hierfür kann man ein sogenanntes Multiskalenmodell anwenden: D= X wj D(mj ) j wobei mj die mittlere P Steigung der j-ten Verteilung und wj eine Wichtung dieser j-ten Verteilung ist. Es gilt natürlich wj = 1. Außerdem sollte eine isotrope Verteilung auf allen Skalen gelten. Wenn verschiedene Skalen eine Vorzugsrichtung aufweisen, ist dieser Umstand von einer symmetrischen Verteilungsfunktion nicht zu erfassen. Abbildung 1.6. Mikrostrukturen können unterschiedliche Skalen aufweisen, die einander auch überlagern können. 1.3.3 Geometrische Abschwächung durch Mikrofacetten Auch für die sogenannte geometrische Abschwächung ist die isotrope Verteilung der Mikrofacetten vorausgesetzt. Unter der Annahme, dass diese Mikrofacetten V-förmige Kerben sind, die symmetrisch zur mittleren Flächennormalen N verteilt sind, kann man sich drei Fälle vorstellen. Abbildung 1.7. a) Vollsicht b) flacher Einblick c) flacher Lichtwinkel 1.3. COOK & TORRANCE MODELL 9 Im Fall a) hat der Betrachter V vollen Einblick auf alle Facetten und auch das Licht L scheint aus einem Winkel auf die Fläche, der wenig von der mittleren Normalen N abweicht und erzeugt daher keine Schatten. Meist ist das sogar für Betrachter- sowie Lichtwinkel von bis zu 70◦ der Fall. Sollte aber der Betrachter wie in Fall b) sehr flach auf die Fläche blicken, kann ein Teil der Mikrofacetten nicht eingesehen werden. Dieser Anteil b (blind) ist aus Symmetriegründen beim Vertauschen von V und L auch genau der Bereich, der vom Licht nicht erreicht wird, wie in Fall c). Die geometrische Abschwächung G wird also Werte zwischen G = 0 (totale Beschattung) und G = 1 (volle Einsicht) annehmen müssen. Für die jeweiligen Fälle bedeutet das Ga = 1 und Gb = Gc = 1 − l−b b = , l l wobei l die Länge der (eindimensionalen) Mikrofacette und b den aus Betrachter oder Lichtrichtung verschatteten Bereich bezeichnet. Die geometrische Abschwächung ist dabei von der Größe und Steigung der Mikrofacetten unabhängig (ausführlich beschrieben von Blinn, 1977 [Bli77]). Diese Oberflächeneigenschaften sind bereits in die Verteilungsfunktion D eingegangen und auch vollständig abgehandelt. Jetzt modelliert man Gb = 2(N · H)(N · V ) (V · H) Gc = 2(N · H)(N · L) (L · H) und entsprechend und berücksichtigt, dass (L · H) = (V · H) per Definition des Halfway-Vektors H gilt. Dann lässt sich für geometrische Abschwächung schließlich schreiben 2(N · H)(N · V ) 2(N · H)(N · L) , . G = min 1, (V · H) (V · H) 1.3.4 Fresnelterm Bisher wurde noch nicht modelliert, dass das Maximum des Highlights nicht mit der Reflektionsrichtung R übereinstimmt, dass also Intensität und auch Farbe des reflektierten Lichts von der Brechung des Lichts an der Schichtgrenze abhängt. Ein Teil der Energie wird bei Lichtbrechung geschluckt, so dass der reflektierte Teil mit geänderter Wellenlänge eine Intensitäts- und Farbverschiebung bedeutet. Der französischen Physiker Auguste Jean Fresnel (1788 - 1827) entdeckte, dass die Brechung des Lichts an Schichtgrenzen nur vom Einfallswinkel und nicht von der Dicke des Materials abhängt. 10 KAPITEL 1. EINFÜHRUNG INS RENDERING Abbildung 1.8. Profile mit gleicher Bündelung des Lichts: Fresnellinse (1) und glattes Profil (2). Rechts eine alte Schiffslaterne mit Fresnel-Kugellinse. Die Fresnellinse nutzt diese Tatsache und findet auch heute noch zur Bündelung von Licht ihre Verwendung beispielsweise in Leuchttürmen, Baulaternen oder als Folie auf Fensterscheiben, wobei eine Lupenwirkung erzeugt wird. 6 N @ I @ @ @ L @ θi @ optisch dünneres Medium optisch dickeres Medium @ @ A A A θt AA AAU Abbildung 1.9. Lichtbrechung an einer Schichtgrenze Das Brechungsgesetz an der Schichtgrenze zwischen Medium 1 und Medium 2 lautet: η1 sin θ1 = η2 sin θ2 Der Fresnelterm F = F (θi , θt ) hängt nun vom Einfallswinkel des Lichts und vom Brechungswinkel 1.3. COOK & TORRANCE MODELL 11 des Mediums ab. Damit ist dieser Term veranwortlich für das im Brechungswinkel geschluckte Licht an einer spiegelnden Oberfläche. 1 F (θi , θt ) = 2 sin2 (θi − θt ) tan2 (θi − θt ) + sin2 (θi + θt ) tan2 (θi + θt ) Durch Umformung des tan α = sin α/cos α ergibt sich 1 sin2 (θi − θt ) cos2 (θi + θt ) F (θi , θt ) = 1+ , 2 sin2 (θi + θt ) cos2 (θi − θt ) so dass dieser Ausdruck jetzt in üblicher Weise umgeschrieben werden kann. Fasst man nämlich F θi cos θt als jetzt mit c = cos θi und g = sin sin θ t 1 F = 2 (g − c)2 (g + c)2 (c(g + c) − 1)2 1+ (c(g − c) + 1)2 (1.2) auf, so ergibt sich g 2 = η 2 + cos2 θi − 1. Hierbei ist der Brechungsindex η zu bestimmen aus ηt sin θt = η sin θt = sin θi . ηi Das Medium Luft hat einen Wert ηi ≈ 1, so dass der Wert von ηt ηi = η ≈ ηt ist. Bemerkung 1.1 Für die Anwendung hier in der Computergraphik stellt sich der Winkel c = cos θi = (L·H) dar, denn wir betrachten ideale Mikrofacetten, deren Spiegellicht ausschließlich in Betrachterrichtung reflektiert wird. Die Normale des Fresnelterms wird also durch die hypothetische Normale H ersetzt. Bemerkung 1.2 Der Fresnelterm bestimmt auch die Farbveränderung des Highlights als Funktion dieser beiden Winkel, Einfallswinkel und Transmissionswinkel, und zwar über die Wellenlängenabhängigkeit des Brechungsindex η = ηλ . Insgesamt erleichtert sich die Berechnung für extreme Einfallswinkel θi = 0 bzw. θi = π/2. Schreibt man nämlich den Fresnelterm F = F (θi , ηλ ) wie in Gleichung (1.2) um, gilt für den normalen Einfallswinkel θi = 0 (entlang der Normalen N , also für ein Headlight oder Kameralicht), dass F = F (0, ηλ ) gerade 1 F (0, ηλ ) = 2 (ηλ − 1)2 (ηλ + 1)2 ·2= ηλ − 1 ηλ + 1 2 12 KAPITEL 1. EINFÜHRUNG INS RENDERING nämlich über c = 1 und g 2 = ηλ 2 + 1 − 1 , also g = ηλ ergibt. Achtung! Da bei normalem Einfallswinkel θi = θt = 0 ist, ergibt sich sin θi = sin θt = 0. Man darf g nicht direkt in Null auswerten, da nicht nur der Zähler sondern auch der Nenner Null wird und man sonst durch Null teilt! Jetzt kann man einen wellenlängenabhängigen Brechungsindex ηλ bestimmen und damit den Fresnelterm generell wellenlängenabhängig machen. ηλ = p F0,λ p 1 − F0,λ 1+ Damit ist die Abhängigkeit des Fresnelterms von der Wellenlänge Fλ = F (θi , ηλ ) aus der Gleichnug für F bei θi = 0 bestimmbar. Wenn das Licht die Oberfläche nur streift, also für den anderen Grenzfall θi = π/2, ergibt sich aus Gleichung (1.2) mit c = 0, dass F (π/2, ηλ ) ≡ 1 gilt. Hier sieht man, dass der Fresnelterm für diesen Winkel und sämtliche Materialien immer konstant 1 ist und sich damit neutral im spiegelnden Anteil der bidirektionalen Reflexivität ρs verhält. Abbildung 1.10. Links ohne, rechts mit Fresnelterm berechnete Reflexion (Quelle: Stephen H. Westin, http://www.graphics.cornell.edu). Die Vorgehensweise zur Bestimmung des Fresnelterms in Abhängigkeit von sämtlichen Wellenlängen und allen möglichen Einfallswinkeln geschieht nun, indem man sich aus den Messgrößen für gegebene Materialien und einer für die RGB-Komponenten einzeln durchgeführten Interpolation die gesamte Fläche berechnet. Nun kann man den spiegelnden Anteil ρs an der Bidirektionalen Reflexivität ρ = EIri tatsächlich nicht nur an einzelnen Punkten messen, was sehr diskontinuierliche Ergebnisse liefert, sondern mit der Gleichung (1.1) modellieren. 1.3. COOK & TORRANCE MODELL 13 Abbildung 1.11. Fresnelterm als Funktion von Einfallswinkel und Wellenlänge. Bemerkung 1.3 Bei Streiflicht gilt F (π/2, ηλ ) ≡ 1. Damit wird die Farbe des Pixels genau die Farbe der Lichtquelle erhalten. Die Materialfarbe wird im RGB-System über die drei Farbkanäle angegeben. Ebenso verfährt man mit der Farbe des Lichts. Nun machen wir die einzelnen Farbkanäle vom Einfallswinkel abhängig, wobei wir die Werte bei 0 und π/2 bereits kennen oder messen können. Red0 Redπ/2 für für θi = 0 θi = π/2 Rotkomponente des Materials Rotkomponente des Lichts Am Beispiel der Rotkomponente müssen wir also Red0 aus F0 , dem Spektrum des einfallenden Lichts und den Farbfunktionen des CIE-Diagramms berechnen. Damit ergibt sich Redθi = Red0 + (Redπ/2 − Red0 ) max(0, Fave,θi − Fave,0 ) Fave,π/2 − Fave,0 als eine lineare Interpolation zwischen dem Materialrot Red0 und dem Lichtrot Redπ/2 , bei der Fave,θi einen über alle Wellenlängen gemittelten Fresnelterm meint. Bemerkung 1.4 Ein spektralabhängiger Fresnelterm kann nicht als Summe dreier Farbkomponenten wiedergegeben werden. Daher kommt es zu Ungenauigkeiten. 14 KAPITEL 1. EINFÜHRUNG INS RENDERING Abbildung 1.12. Kupferdarstellung im Comic: Asterix und der Kupferkessel. Roy Hall dagegen schlägt vor, NICHT komponentenweise vorzugehen, sondern den Freselterm für jede Wellenlänge zu bestimmen. Fλ,θi = Fλ,0 + (1 − Fλ,0 ) max(0, Fave,θi − Fave,0 ) 1 − Fave,0 Bemerkung 1.5 Bei anisotroper Oberfläche, z.B. gebürstete Metalloberflächen oder gekämmte Haare, liegen orientierte Mikrostrukturen vor, die nicht gleichmäßig zur Oberflächennormalen verteilt sind. Hier kann man eine veränderte Normale benutzen, in die die Tangente an die Hauptstrukturrichtung eingeht. Bemerkung 1.6 Der Fresnelterm gilt in dieser Form nur für unpolarisiertes Licht. Der Polarisationsgrad ändert sich, wenn Licht von einer Oberfläche mit Mikrostruktur reflektiert wird. Metalloberflächen polarisieren wellenlängenabhängig: Licht unterschiedlicher Wellenlänge wird unterschiedlich stark polarisiert. 1.4 Übungsaufgaben Aufgabe 1.1 Transformationen über gluLookAt() Schreiben Sie in OpenGL ein Programm, das ein Koordinatenkreuz mit Achsenbeschriftung und ein beliebiges Objekt darstellt. Steuern Sie die Transformationen über Veränderungen des Befehls void gluLookAt(GLdouble eyeX,.Y,.Z, GLdouble centerX,.Y,.Z, GLdouble upX,.Y,.Z). Machen Sie diese Transformationen vom Drücken der linken Maustaste und dann der Bewegung der Maus in x- 1.4. ÜBUNGSAUFGABEN 15 oder y-Richtung abhängig. Legen Sie den Zoom auf die mittlere Maustaste, damit die rechte Maustaste für eine Menüsteuerung mit einem Eintrag für Quit belegt werden kann. Aufgabe 1.2 Gerichtete Lichtquelle Stellen Sie in OpenGL eine gerichtete Lichtquelle als Objekt dar. Achten Sie dabei darauf, dass ein konischer Lampenschirm sich entsprechend des eingestellten Winkels Ihres Lichts öffnet. Lassen Sie dieses Licht auf ein möglichst fein unterteiltes Objekt scheinen, das eine metallische Materialeigenschaft trägt. Abbildung 1.13. Schreibtischlampe mit Star-Charakter: Das Logo von Pixar. Abbildung 1.14. Realer Nachbau des Logos für die Pixar Ausstellung in Melbourne, September 2007. 16 KAPITEL 1. EINFÜHRUNG INS RENDERING Aufgabe 1.3 Umformung des Fresnelterms Der Fresnelterm F = F (θi , θt ) hängt vom Einfallswinkel des Lichts und vom Brechungswinkel des Mediums ab. 1 F = 2 sin2 (θi − θt ) tan2 (θi − θt ) + sin2 (θi + θt ) tan2 (θi + θt ) wird üblicherweise umgeschrieben zu 1 (g − c)2 F = 2 (g + c)2 (c(g + c) − 1)2 1+ (c(g − c) + 1)2 mit c = cos θi und g 2 = η 2 + cos2 θi − 1. Dadurch erleichtert sich die Berechnung für extreme Einfallswinkel θi = 0 bzw. θi = π/2. a) Führen Sie diese Umformung durch. Hinweis: Beachten Sie die Additionstheoreme für die Winkelfunktionen sowie den Zusammenhang zwischen dem Brechungsindex η und den entsprechenden Winkeln, nämlich η sin θt = sin θi . Finden Sie einen wurzelfreien Ausdruck für g. b) Zeigen Sie, wie sich F = F (0, θt ) und F = F (π/2, θt ) für alle Medien vereinfacht. Kapitel 2 Graphikkarten Programmierung Moderne Grafikkarten sind dafür ausgelegt, den Prozess des Renderings eines Bildes sehr schnell auszuführen, um in Echtzeit Animationen mit qualitativ möglichst hochwertigen Effekten zu berechnen. Dabei resultiert der Geschwindigkeitsvorteil aus der einfach parallel zu bearbeitenden Bildberechnung, die auf die einzelnen Prozessoren einer GPU verteilt werden kann. Außerdem werden Vektoroperationen oder Matrix-Vektor-Produkte in einem einzigen Aufruf über sogenannte Packed arrays berechnet. Diese Single Instruction Multiple Data (SIMD) Berechnungen sind eine Art Rückkehr des Vektorrechners aus der Ecke der Hochleistungsrechner auf die Ebene der PC-Technologie. Früher musste der Programmierer zu einer Assembler-Sprache greifen und den Code auf den eingesetzten Grafikchip direkt anpassen, inzwischen gibt es dafür Hochsprachen (siehe [FK03]). Das macht es wiederum interessant, auf der GPU auch Berechnungen vorzunehmen, die typischerweise parallelen Code auf der CPU erfordern, wie beispielsweise Filterverfahren der Bildverarbeitung, aber auch einfache finite Differenzen für partielle Differentialgleichnungen, deren Ortsabhängigkeiten oder Geschwindigkeitsfelder in Texturen gespeichert und über Texturzugriffe neu berechnet werden können. 2.1 Shader Programmierung Die Idee der Shader stammt aus den großen Studios für Animationsfilme. Ende der 80er Jahre wurde bei Pixar für ihr Rendering-Interface Renderman eine eigene Shader-Sprache entwickelt. Die Anwendung beschränkte sich jedoch auf das relativ langsame Batch-Rendering einzelner Filmframes. Mit einem Shader berechnen die Renderer für jeden Geometriepunkt respektive dargestellten Pixel das Aussehen, statt nur statisch eine einzige Farbe oder Textur zu verwenden. Trotz einfacher Geometrie erscheinen damit gerenderte Objekte mit komplexer Oberflächenstruktur. Diese Idee geht auf eine frühe Arbeit von Robert Cook [Coo84] zurück, der den Ablauf des Shading in einer Baumstruktur organisiert hat. In diese Bäume an unterschiedlichen Stufen eingreifen zu können, genügt ein rein knotenbasierter Ansatz nicht. Auf der viel tiefer liegenden Ebene der Rasterung dagegen erzielt man wie der Name schon sagt, das bessere Shading, die mit den Nachbarpunkten des Gitters abgestimm17 18 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG te Abstufung. Moderne Grafikkarten beherrschen diese Technologie in Echtzeit. Der Programmierer lädt seinen Shader-Code in die GPU. Die Graphikkarte führt diesen Code während des Renderings sehr schnell für jeden einzelnen Punkt aus. Dabei kann das Bild einfach parallel berechnet werden, in dem es in Bereiche zerlegt und auf die einzelnen Prozessoren einer GPU verteilt wird. Im Renderprozess sind Vektoroperationen oder Matrix-Vektor-Produkte über Packed arrays auszuführen. Statt in Assembler und für einen speziellen Grafikchipsatz kann die GPU heute in einer Hochsprache angesprochen werden. Die Besonderheit liegt darin, dass der Compiler den in einer solchen Sprache abgefassten Shader in Code für die jeweilige GPU während der Ausführung übersetzt. Shader beschreiben keine Geometrien oder Objekte, das ist immer noch die Aufgabe von APIs wie OpenGL oder Direct3D. Aber sie beeinflussen, wie die Grafikkarte Transformationen, Licht und Farben verarbeitet. An dieser Stelle wird es nötig, den Begriff Fragment deutlich vom Pixel zu unterscheiden. Während ein Pixel die kleinste Einheit auf dem Rasterschirm darstellt, umfasst das Fragment wesentlich mehr Information und ist die abstraktere und von der anzusteuernden Hardware losgelöste Variante einer kleinsten Rastereinheit. Mit an die Graphikprozessoren übergebenen Knoten (Vertices) und mit diesen Fragmenten kann nun auf der Graphikkarte operiert werden, ohne dass die CPU in diesen Vorgang eingreifen muss. Zur Erinnerung: Buffer beinhalten gleichmäßig für alle Pixel des Graphikfensters (oder des Bildes bei Offscreen-Rendering) gespeicherte Informationen. Sichtbar ist nur der (Front Left, Front Right) Colorbuffer. Der Framebuffer ist die Vereinigung sämtlicher Buffer. Definition 2.1 Ein Fragment ist in der Computergraphik der Begriff für sämtliche Daten, die benötigt werden, um den Farbwert des Pixels im Colorbuffer zu erzeugen. Das beinhaltet (aber ist nicht beschränkt auf): • Rasterposition • z-Tiefe • Interpolierte Attribute (Farbe, Texturkoordinaten , etc.) • Einträge im Stencilbuffer • Alphawerte • Window ID Man denke sich das Fragment als die Vereinigung alle Daten, die benötigt werden, um den Farbwert des Pixels zu bestimmen, zusammen mit allen Daten, mit denen getestet wird, ob der Colorbuffer überhaupt erreicht wird. 2.2. SHADE TREES 2.2 19 Shade trees Um den Illuminationsprozess und Schattierungen zu modularisieren, hat man entsprechende Shader implementiert. Der nächste Entwicklungsschritt betraf Entscheidungsbäume, um diese verschiedenen Shader und Kombinationen in einem Programm benutzbar und zur Laufzeit entscheidbar einzusetzen. Zum Beispiel stammt von Whitted (1982) die Idee eines Scanline Algorithmus, bei dem eine verkettete Liste einzelner Spans mit der Information (z-Werte, Normalen) an den jeweiligen Eckpunkten assoziiert wird. Diese Idee konnte sich allerdings nicht gegen eine stärker objektorientierte Beschreibung durchsetzen, wie sie im Format des Renderman Interface Bytestream (RIB) festgehalten ist. Definition 2.2 Ein Shade tree besitzt eine Baumstruktur, in deren Knoten Parameter der Kinderknoten eingehen und daraus Parameter für die darüberliegenden Elternknoten produzieren. Die Parameter sind dabei Werte für einzelne Terme und Begriffe, die man aus Beleuchtungsmodellen kennt, z.B. der Spekularkoeffizient ks oder Oberflächennormalen. In den Knoten werden diese Parameter aus darunterliegenden Halbbäumen gesammelt und weiter bearbeitet, um schließlich die Farbgebung des Pixels zu erhalten. So werden z.B. Knoten als Spekularterm, Ambienter Term aber auch Square root oder Mix-Knoten bezeichnet. Abbildung 2.1. Shade tree für Kupfer, nach Robert L. Cook [Coo84]. Unterschiedliche Objekte können verschiedene Schattierungsbäume haben. Der Mix-Knoten erlaubt das Mischen spezieller Shader für besondere Zwecke wie beispielsweise Holzmaserung. Bemerkung 2.1 Außer Shade trees gibt es zur Modellierung von Licht sogenannte Light trees und zur Modellierung von atmosphärischen Effekten entprechend Atmosphere trees. 20 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG Abbildung 2.2. Der mix-Knoten in einem Shade tree, nach Robert L. Cook [Coo84]. Lichter und ihre Parameter werden genau wie Objekte behandelt. Lichtberechnung und Streuung in der Atmosphäre hängt vom Betrachterstandpunkt und der z-Tiefe ab. Abbildung 2.3. Ein Light tree gibt die Lichtposition zurück, nach Robert L. Cook [Coo84]. Bemerkung 2.2 Häufig interessiert bei einem Highlight NICHT die Position der erzeugenden Lichtquelle sondern nur, WO es erscheint. Also möchte man ein Highlight positionieren und die Lichtrichtung als Ergebnis erhalten. Ein entsprechender Light tree ist in Abb. 2.3 gezeigt. Beispiel 2.1 Ein benutzerseits definierter Shader kann die Welt aus der Sicht einer Biene (andere Wahrnehmung der Spektralfarben) wiedergeben. Beispiel 2.2 Relativitätsaspekte wie die spektrale Verzerrung bei Lichtgeschwindigkeit kann in einem Shader implementiert werden. Dabei werden Projection trees nötig, die neben den Standardprojektionen wie paralleler und linear perspektivischer Projektion auch den gekrümmten Raum darstellen können. Durch den Doppler Effekt entsteht eine Farbverschiebung, bei der sehr schnell unser übliches Farbspektrum rekalibriert werden muss, da ansonsten alle Farben, auf die man zufliegt, zu weiß überstrahlen. 2.2. SHADE TREES 21 Abbildung 2.4. Tübingen, links: relativistisch verzerrt, rechts auch unter Berücksichtigung des Doppler Effekts bei der Ausbreitung des Lichts. Bilder von Ute Kraus. 2.2.1 Reyes-Pipeline und Renderman Interface Cook, Carpenter und Catmull gelten als die Urheber der sogenanten Reyes-Pipeline (siehe Abb. 2.5). Die geographische Nähe der Lukasfilm Studios zu Point Reyes (siehe Abb. 2.6) hat dem Akronym aus Renders everthing you ever saw sicherlich Vorschub geleistet. Renderman greift diese Pipeline auf und speichert in sogenannten RIB-Files, dem Renderman Interface Bytestream die Punkte auf der Oberfläche eines Objekts, ihre Orientierung und die Lichtquellen und übergibt diese einem Surface shader, der daraus Lichtfarbe und Lichtrichtung bestimmt. Wie aus Abb. 2.5 hervorgeht, stellt das RIB-File die Eingabe für Programme wie beispielsweise 3Delight dar, die Renderman Formate lesen und in Bilddaten ausgeben können. Renderman ist auf das (Nach-) Bearbeiten einzelner Frames spezialisiert und beschränkt. Das Programm hat nicht den Anspruch, Animationen zu erstellen, also zwischen einzelnen Bildern zu vermitteln. 2.2.2 Dicing oder Würfelalgorithmus Ähnlich zu Catmulls Subdivision Algorithmus für Pixel werden beim Dicing alle Objekte in Mikropolygone zerlegt, deren Kantenlänge Subpixelgröße hat (Beispielsweise 1/2 Pixel). (1) Dicing geschieht vor der perspektivischen Transformation, d.h. man schätzt die Größe der Mikropolygone aufgrund der anschließenden perspektivischen Transformation. (2) Schattierung geschieht in Weltkoordinaten. Da alle quadrilateralen Polygone unter Pixelgröße sind, kann mit einfachem Flatshading gearbeitet werden, das nur einen Farbwert für jedes Polygon kennt. (3) Das Bild wird in einzelne Rechtecke unterteilt, um nicht alle Gitter von Mikropolygonen und Subpixelinformationen für das gesamte Bild sequenziell abarbeiten zu müssen. Auf diese Weise ist 22 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG Abbildung 2.5. Reyes-Pipeline. der Algorithmus leicht parallelisierbar. (4) Jedes Objekt wird mit der linken oberen Ecke seiner Bounding Box in das Rechteckgitter einsortiert. Die Bildbereiche werden nun von links nach rechts und von oben nach unten abgearbeitet. Im Speicher muss nur die Information für einen Bildbereich gehalten werden, mit Ausnahme der z-Werte, so dass die Speichertiefe des z-Buffers limitierend ist. 2.3 C for graphics Mit der Programmbibliothek C for graphics (Cg) entstand 2002 ein verlässlicher Standard zur Ansteuerung der programmierbaren Teile eines Graphikprozessors. Bis dahin musste für jede Graphikkarte ein eigenes Interface zum Beispiel in Assembler geschrieben werden, was einerseits eine Hürde für viele Programmierer darstellte und andererseits das Portieren der Anwenderprogramme extrem schwierig machte. 2.3. C FOR GRAPHICS 23 Abbildung 2.6. Road to Point Reyes, eine Simulation aus Shade trees von Robert L. Cook [Coo84], und die Landkarte mit der entsprechenden Stelle. Die Entwicklung von Cg wurde von Bill Mark bei NVIDIA in enger Kooperation mit Microsoft betrieben, womit die beiden entscheidenden Plattformen für Graphikentwicklung, nämlich OpenGL und Direct3D abgedeckt wurden. Über das Cg Tutorial von Fernando und Kilgard (siehe [FK03]), das auf der SIGGRAPH 2003 zum Bestseller wurde, fand die Sprache rasche Verbreitung. Als rufende Programme sind Applikationen in beiden Graphikbibliotheken gleichermaßen möglich, und Cg-Programme brauchen diesen APIs nicht angepasst werden. Dabei speist sich die Cg-Bibliothek aus drei wesentlichen Quellen (siehe Abb. 2.7), nämlich der in der Graphikprogrammierung weit verbreiteten Programmiersprache C/C++, der aus der Reyes-Pipeline motivierten Shading Language und den 3D APIs OpenGL und Direct3D. Abbildung 2.7. Die Programmbibliothek C for graphics (Cg) speist sich aus drei Quellen. 24 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG Die folgende Skizze (Abb. 2.8) zeigt eine vereinfachte Graphikpipeline, über der man sich jede 3DApplikation oder ein Computerspiel denken kann, das mit OpenGL oder Direct3D Anweisungen auf der CPU implementiert bleibt. Programmierbare Teile des Graphikprozessors sind der Vertex- (blau hinterlegt) und der Fragmentprozessor (rot hinterlegt). Moderne Graphikkarten haben heute 16 bis 32 parallele Prozessoren in der Pixelpipeline, die das Rendering entsprechend beschleunigen. OpenGL Anweisungen ? Vertex-Verarbeitung - Rasterung Transformationen Licht- und Farbberechnung - Pixel-Verarbeitung - Framebuffer Pixelbezogene Farbberechnung Abbildung 2.8. Vereinfachte OpenGL-Grafik-Pipeline. Die Teile, die sich bei neueren Grafikkarten frei programmieren lassen, sind farbig hinterlegt. 2.3.1 Cg - Historische Entwicklung Die historische Entwicklung in der Zeitachse macht deutlich, wie sich seit den siebziger und speziell in den achtziger Jahren parallele Stränge abzeichnen, die alle das gleiche Ziel hatten, nämlich ein am Objekt orientiertes Bild schnell und in guter Qualität auf den Schirm bringen zu wollen (siehe Abb. 2.9). Es wird ebenfalls deutlich, dass sich Standards nur dann durchsetzen, wenn sich eine kritische Firmenmasse auf diese Standards einlässt. Projekte wie NeXT sind über die Zeit eingestellt worden. 2.3.2 Programmierbarer Vertex Prozessor Untransformierte Knoten (Vertices) aus einem GPU-Frontend werden typischerweise als Vertex-IndexStream zu Graphikprimitiven zusammengestellt, um als Polygone, Linien und Punkte gerastert werden zu können. An dieser Stelle können die Knoten für eine optimale Darstellung transformiert und neu geordnet werden. Dadurch ist dieser Teil grundsätzlich programmierbar geworden und lässt natürlich auch eigene Programmierung zu, die vor allem zur Laufzeit interessant wird, wenn beispielsweise eine geänderte Transformation eine andere Dreieckszerlegung eines Polyeders erfordert. 2.3. C FOR GRAPHICS 25 Abbildung 2.9. Die historische Entwicklung im Überblick. 2.3.3 Programmierbarer Fragment Prozessor Die schließlich gerasterten und für Interpolationen vortransformierten Fragmente sind über die Ortsangaben der Pixel (Pixel location stream) in der Pipeline auf dem Weg zum Colorbuffer. Im Fragmentprozessor erhalten sie ihre endgültige Schattierung häufig erst durch Texturen, die im Fall prozeduraler Texturen auch wieder notwendig während der Laufzeit anzupassen sind. Schon einfaches Mipmapping setzt voraus, dass eine Entscheidung für die eine oder andere Textur von der Größe des ankommenden Graphikprimitivs abhängt. Gerasterte vortransformierte Fragmente werden weiteren Transformationen unterzogen: Bumpmapping und generelles Beeinflussen der Lichtmodelle ist auf dieser Ebene leicht und vor allem schnell möglich. 2.3.4 CgFX Toolkit und Austauschformat Ein standardisiertes Austauschformat zur Darstellung von Effekten setzt saubere Schnittstellen zu den verschiedenen Graphikkarten voraus, die derzeit auf dem Markt erhältlich sind. Dann aber garantiert 26 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG Abbildung 2.10. Aufbau des programmierbaren Vertex Prozessors. es auch die Verbreitung der nötigen Bibliotheken, die diesen Standard unterstützen. Je mehr große Software-Pakete solche Austauschformate in ihren Code aufnehmen, um so stärker wird sich die spezielle Implementierung verbreiten. Verlässlichkeit wird auf diese Weise propagiert. Mit CgFX, einem Produkt von Microsoft und NVIDIA, wurde ein Austauschformat entwickelt, das textbasiert, also lesbar und editierbar ist. Gebräuchliche Suffix ist *.fx. CgFX geht in den folgenden Punkten über Cg hinaus: 1. Mechanismus für multiple Renderpfade 2. Beschreibung von nichtprogrammierbarem Renderstatus (Alpha-Test-Modus, Texturfilter) 3. Zusätzliche Annotation für Shaderparameter Darüber hinaus wurde ein CgFX Toolkit zur Verfügung gestellt, das einen CgFX Compiler benötigt, um zur Laufzeit ausführbare GPU Anweisungen zu erstellen. Auf dieser Basis sind Plugin-Module für sogenanntes Digital Content Creation (DCC) möglich. Eine Beispieldatei ist am Ende dieses Kapi- 2.3. C FOR GRAPHICS 27 Abbildung 2.11. Aufbau des programmierbaren Fragment Prozessors. tels in Abb. 2.14 dargestellt. Alle großen Animationsprogramme (Alias|Wavefront’s Maya, discreet’s 3dStudioMax und Softimage|XSI) unterstützen Cg über CgFX und DCC Applikationen. 2.3.5 Compiler und Bibliotheken KEINE GPU kann ein Cg-Programm direkt ausführen. Es muss zunächst kompiliert werden. Dazu wählt man ein 3D Programming Interface entweder in OpenGL (Prefix der Syntax: cgGL) oder in Direct3D (Prefix der Syntax: cgD3D). Das dynamische Kompilieren (Kompilieren zur Laufzeit!) wird über Cg-Bibliotheksaufrufe durchgeführt. Dazu besteht die Cg-Bibliothek aus (a) Cg-Runtime instructions und (b) Cg-Compiler instructions. Während ein C-Programm Dateien lesen und schreiben, über Standardschnittstellen mit dem Terminal oder anderen Eingabeformen bedient werden, Graphiken anzeigen und über Netzwerk kommunizieren kann, geht das alles mit Cg nicht. Ein Cg-Programm kann NUR Positionen, Farben, Texturkoordinaten; Punktgrößen und uniforme Variablen entgegennehmen, Berechnungen durchführen und Zahlenwerte zurückgeben. Im Application Programming Interface (API) (siehe das OpenGL Beispiel 2.6) wird die nötige Headerdatei geladen. 28 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG Abbildung 2.12. Das CgFX-Austauschformat wird an den Cg-Kompiler übergeben. #include <Cg/cg.h> Diese Headerdatei wiederum lädt aus dem Standardpfad /usr/include/Cg die weiteren Header: #include #include #include #include #include <Cg/cg_bindlocations.h> <Cg/cg_datatypes.h> <Cg/cg_enums.h> <Cg/cg_errors.h> <Cg/cg_profiles.h> Das Interface zu OpenGL wird mit #include <Cg/cgGL.h> geladen, indem bereits der Aufruf für cg.h enthalten ist. Also genügt der letzte Aufruf. Die entsprechenden Bibliotheken stehen üblicherweise unter /usr/lib/libCg.so respektive /usr/lib/libCgGL.so. Sie können mit den Kompilerflags -lCg beziehungsweise -lCgGL geladen werden. Das Kompilieren der Shader zur Laufzeit geschieht über Bibliotheksaufrufe! Eine Entry function definiert ein Cg-Vertex- oder Cg-Fragmentprogramm und ist ein Analogon zur main function in C/C++. Da man aber viele solcher Entry functions in einem rufenden API haben 2.3. C FOR GRAPHICS 29 kann, sollte man sie nicht ebenfalls main nennen, um Verwirrungen vorzubeugen. Internal functions sind Hilfsfunktionen, die von den Entry functions aufgerufen werden können. Das sind beispielsweise von der Cg-Standardbibliothek zur Verfügung gestellte oder selbstgeschriebene Funktionen. Die Zeile return OUT; gibt die initialsierte Output Struktur zurück (mit entsprechender Semantik, die den einzelnen Komponenten zugeordnet ist). Zum Kompilieren von Cg-Code muss zum einen der Name des Cg-Programms bekannt sein, zum anderen muss der Profilname jeweils für Vertex- und Fragmentprofil gewählt werden. Da die Profile abhängig von der Graphikkarte sind, sollte ein Profil gewählt werden, das nach Möglichkeit von allen Graphikkarten unterstützt wird. Will man aber die Besonderheit eines speziellen Profils oder einfach ein neueres Profil und seine Vorzüge ausnutzen, sollte eine Abfrage an die GPU geschehen, mit der man das Vorhandensein entsprechender Möglichkeiten sicherstellt und wahlweise einfachen Cg-Code für ältere Graphikkarten zur Verfügung stellt. Cg-Vertexprofile: arbvp1 vs 1 1 vs 2 x OpenGL Basic multivendor programmibility ARB-vertex-profile DirectX8 Vertex shader DirectX9 Vertex shader Cg-Fragmentprofile: arbfp1 ps 1 1 ps 2 x OpenGL Basic multivendor programmibility ARB-fragment-profile DirectX8 Pixel shader DirectX9 Pixel shader 2.3.6 Ähnlichkeit mit C Cg liest sich einfach, wenn man mit C vertraut ist: Viele Keywords sind gleich oder erschließen sich einfach aus ihrem Name (hier ein Auszug aus der alphabetischen Liste): asm*, bool, break, · · · , pixelfragment*, · · · , while !!!ACHTUNG: Sie sollten Keywords NIE als Identifier verwenden!!! Auch Strukturen sind in gleicher Weise aufgebaut wie in C. Dem Keyword struct folgt ein Identifier mit dem Namen und in geschweiften Klammern die Liste der Variablen. Handelt es sich dabei aber um eine IN- oder OUT-Struktur, wird jede Komponente um eine sogenannte Semantik erweitert. 30 2.3.7 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG Besonderheiten Besonderheiten 1: Semantik Über die Semantik wird der Input oder das Ergebnis eines Cg-Programms an der richtigen Stelle in die Graphikpipeline eingegliedert. Die Semantik wird hinter einem Doppelpunkt und in Großbuchstaben hinter einem Membernamen angefügt und mit einem Komma vom nächsten Member getrennt. POSITION, COLOR, TEXCOORD0, PSIZE, NORMAL sind mögliche Semantiken. Die Semantik POSITION hängt entscheidend davon ab, ob sie über ein Vertexoder ein Fragmentprofil in die Graphikpipeline eingefügt werden soll, denn eine Knotenposition wird anders interpretiert, als eine Rasterposition. Texturkoordinaten werden mit angehängter Ziffer einem Texturkoordinatensatz zugeordnet, da man häufig mehrere Texturzugriffe in einem Programm ermöglichen möchte. Und schließlich will man mit PSIZE die sogenannten Partikelsysteme ebenfalls hardwarenah steuern können. Exkurs Partikelsysteme Partikelsysteme stellen eine Möglichkeit dar, ein sprühendes oder fließendes Objekt und seine Materialeigenschaft über einzelne, nicht verbundene Punkte zu modellieren. Dabei berechnet man Trajektorien dieser Partikel nach (einfachen) physikalischen Gesetzen und modelliert graphisch die Darstellung dieser einzelnen Punkte, in dem man beispielsweise die Punktgröße mit der Zeit variiert. Bessere Effekte erzielt man mit sogenannten Point sprites, kleinen meist quadratischen Texturen, die automatisch senkrecht zur Blickrichtung ausgerichtet werden und deren Mittelpunkt mit der Punktposition übereinstimmt. Die üblichen Texturkoordinaten (typischerweise laufen uv-Koordinaten in den Intervallen [0,1]x[0,1]) werden ebenfalls automatisch an das entsprechende Quadrat mit der angegebenen Punktgröße angepasst. Mit Partikelsystemen kann man beispielsweise Feuerwerk, Spritzwasser, Springbrunnen, Wasserfälle, aber auch semitransparente Objekte wie Flammen oder Rauch ansprechend und einfach darstellen. Beispiel 2.3 Mit der einfachen Gleichung 1 Pfinal = Pinitial + vt + at2 2 wird eine Vorwärtsintegration eines Anfangswertproblems beschrieben. Wählt man für jedes Partikel eine zufällige Anfangsgeschwindigkeit v bei konstanter (Erd-)Beschleunigung a, kann man die Punktgröße und Farbe mit der Zeit t variieren. Besonderheiten 2: Vektoren Auf der Graphikhardware werden immer wieder Vektoroperationen benötigt, die mit Rasterkoordinaten, Farben oder homogenen Raumkoordinaten umgehen und daher typische Vektorlängen von zwei, drei oder vier haben. Daher liegt es nahe, diese Operationen in der Hardware abzubilden und die Graphikleistung auf diese Weise zu beschleunigen. Will man diese Graphikleistung optimal ansteuern, muss auch der Compiler entsprechende Datentypen kennen, was 2.3. C FOR GRAPHICS 31 Abbildung 2.13. Zwei Partikelsysteme mit Point sprites, die eine Flamme und einen Wasserstrahl mit entsprechend unterschiedlichem Gravitationsverhalten darstellen. Bild von Daniel Jungblut. in der Hochsprache C/C++ nicht der Fall ist. Cg dagegen kennt die Datentypen float2, float3, float4 beziehungsweise entsprechende Vektoren, die mit den Standardnamen anderer Datentypen und den Ziffern 2, 3 und 4 gebildet werden. Sie sind NICHT äquivalent mit einem Array derselben Länge in C/C++, da die Vektoren als sogenannte Packed arrays gespeichert werden. float x[4] 6= float4 x Vektoren sind KEINE Keywords der Programmiersprache, könnten also als Identifier verwendet werden. Man sollte es aber vermeiden, um Verwirrungen vorzubeugen. Bemerkung 2.3 Wenn zwei Input-Vektoren als packed arrays gespeichert sind, können typische vektorwertige Operationen (skalare Multiplikation, Addition, Negation, Skalarprodukt, Kreuzprodukt, Vertauschen von Indizes) in einer einzigen Instruktion berechnet werden. Packed arrays helfen dem Cg-Compiler, die schnellen Vektoroperationen der programmierbaren GPUs auszunutzen. Die GPU ist ein Vektorrechner. Außerdem sollte man beachten, dass man auf die einzelnen Einträge eines Vektors sehr effizient mit der Ziffer des entsprechenden Index zugreift. Dagegen ist ein Zugriff über eine Referenz, die erst ausgewertet werden muss, ineffizient oder sogar unmöglich. float4 x = {1.0, 0.0, 1.0, 1.0}; // Initialisieren wie in C 32 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG int index = 3; float scalar; scalar = x[3]; // Effizienter Zugriff, scalar = 1.0; scalar = x[index]; // Ineffizient oder unmoeglich! Besonderheiten 3: Matrizen Da die GPU natürlich auch Matrix-Vektor-Operationen hardwarenah unterstützen muss, liegt es nahe, dass es in Cg dafür entsprechende Matrizen gibt. Hier einige Beispiele: float4x4 16 Elemente 32 bit half3x2 6 Elemente 16 bit Effizienter Datentyp für Fragmentoperationen fixed2x4 8 Elemente 32 bit, [-2.0, 2.0 [ Effizient für exp2-Auswertung (Fog) double4x4 16 Elemente 64 bit Die sechs Elemente von half3x2 entsprechen einer Matrix mit drei Reihen und zwei Spalten. Matrizen sind für alle besonderen Datentypen der GPU verwendbar, die im nächsten Paragraphen kurz vorgestellt werden. Besonderheiten 4: Datentypen Neu hinzugekommene Datentypen auf der GPU sind half und fixed. Mit half haben insbesondere alle Fragmentoperationen geringeren Speicherbedarf und laufen schneller ab, ohne dass man beispielsweise bei Farbinterpolationen einen sichtbaren Unterschied zur vollen Darstellung in float oder gar double ausmachen kann. Der Datentyp fixed dagegen verfolgt als Festkommazahl eine andere Philosophie, nämlich mit dem gleichen Speicherbedarf eines float eine größere Genauigkeit im Bereich von [-2.0, 2.0 [ zu garantieren, also in einem Intervall, das bei Operationen mit den Einträgen zweier Vektoren der Länge Eins maximal auftreten kann. Dieser Datentyp ist sehr effizient für exp2-Auswertungen, die beispielsweise für atmosphärische Effekte wie Nebel (Fog) gebraucht werden (plötzliches Erscheinen von Objekten in Abhängigkeit ihrer z-Tiefe). Besonderheiten 5: Konstruktoren Man kann alle diese Datentypen samt angehängter Ziffern wie Funktionen benutzen, also eine beliebige Zahlenfolge in einen Vektor oder eine Matrix packen. Sie sind damit sogenannte Konstruktoren. float4(1, 0, 1, 1); // erzeugt einen Vektor (Packed array) Besonderheiten 6: Qualifier uniform Mit dem Qualifier uniform wird deutlich gemacht, dass eine Variable aus einem externen Programm, also üblicherweise einem OpenGL oder Direct3D API, 2.3. C FOR GRAPHICS 33 an das Cg-Programm übergeben wird. Anders als in Renderman darf ein als uniform übergebener Parameter durchaus auf der GPU verändert werden. In Cg wird nicht zwischen uniform und einem nur in Renderman bekannten Qualifier varying unterschieden. Ein mit uniform übergebener Parameter wird als Variable behandelt. Wenn eine Variable nicht initialisiert wurde, kann das in der Entry function immer noch geschehen und dabei auch mit einer Semantik versehen werden, die beispielsweise für die Ausgabe dieses Cg-Programms benötigt wird. Besonderheiten 7: Swizzling Eine syntaktische Besonderheit stellt das Swizzling dar. Damit ist der Zugriff auf die Komponenten von Vektoren oder Matrizen in beliebiger Reihenfolge möglich. Zunächst können die Komponenten entsprechender Vektoren float4 position, color; über die folgende Konvention aufgerufen und zugewiesen werden (wenn kein w angegeben wird, ist implizit w = 1): float3 P = position.xyz; float4 Q = position.xyzw; float4 C = color.rgba; Beide Suffix Zeichenketten sind gültig, können aber nicht gemischt werden. Sie bezeichnen in natürlicher Weise die erste (r oder x), zweite (g oder y), dritte (b oder z) und vierte (a oder w) Komponente. Weder C noch C++ unterstützen das Swizzling, da keine der Sprachen Vektorrechnung unterstützt. Beispiel 2.4 Dieses Beispiel zeigt, wie einfach mit der Syntax einzelne Komponenten eines Vektors überschrieben werden können. float4 vec1 = float4(4.0, -2.0, 5.0, float2 vec2 = vec1.yx; // vec2 = float scalar = vec1.w; // scalar float3 vec3 = scalar.xxx; // vec3 = vec1.xw = vec2; // vec1 = 3.0); // float4 als Konstruktor (-2.0, 4.0) = 3.0 (3.0, 3.0, 3.0) (-2.0,-2.0, 5.0, 4.0) Beispiel 2.5 Gleiches gilt für Matrizen mit der Notation *. m<row><column>. float4x4 myMatrix; float myScalar; float4 myVec4; myScalar = myMatrix._m32; myVec4 = myMatrix._m00_m11_m22_m33 myVec4 = myMatrix[0] // myMatrix[3][2] // Diagonale // erste Reihe der Matrix 34 2.3.8 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG Fehlerbehandlung Bei den Cg-Compilerfehlern gibt es einerseits die konventionellen Fehler wie inkorrekte Syntax (Tippfehler) oder inkorrekte Semantik (falsche Anzahl der Parameter). Derartige Fehler treten bereits beim Vorkompilieren zu Tage, man kennt diese Art Fehler aus C/C++. Es empfiehlt sich, eine Fehlerfunktion im OpenGL oder Direct3D API zur Verfügung zustellen, wie in Beispiel 2.6 geschehen. Syntaktische Fehler werden mit der entsprechenden Stelle aus dem API sowie dem Kontext des Cg-Programms an das Terminal ausgegeben. Eine zweite Art der Fehler ist neu: der profilabhängige Fehler. Das ausgewählte Vertex- oder Fragmentprofil unterstützt die (an sich korrekten) Aufrufe nicht. Hierbei unterscheidet man nun drei verschiedene Arten solcher profilabhängiger ERROR: (a) Capability. Ein Beispiel: Bisher (2003) wird vom Vertexprofil kein Texturzugriff erlaubt, in Zukunft wird sich das ändern. Cg kann das heute schon kompilieren, aber die Hardware oder das 3D API kann es nicht umsetzen. (b) Context. Ein Beispiel: Ein Vertexprogramm muss die Semantik POSITION zurückgeben, sonst entsteht ein Fehler. Dagegen kann ein Fragmentprofil keine entsprechende Vertexposition zurückgeben, weil das in den Fluss der Graphikpipeline nicht passt. (c) Capacity. Ein Beispiel: Einige GPUs erlauben nur vier Texturzugriffe in einem Renderpfad, bei anderen ist der Zugriff unbeschränkt. Diese Art Fehler ist schwierig zu finden, da die Anzahl der Zugriffe oft nicht klar ersichtlich ist (vergleichbar mit einem Segmentation Fault in der CPUProgrammierung). Beispiel 2.6 Ein in OpenGL geschriebenes API stellt die auf der CPU zu kompilierenden Programmteile vor. Zum besseren Überblick sind die Teile des Codes blau gefärbt, die grundsätzlich nötig sind oder sich auf den programmierbaren Vertexprozessor beziehen. Dagegen sind die Teile mit Bezug auf den programmierbaren Fragmentprozessor in rot hervorgehoben. Die Übergabe von Parametern ist grün dargestellt. /* Open-GL program using Cg for programming a simple vertex-shader by Daniel Jungblut, IWR Heidelberg, February 2008 based on example code of Cg Tutorial (Addison-Wesley, ISBN 0321194969) by Randima Fernando and Mark J. Kilgard. */ #include <cstdlib> #include <stdio.h> #include <GL/glut.h> #include <Cg/cg.h> #include <Cg/cgGL.h> static CGcontext static CGprofile static CGprogram cg_context; cg_vertex_profile; cg_vertex_program; 2.3. C FOR GRAPHICS static CGprofile static CGprogram 35 cg_fragment_profile; cg_fragment_program; static CGparameter cg_parameter_vertex_scale_factor; static CGparameter cg_parameter_vertex_rotation; static CGparameter cg_parameter_fragment_color; // Error checking routine for Cg: static void checkForCgError(const char *situation) { CGerror error; const char *string = cgGetLastErrorString(&error); if (error != CG_NO_ERROR) { printf("%s: %s\n", situation, string); if (error == CG_COMPILER_ERROR) { printf("%s\n", cgGetLastListing(cg_context)); } exit(1); } } // keyboard callback: void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: // Escape case ’q’: cgDestroyProgram(cg_vertex_program); cgDestroyProgram(cg_fragment_program); cgDestroyContext(cg_context); exit(0); break; } } // display function: void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); cgGLBindProgram(cg_vertex_program); checkForCgError("binding vertex program"); cgGLEnableProfile(cg_vertex_profile); checkForCgError("enabling vertex profile"); // Hier werden die Werte der einheitlichen Parameter "scale_factor", "vertex_rotation" festgesetzt: cgGLSetParameter1f(cg_parameter_vertex_scale_factor, 0.7); cgGLSetParameter1f(cg_parameter_vertex_rotation, 1.509); cgGLBindProgram(cg_fragment_program); checkForCgError("binding fragment program"); cgGLEnableProfile(cg_fragment_profile); checkForCgError("enabling fragment profile"); GLfloat color[] = {0.2, 0.7, 0.3}; cgGLSetParameter3fv(cg_parameter_fragment_color, color); // Rendern eines Dreiecks. Hierfuer wurde keine Farbe ausgewaehlt! glBegin(GL_TRIANGLES); glVertex2f(-0.8, 0.8); glVertex2f(0.8, 0.8); glVertex2f(0.0, -0.8); glEnd(); cgGLDisableProfile(cg_vertex_profile); checkForCgError("disabling vertex profile"); cgGLDisableProfile(cg_fragment_profile); checkForCgError("disabling fragment profile"); 36 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG glutSwapBuffers(); } int main(int argc, char **argv) { glutInitWindowSize(400, 400); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutInit(&argc, argv); glutCreateWindow("Vertex and fragment shaders"); glutDisplayFunc(display); glutKeyboardFunc(keyboard); glClearColor(0.1, 0.2, 0.8, 1.0); cg_context = cgCreateContext(); checkForCgError("creating context"); cg_vertex_profile = cgGLGetLatestProfile(CG_GL_VERTEX); cgGLSetOptimalOptions(cg_vertex_profile); checkForCgError("selecting vertex profile"); cg_vertex_program = cgCreateProgramFromFile(cg_context, CG_SOURCE, "E6_vertex.cg", cg_vertex_profile, "more_complex_vertex_shader", NULL); checkForCgError("creating vertex program from file"); cgGLLoadProgram(cg_vertex_program); checkForCgError("loading vertex program"); // Verbinden der Variable "cg_parameter_vertex_scale_factor" // mit der Variable "scale_factor" aus dem Vertex-Shader: cg_parameter_vertex_scale_factor = cgGetNamedParameter(cg_vertex_program, "scale_factor"); checkForCgError("getting scale_factor parameter"); cg_parameter_vertex_rotation = cgGetNamedParameter(cg_vertex_program, "rotation"); cg_fragment_profile = cgGLGetLatestProfile(CG_GL_FRAGMENT); checkForCgError("selecting fragment profile"); cg_fragment_program = cgCreateProgramFromFile(cg_context, CG_SOURCE, "E6_fragment.cg", cg_fragment_profile, "simple_fragment_shader", NULL); checkForCgError("creating fragment program from file"); cgGLLoadProgram(cg_fragment_program); checkForCgError("loading fragment program"); cg_parameter_fragment_color = cgGetNamedParameter(cg_fragment_program, "color"); checkForCgError("getting fragment parameter color"); glutMainLoop(); return 0; } Beispiel 2.7 Passend zum vorhergehenden Beispiel ist hier ein Cg-Vertexprogramm aufgeführt. /* More complex vertex shader by Daniel Jungblut, IWR Heidelberg, February 2008. */ void more_complex_vertex_shader(float4 position : POSITION, out float4 out_position : POSITION, uniform float scale_factor, uniform float rotation) { 2.3. C FOR GRAPHICS 37 // Erzeugung der 2D-Skalierungsmatrix: float2x2 scale_matrix = float2x2(scale_factor, 0.0, 0.0, scale_factor); float sin_rot, cos_rot; sincos(rotation, sin_rot, cos_rot); float2x2 rotation_matrix = float2x2(cos_rot, -sin_rot, sin_rot, cos_rot); // Transfomieren der Vertices mit Hilfe der Skalierungsmatrix: out_position = float4(mul(scale_matrix, mul(rotation_matrix, position.xy)), 0, 1); } Beispiel 2.8 Ebenfalls zum vorhergehenden Beispiel passend ist hier ein ganz einfaches Cg-Fragmentprogramm aufgeführt. /* Simple fragment shader by Daniel Jungblut, IWR Heidelberg, February 2008. */ void simple_fragment_shader(out float4 out_color : COLOR, uniform float3 color) { out_color = float4(color, 1.0); } 2.3.9 Parameter, Texturen und mathematische Ausdrücke Mit dem Qualifier uniform werden Parameter eines externen Programms an das Cg-Programm übergeben. Wenn eine Variable NICHT initialisiert wurde, kann das in der Entry function geschehen. Hier können auch mit dem Qualifier const nicht veränderbare Konstanten gesetzt werden. const float pi = 3.14159; // NICHT veraenderbar!!! pi = 4.0; // NICHT erlaubt! float a = pi++; // NICHT erlaubt! Texture sampler werden uniform übergeben, d.h. sie treten als Teil einer Eingabe an den Fragmentprozessor auf. uniform sampler2D decal // Teil einer IN-Struktur Um auf eine Textur zuzugreifen, gibt es Standard Cg Funktionen, die den Namen der uniform übergebenen Textur mit den Texturkoordinaten versieht und als Farbe zurückgibt. 38 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG OUT.color = tex2d(decal, texCoord); Folgende Texture sampler sind möglich: Sampler Typ Textur Typ Anwendung sampler1D sampler2D sampler3D samplerCUBE samplerRECT Eindimensionale Textur Zweidimensionale Textur Dreidimensionale Textur Cube Map Textur Non-Power-of-Two Non-Mipmapped 2D-Textur 1D Funktion Abziehbilder (Decal), Normalenfelder Volumendaten, Dämpfungsterme Environment Maps, Skybox Videofilme, Fotos Tabelle 2.1. Mögliche Texturaufrufe Mathematische Ausdrücke können einerseits Operatoren sein, die auf der Graphikkarte immer auch für Vektoren gelten. Wenn skalare Operationen mit Vektoroperationen gemischt werden, wird der skalare Wert automatisch so häufig wiederholt, bis er die Länge des Vektors erreicht. Dieses Verschmieren eines Skalars auf einen Vektor wird Smearing genannt und garantiert wieder die Geschwindigkeitsvorteile eines Vektorrechners. Operator Art + * / Auswertung Negation Links nach rechts Addition Subtraktion Multiplikation Division Tabelle 2.2. Ausnahmen der Auswertung (Rechts nach links) bei: ++, +=, sizeof, (type) Beispiel 2.9 Hier werden einige typische Vektoroperationen vorgestellt. float3 modulatedColor = color * float3(0.2, 0.4, 0.5); modulatedColor *= 0.5; float3 specular = float3(0.1, 0.0, 0.2); modulatedColor += specular; negatedColor = -modulatedColor; float3 direction = positionA - positionB; Sehr effizient implementiert und daher eigenen Routinen gleicher Funktion vorzuziehen sind die in der folgenden (überhaupt nicht vollständigen) Tabelle gelisteten Funktionsaufrufe. ACHTUNG: Es gibt in Cg KEINE IO-Routinen, KEINE String-Manipulationen und KEINE Speicherallokationen. 2.4. ÜBUNGSAUFGABEN Prototyp abs(x) cos(x) cross(v1, v2) ddx(a) ddy(a) dot(a,b) reflect(v,n) normalize(v) determinant(M) mul(M,N) mul(M,v) mul(v,M) tex2D(sampler,x) tex3Dproj(sampler, texCUBE(sampler,x) 39 Profil Beschreibung alle Vertex, Adv. Fragment Vertex, Adv. Fragment Advanced Fragment Advanced Fragment alle Vertex, Adv. Fragment Vertex, Adv. Fragment Vertex, Adv. Fragment Vertex, Adv. Fragment Vertex, Adv. Fragment Vertex, Adv. Fragment Fragment Fragment Fragment Absolutwert von Skalar oder Vektor Kreuzprodukt zweier Vektoren Richtungsableitung nach x im Fragment a Richtungsableitung nach y im Fragment a Skalarprodukt Reflexion von Vektor v bei Normale n Normalisieren des Vektors v Determinante der Matrix M Matrizenprodukt Matrix-Vektorprodukt Vektor-Matrixprodukt 2D-Texturaufruf Projektiver 3D Texturaufruf CubeMap Texturaufruf Tabelle 2.3. Standardisierte Funktionsaufrufe, sehr effiziente Implementierung Das Function overloading wird von allen diesen Funktionen ebenfalls sehr effizient unterstützt. Damit ist gemeint, dass man sich nicht um den speziellen Datentyp kümmern muss, der in eine der Funktionen eingeht: die Cg-Bibliothek sucht für jeden Datentyp die richtige Funktion aus. Das gilt auch für Vektoren, so dass es beispielsweise für die Funktion abs(x) egal ist, ob x ein Skalar oder ein Vektor ist. 2.4 Übungsaufgaben Aufgabe 2.1 Einfacher Vertex Shader Ändern Sie den in der Übung vorgestellten einfachen Vertex-Shader wie folgt: Verschieben Sie das Dreieck um einen beliebigen Offset. Verwenden Sie hierzu die in Cg vorgesehenen Vektorvariablen. Das Dreieck soll anschließend noch voll sichtbar sein. Verändern Sie die Farbe des Dreiecks. Finden Sie eine Möglichkeit jedem der drei Eckpunkte des Dreiecks eine andere Farbe zu geben? Wichtig: Ändern Sie hierfür nur den Shader ”E3.cg”, nicht jedoch die C++-Datei ”main.cpp”! Das in der Übung vorgestellte Beispielprogramm finden Sie auch im Netz unter www.iwr.uni-heidelberg.de/groups/ngg/CG2008/lecture.php. Beantworten Sie folgende Fragen durch Kommentare im von Ihnen geänderten Shader: Warum muss 40 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG das Programm nicht neu compiliert werden, wenn man nur den Shader verändert? Worin unterscheidet sich der Übergabeparameter der Shader-Funktion ”simple vertex shader” von den Übergabeparametern, die Sie aus C oder C++ kennen? Warum ist das so? Der hier vorgestellte einfache VertexShader verändert die Koordinaten und die Farbe der einzelnen Vertices. Welche Attribute eines Vertex kann ein Vertex-Shader noch verändern? Aufgabe 2.2 Listen aufrufen Programmieren Sie ein Moebiusband als Trianglestrip. Zeichnen Sie mehrere dieser Bänder, wobei Sie in Ihrer Display-Routine das Band direkt aufrufen oder ein mit void glNewList(GLuint list, Glenum mode) vorkompiliertes Band zeichnen lassen. Lassen Sie sich die Framerate beim Drehen nacheinander für beide Varianten auf dem Bildschirm ausgeben. Das Umschalten sollte über die Taste l geschehen. Wie verhält sich die Framerate? Aufgabe 2.3 Fragment-Shader Der Ausgangscode für diese Aufgabe ist unter www.iwr.uni-heidelberg.de/groups/ngg/CG2008/lecture.php zu finden. Erweitern Sie den Fragment-Shader, so dass die Farbe der Fragmente durch einen einheitlichen Parameter über das Hauptprogramm festzulegen ist. Drehen Sie das Dreieck mit Hilfe des Vertex-Shaders um einen Winkel, der durch das Hauptprogramm gesteuert werden kann. Erklären Sie den Unterschied zwischen variierenden und einheitlichen Parametern. Erklären Sie den Begriff call-by-result. Warum werden in Cg genau Vektoren bis zur Dimension 4 unterstützt? Schreiben Sie die Antworten zu den Fragen als Kommentare in einen der beiden Shader. Hinweis: Im Gegensatz zu Aufgabe E03 sind zur erfolgreichen Bearbeitung dieser Aufgabe auch Änderungen im Hauptprogramm nötig. Aufgabe 2.4 Heat Equation Berechnen Sie eine numerische Lösung der linearen Wärmeleitungsgleichung ∂ut = ∆u auf R+ × Ω u(x, 0) = u0 auf Ω̄ u = 0 auf R+ × ∂Ω im Zweidimensionalen. Ein semiimplizites Diskretisierungsschema für den Zeitschritt führt zu dem Gleichungssystem (1 − τ ∆h )uτ = Auτ = u0 2.4. ÜBUNGSAUFGABEN 41 wobei u0 die Wärmeverteilung zu Beginn und uτ die Wärmeverteilung zum Zeitpunkt τ beschreibt. Diskretisiert man den Laplace-Operator mittels finiter Differenzen, so ergeben sich die Gleichungen i−1,j (1 + 4τ )ui,j + ui+1,j + uτi,j−1 + ui,j+1 ) = ui,j ∀ i, j 0 τ − τ (uτ τ τ in denen die Indizes i und j die Raumkoordinaten der einzelnen Gitterpunkte angeben. Das Gleichungssystem soll mit Hilfe des Jacobi-Verfahrens gelöst werden für das sich folgende Iterationsvorschrift ergibt ui,j neu = 1 i,j + ui,j+1 + ui,j−1 + ui+1,j (τ (ui−1,j alt ) + u0 ). alt alt alt (1 + 4τ ) Implementieren Sie dieses numerische Lösungsverfahren, wobei die einzelnen Iterationsschritte des Jacobi-Verfahrens in einem Fragment-Shader berechnet werden. Gehen Sie dabei wie folgt vor: (a) Laden Sie von der Vorlesungswebseite die Datei waves.png herunter. Schreiben Sie zunächst ein OpenGL Programm mit zweidimensionalem Weltkoordinatensystem, so dass jeder Texel dieser Textur genau auf einen Pixel des Ausgabefensters abgebildet wird. Setzen Sie die Texturfilter auf GL NEAREST um Interpolationsfehler zu vermeiden. Die vorgegebene Textur ist ein Graustufenbild. Da später mehr als ein Farbkanal benötigt wird, übertragen Sie die Textur im RGB-Format an die Graphikkarte, wobei die drei Kanäle R, G und B jeweils mit dem Grauwert des entsprechenden Texels initialisiert werden. (b) Erweitern Sie dieses Programm um einen Fragment-Shader, der die Auswertung der Textur übernimmt. (c) Implementieren Sie eine idle-Funktion, die mit Hilfe des Befehls glCopyTexSubImage2D(...) den Inhalt des aktuellen Color-Buffer in die Textur kopiert und anschließend das Bild neu zeichnet. (d) Nach hinreichend vielen Jacobi-Iterationen ist das Gleichungssystem näherungsweise gelöst. Speichern Sie nach 120τ Aufrufen der idle-Funktion den aktuellen Inhalt des Color-Buffers in eine Datei und beenden Sie das Programm. Der Color-Buffer kann mit der Funktion glReadPixels(...) ausgelesen werden. (e) Implementieren Sie zum Abschluss das Jacobi-Verfahren in Ihrem Fragment-Shader. Verwenden Sie den Rot-Kanal zur Speicherung des Iterationsfortschritts und den Grün-Kanal zur Speicherung der rechten Seite u0 des Gleichungssystems. Um die Pixel am Rand des Bildes korrekt zu verarbeiten, genügt es die Wrapping-Parameter für die Texturkoordinaten auf GL CLAMP zu setzen. 42 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG (f) Wenden Sie das Programm für τ = 1, 2, 4, 8 auf das Ausgangsbild an und speichern Sie die Ergebnisbilder gut erkennbar ab. Beschreiben Sie das Ergebnis dieses Verfahrens als Kommentar in Ihrem Shader. 2.4. ÜBUNGSAUFGABEN Abbildung 2.14. Das CgFX-Austauschformat, eine Beispieldatei. 43 44 KAPITEL 2. GRAPHIKKARTEN PROGRAMMIERUNG Kapitel 3 Volume Rendering Das Problem der graphischen Darstellung von Volumendaten gilt als zentrales Forschungsgebiet der wissenschaftlichen Visualisierung. Immer mehr dreidimensionale Skalarfelder und Vektorfelder aus Messungen (bildgebende Verfahren der Medizin wie Computertomographie und Magnetresonanzspektrskopie, seismische Untersuchungen, Georadar, Sonar) oder aus Simulationsrechnungen (Strömungsmechanik, Atomphysik) sollen möglichst plastisch dargestellt werden. Neben der Konturflächenbestimmung (Isoflächen = Oberflächen mit gleichen skalaren Werten) werden heute in zunehmendem Maße direkte Volume Rendering Verfahren eingesetzt. Abbildung 3.1. 3D-Computertomogrammdaten bestehen aus einzelnen Schichten von Röntgenbildern. Das Volumen wird am Rechner zusammengesetzt und visualisiert. 45 46 KAPITEL 3. VOLUME RENDERING Obwohl Raytracing in der Computergraphik eine schon lange bekannte Idee ist, wird sie für das Volume Rendering wiederentdeckt und dabei allerdings entscheidend abgewandelt. Die Strahlen, die durch das Volumen geschickt werden, treffen in jedem Volumenelement (Voxel) des regelmäßigen Gitters auf unterschiedliche skalare Werte, die als optische Dichten interpretiert werden. Die Bestimmung der Schnittpunkte ist hier also nicht das Problem, sondern die große Menge an Voxeln und ihre Zuordnung zu Farb- und Lichteffekten. Jedes Voxel liefert einen Beitrag zum endgültigen Bild, so dass auch tiefer liegende Schichten durch Transparenz sichtbar gemacht werden. Dabei können durch die flexible Abbildung der Datenwerte auf Farbe und Opazität unterschiedliche Strukturen und Phänomene sehr effizient visualisiert werden. Betrachter @ xB s s s s s s s s s s@ @ @ @ @ Bildebene s Abbildung 3.2. Entlang des Sichtstrahl werden die als optische Dichten interpretierten skalaren Werte der einzelnen Voxeln auf dem Weg durch das Volumen summiert. Volumenvisualisierungsverfahren basieren heute fast ausschließlich auf den Näherungen des Absorptions-Emissions-Modells, das Streuung und Frequenzabhängigkeiten als unerwünschte Effekte in der Strahlungstransportgleichung nicht berücksichtigt. Beim Rendering von Szenen mit volumetrischen Objekten (z.B. Nebel, Wolken, etc.) sind diese Phänomene für eine realistische Darstellung jedoch unverzichtbar. Ziel des Verfahrens ist insbesondere bei medizinischen Daten wie 3D-Computertomogrammdaten (CT-Daten, Intensitäten im voxelbasierten Raum), dass sie • möglichst plastisch dargestellt • in Echtzeit transformierbar • animierbar 3.1. HERLEITUNG DER GLEICHUNG 47 sind. Erst dann können sie über die reine Operationsplanung hinaus auch in der minimalinvasiven Chirurgie zur visuellen Unterstützung während des Eingriffs eingesetzt werden. 3.1 Herleitung der Gleichung Die physikalische Modellvorstellung rührt von einem Lichstrahl her, der an einem semitransparenten Medium in einem beschränkten Volumen streut. Der Photonenfluss erreicht dabei sofort ein Gleichgewicht, d. h. für ein beschränktes Volumen werden für die vorher bestimmten Richtungen zeitlich konstante Bilder erzeugt. L(r, ω) Strahlungsdichte, Radiance beschreibt die Energiedichte an einem bestimmten Punkt r pro Flächenelement in Flussrichtung [m2 ], die in Richtung des Betrachters ω pro Winkeleinheit [sr] in MKS-Einheit [W/m2 sr]. 3.1.1 Energieerhaltungsgleichung Die Energieerhaltungsgleichung oder Transfergleichung in ihrer differentiellen Form lautet Z k(r, ω 0 → ω)L(r, ω 0 )dω 0 ω · ∇L(r, ω) = −φt (r)L(r, ω) + (r, ω) + S2 und Anfangsbedingungen und Randbedingungen. Die integrale Form −τ (r,rB ) L(r, ω) = e Z LB (rB , ω) + 0 e−τ (r,r ) Q(r0 , ω)dr0 Γ(r,rB ) mit einem Auslöschungsterm entlang des Strahls von r bis s Z τ (r, s) ≡ φt (r0 )dr0 , Γ(r,rB ) der Strahlungsdichte am Rand LB und einem aus Emissions- und einem Streuanteil gewonnenen Term Z Q(r, ω) = (r, ω) + k(r, ω 0 → ω)L(r, ω 0 )dω 0 S2 erhält man durch Umformung aus der differentiellen Form. 48 KAPITEL 3. VOLUME RENDERING Bemerkung 3.1 e−τ (r,s) ist der integrierende Faktor, um die Differentialgleichung in die Integralgleichung umzuwandeln. 3.2 Vereinfachungen Die folgenden Vereinfachungen führen zu einem schnellen Algorithmus, der allerdings nicht jeder Anforderung genügen kann. Beispielsweise lässt sich keine Schattenwirkung erzeugen. 1. Einfache Streutiefe: Photonen werden nur einmal am Volumenelement gestreut, gehen in keine Iteration ein. 2. Keine Absorption zwischen Lichtquelle und Streuereignis. 3. Isotrope Absorption 4. Einfache Randbedingungen: Endliche Zahl punktförmiger Lichtquellen im Inneren Wegen der 1. und 2. Vereinfachung ist der Streukern k = 0. Somit besteht Q nur aus einem Emissionsterm, der integrale Anteil entfällt. Hier ergibt sich die Frage, wie der Emissionsteil modelliert wird. In jedem Voxel wird ein lokales Illuminationsmodell verwendet, das eine Funktion des skalaren Werts (optische Dichte) und der Position der Lichtquelle ist. Schattenwurf ist nicht in diesem Modell enthalten, denn dazu müßte Absorption des Lichts beim Streuvorgang auf die nachfolgenden Voxel berücksichtigt werden (siehe 2. Vereinfachung). Mit diesen Vereinfachungen kommt man zur Volume Rendering Gleichung Z L(x) = xB R x0 e x φt (x00 )dx00 (x0 )dx0 x wobei x den Abstand auf dem Betrachterstrahl markiert und xB den Randpunkt beim Verlassen des Volumens. Die Isotropieanahme sorgt für die einfachen Integrationsgrenzen, wegen der Lichtquellenannahme entfällt der Randoperator. 3.3 Einfacher Ray Casting Algorithmus Parallel zum Volumen werden Strahlen in das Volumen hineinverfolgt und werten die Integralgleichung im Innern numerisch aus. Mit der Rechteckregel erhält man folgende Summe: 3.3. EINFACHER RAY CASTING ALGORITHMUS L(x) = = n−1 X i=0 n−1 X i=0 e− 49 Pi−1 j=0 i ∆x φt ∆x i−1 Y i ∆x e−φj ∆x j=0 mit i ≡ (x + i∆x) φi ≡ φt (x + i∆x) wobei ∆x das Inkrement entlang des Strahls bezeichnet. Definiere αi ≡ 1 − e−φi ∆x Ci ≡ (i /αi )∆x ci ≡ Ci αi als Durchsichtigkeit, Farbe und mit der Durchsichtigkeit gewichtete Farbe an der i-ten Position auf dem Strahl. L(x) = n−1 X i=0 ci i−1 Y αj j=0 = c0 + c1 (1 − α0 ) + c2 (1 − α0 )(1 − α1 ) + · · · + cn−1 (1 − α0 ) · · · (1 − αn−2 ) = c0 over c1 over · · · over cn−1 Bemerkung 3.2 Der Operator over bezieht sich auf den Digital composing operator, wodurch sich die Gleichung kompakter schreiben lässt. Damit ergibt sich der folgende Algorithmus: 1. Für jeden Bildpunkt wird ein Strahl durch das Volumen verfolgt. 2. Farbwerte Ci und Dichtewerte αi werden in regelmäßigen (äquidistanten) Abständen entlang des Strahls aufgrund der Probepunkte ermittelt. 50 KAPITEL 3. VOLUME RENDERING 3. Die Produkte werden zur Strahlungsdichte L(x) summiert. Für ein kubisches Volumen mit Kantenlänge n werden n2 Strahlen mit n Probepunkten pro Strahl zu O(n3 ) Operationen führen. 3.3.1 Klassifizierung und Transferfunktion Der Ablauf der Visualisierung vom skalaren Feld geschieht über die Klassifizierung der Daten, die Farbgebung und schließlich die Bildgenerierung. Eine gute Interaktion erlaubt dem Benutzer, auf diese Schritte interaktiv Einfluss zu nehmen. Abbildung 3.3. User Interface zur Segmentierung auf Basis der Dichtewerte und Gradientenlängen. Klassifizierung heißt, jedem Voxel aufgrund des skalaren Feldes von 3D-Daten Transparenzen ai und Farbwerte Ci zuzuordnen. Dies geschieht mittels einer Transferfunktion, die die Intensitäten, also skalare Werte, in Farb- und Transparenzwerte umsetzt. Zusätzlich will man häufig mittels Segmentierung größere Bereiche zusammenfassen, die dann einen gleichmäßigen Farbwert bekommen. Eine Segmentierung lässt zu, dass nur ein (oder zwei) dieser Segmente gezeigt werden, während man die anderen völlig transparent darstellt und somit ausblendet. Diese Segmentierung nimmt man anhand 3.3. EINFACHER RAY CASTING ALGORITHMUS 51 Abbildung 3.4. Ergebnis der Segmentierung und anschließender Glättung der Oberfläche. des Histogramms des skalaren Feldes vor, das heißt anhand der Verteilung der Häufigkeit einzelner Intensitäten in den Volumendaten. Segmentgrenzen wird man typischerweise in den Tälern des Histogramms platzieren. Ein anderes wichtiges Merkmal ist die Länge der Grauwert- oder Dichtegradienten. Hierüber erfährt man, an welchen Stellen der steilste Abfall zu benachbarten Voxeln vorhanden ist. Auch hier ist eine Segmentgrenze sinnvoll gesetzt. Zudem zeigt der Gradient bereits in die Richtung einer Normalen an der Oberfläche dieses Segments. Möchte man später diese Konturfläche mit einem Lichtmodell versehen, kann man auf diese vorberechneten Normalen zurückgreifen. Bemerkung 3.3 Eine wesentliche Verkürzung der Volume-Rendering-Zeiten kann für Röntgenbildartige Darstellungen unter Ausnützung des Fourier-Projection-Slice-Theorems im Frequenzraum erzielt werden. Zur genauen Rekonstruktion benötigte Filter können mit biorthogonalen Wavelets realisiert werden. Das reduziert den Aufwand auf O(n2 logn) Operationen. Bemerkung 3.4 Wenn Daten auf gekrümmten oder unstrukturierten Gittern vorliegen, wie es bei Simulationsrechnungen häufig der Fall ist, muss man sie auf reguläre (nicht notwendig äquidistante Gitter) zurückführen, bevor man den Weg der Strahlen durch das Volumen berechnet. Es lohnt, diese Interpolation permanent zu speichern, auch wenn dadurch viele Daten, die auf Rechengittern ausgegeben wurden, doppelt auf der Festplatte vorliegen. 52 KAPITEL 3. VOLUME RENDERING Abbildung 3.5. Volumenbasierte Darstellung eines Schädels, links angeschnitten, rechts als vollständiger Datensatz mit Transparenzen. Beispiel 3.1 Die CT-Daten eines menschlichen Schädels können aufgrund charakteristischer Intensitäten und unter Ausnutzung von Kontinuitätseigenschaften auf Zusammenhangskomponenten in die Segmente Haut, Knochen, Hirnmasse und Tumormasse segmentiert werden. In der Operationsplanungsphase können diese Segmente stark kontrastierend im selben Bild dargestellt werden bzw. ein oder mehrere Segmente ausgeblendet sein. Mit entsprechenden Werkzeugen kann nun auch der Datensatz manipuliert, d.h. eine virtuelle Operation vorgenommen werden. 3.4 Beschleunigungen 3.4.1 Early Ray Termination – Abbruchkriterien Durch frühzeitiges Abbrechen der Summation bei Erreichen eines Schwellwerts, der nahezu Undurchsichtigkeit garantiert, kann der Algorithmus, abhängig von den Materialeigenschaften, erheblich beschleunigt werden. Dieses Vorgehen wird Early Ray Termination genannt und lässt sich einfach implementieren. 3.4.2 Ausnutzen kohärenter Strukturen Meagher [Mea82] hat 1982 einen Algorithmus vorgeschlagen, der einen Octree-Suchalgorithmus durch einen 2D-Quadtree ersetzt. Bei der Segmentierung kann dieser nutzbringend in die Strahlverfolgung eingebracht werden, um bei Eintritt eines Strahls in ein Segment die erforderlichen Summatio- 3.4. BESCHLEUNIGUNGEN 53 nen abzuschätzen (Greene 1993, [GKM93]). Allerdings führt die Wandlung von einem zum anderen Suchalgorithmus zu einem erheblichen Overhead, der die gewonnene Beschleunigung innerhalb von virtueller Realität nahezu kompensiert. Bessere Ergebnisse verspricht man sich durch das dauerhafte Filtern entlang dreidimensionaler Strukturen. Damit ist das Glätten verrauschter Daten gemeint, die dann den Segmentieralgorithmen zugänglicher sind. 3.4.3 Shear-Warp Faktorisierung Der Scher-Verwerfungsalgorithmus wurde in Stanford von Lacroute [Lac95] entwickelt und beinhaltet drei nacheinander ausgeführte Schritte, das Scheren, Projizieren und anschließende Neigen des Bildes auf die für den Betrachter wesentliche Bildebene (siehe Abbildung 3.6). Statt Sichtstrahlen schräg durch das Volumen zu schicken, werden die an den Koordinatenachsen ausgerichteten Schichten der Volumendaten um einen entsprechenden Offset gegeneinander verschoben, also geschert. Nun können die Strahlen die im Speicher benachbarten Werte sehr viel schneller addieren. Das anschließende Projizieren resultiert in einem verzerrten Zwischenbild, das auf die tatsächliche Bildebene geneigt werden muss. Bei orthographischen Projektionsverfahren funktioniert dieser Algorithmus über einfaches Abbilden der entsprechend verzerrten Zwischenbilder auf die drei dem Betrachter zugewandten Seitenflächen eines achsenparallelen Quaders in den Proportionen der Volumendaten. scheren Sichtstrahlen I @ @ I @ I @ @ @ @ @ @ @ @ Geschichtete @ @ @ Volumendaten @ @ @ @ @ @ @ @ @ @ @ @ @ @ Bildebene 6 6 6 projizieren ? @ @ @ R @ @ @ @ @ @ @ @ @ @ @ neigen Bildebene Abbildung 3.6. Scherverwerfung nach Lacroute. Will man Objekte in perspektivischer Projektion darstellen, muss die Verkürzung weiter entfernter Schichtbilder schon beim Scheren berücksichtigt werden. Die nun aufsummierten Farbwerte ergeben so geartete Projektionen (Zwischenbilder), dass sie beim Texture Mapping auf einen perspektivisch erscheinenden Kubus wieder geeignet entzerrt werden. Für den Betrachter erscheint das im Kubus verborgene Volumen jetzt unverzerrt. 54 KAPITEL 3. VOLUME RENDERING xz-Ebene Bild auf dem Schirm xy-Ebene yz-Ebene Abbildung 3.7. Die einzelnen verzerrt berechneten Zwischenbilder werden auf die Außenflächen des kubischen Volumens projiziert. Vor einem schwarzen Hintergrund erscheint das 3D-Objekt. 3.4.4 Texturbasiertes Volume Rendering Ein gänzlich anderer Ansatz der Volumenvisualisierung besteht in der Berechnung vieler einzelner Schichtbilder auf Basis einer Transferfunktion, die wie oben beschrieben Intensitäten, also skalare Werte, in Farb- und Transparenzwerte umsetzt. Diese Bilder werden als Texturen einander überblendet und erzeugen dadurch ebenfalls einen halbtransparenten farbigen Eindruck eines Volumens, der sehr schnell gerendert werden kann. Schaut man allerdings nahezu parallel zu den Schichten auf das Volumen, sieht man kaum noch Farbwerte des Datensatzes sondern zwischen den Schichten hindurch die Hintergrundfarbe. Abhilfe schafft hier ein Wechsel zu einem ebenfalls vorab berechneten Stapel othogonaler Schichten. Beim Ändern der Blickrichtung wird dabei immer wieder nötig, zwischen den verschiedenen Texturen zu wechseln bzw. zu überblenden. Dabei treten allerdings unerwünschte Diskontinuitäten auf. Auch ist mit diesem Ansatz nicht möglich, Konturflächen von Segmenten darzustellen, da auf jegliche Verbindung zwischen den Schichtbildern verzichtet wird. Oberflächennormalen, die für lokale Lichtmodelle benötigt werden, lassen sich daher nicht berechnen. 3.5 Übungsaufgaben Aufgabe 3.1 Volumenvisualisierunssoftware Vrend Auf der Homepage zur Vorlesung liegt das File Vrend2.1 dummy.tar.gz, das Sie auf Ihrem Account mit tar -xvzf Vrend2.1 dummy.tar.gz entpacken. Starten Sie das Programm Vrend2.1/bin/vrend und laden Sie die Beispiele. Unter dem Menüpunkt Segments finden Sie vorbereitete Materialklassen <filename.scl>. Mit dem Segments editor lassen sie sich weiter bearbeiten. Die Apply Taste sorgt für eine neue Berechnung der Normalen an den Segmentgrenzen. Das Beispiel Dummy enthält noch keine Segmentierung. Was verbirgt sich hinter dummy.dat? Weisen Sie den von Ihnen erzeugten Segmenten unterschiedliche Materialeigenschaften und Transparenzen zu. Sichern Sie Ihre Segmentierung in einer Datei, die Sie sinnvoll benennen. Machen Sie einen 3.5. ÜBUNGSAUFGABEN 55 Abbildung 3.8. Hans Holbein der Jüngere, Die Gesandten, 1533. Schaut man durch einen Schlitz im Rahmen an der rechten Seite auf halber Höhe, erkennt man in dem Objekt im Vordergrund einen Schädel, das Symbol für Vergänglichkeit. Solche perspektivischen Verzerrungen werden Anamorphismen genannt. Screenshot von Ihrem segmentierten, farbigen Ergebnis (z.B. mit gimp > File> Acquire). Alternativ finden Sie das Programm unter: http://www.iwr.uni-heidelberg.de/groups/ngg/Vrend/ 56 KAPITEL 3. VOLUME RENDERING Kapitel 4 Radiosity Anders als bei den lokalen Beleuchtungsverfahren, die jeweils immer nur einen Vertex betrachten wie z.B. das Blinn-Phong Modell, wird beim Radiosity-Verfahren der ganze Objektraum berücksichtigt. Dadurch lassen sich realistischere Bilder einer Szene erstellen. Abbildung 4.1. Die Lösung des Bildes Steel mill der Cornell University benötigte 1988 für die Berechnung der Radiosity fünf Stunden bei 30000 Flächenstücken und 2000 Iterationsschritten eines Shooting Verfahrens, dann nochmal 190 Stunden für das Rendern auf einer VAX8700 (siehe [CCWG88]). Mit dem Begriff Radiosity (Strahlung) wird die gesamte von einer Fläche abgegebene Energie bezeichnet. Bei dem Verfahren handelt es sich um ein Strahlungstransportmodell für diffuse Beleuchtung, das auf Methoden zurückgeht, die von Siegel und Howell 1984 für den Strahlungstransport von 57 58 KAPITEL 4. RADIOSITY Hitze in Schmelzöfen oder Raketentriebwerken entwickelt wurden. Im gleichen Jahr wurde das Verfahren von Goral, Torrance, Greenberg und Bataille in die Computergraphik eingeführt [GTGB84]. Die Idee des Verfahrens beruht auf der Berücksichtigung des Strahlungsaustausches zwischen Oberflächen und dem Energieerhaltungssatz (Energiesumme in einem abgeschlossenem System ist konstant). Da Licht eine Form von Energie ist, können Sätze der Thermodynamik verwendet werden, um die Radiosity zu berechnen. Zur Vereinfachung der Szene gelten folgende Annahmen: 1. Die Szene wird in endliche zusammenhängende Teilflächen (Patches) unterteilt, die so gewählt werden, dass jede Fläche homogen in Bezug auf ihre Strahlungsemissions- und Reflexionseigenschaften (konstante Radiosity) ist. 2. Alle Teilflächen sind Lambert-Strahler bzw. Reflektoren, d.h. die Lichtquellen zeigen ideal diffuse Emissionseigenschaften und alle Oberflächen haben ideal diffuse Reflexionseigenschaften. Ideal diffus bedeutet, dass Licht in alle Richtungen gleichmäßig abgestrahlt bzw. reflektiert wird. 3. Die Szene ist abgeschlossen bezüglich ihrer Strahlungsenergiebilanz, d.h. es wird weder Energie zugeführt noch abgegeben. Das Radiosity-Verfahren berechnet unabhängig vom Blickpunkt alle Lichtintensitäten einer Szene. Es benutzt den Energieerhaltungssatz in abgeschlossenen Systemen. Damit ist es ähnlich wie das Volume Rendering oder das Photonmapping beobachterunabhängig, d.h. die Berechnung wird einmal für alle Objekte durchgeführt und die vollständige Lösung des 3D-Objektraums wird dann einem Darstellungsprogramm übergeben, das das gewünschte Bild in 2D rendert, also die aus einer bestimmten Richtung sichtbaren Flächen ermittelt, projiziert und durch Interpolation schattiert (mittels Flatshading oder Gouraud Shading). Vorteil des Verfahrens ist ein überzeugender Realismus und die gute Eignung für matte Objekte, Nachteile sind ein noch höherer Rechenaufwand als beim Raytracing und ein hoher Speicherbedarf. Zudem muss die spiegelnde Reflexion gesondert behandelt werden (beispielsweise mit pixelbasiertem Raytracing). Außerdem ist das Verfahren gitterbasiert, lässt also keine einfache Behandlung analytisch definierter Primitive (Kugel, Konus, etc.) zu, sondern muss diese triangulieren und die Einzelflächen behandeln. Indirekte Beleuchtung und Lichtführung sind besonders in Museen gefragt, wo die Exponate gleichmäßig ausgeleuchtet sein sollen. Derartige Ansprüche an realistische Simulationen von Streulicht können nur mit dem Radiosity-Verfahren erreicht werden. Ein sehr bekanntes Beispiel findet sich auf der Webseite der Graphikgruppe an der Cornell University (siehe Abb. 4.2). Hauptsächlich findet Radiosity in speziellen Programmen für Innenarchitektur Verwendung, um einem Kunden ein geplantes Gebäude möglichst realistisch vorzuführen. Statische Gebäude eignen sich außerdem besser für die aufwändige Berechnung der Radiosity-Werte als dynamische Objekte und Animationen, da die Werte nur einmal für jede Szene berechnet werden müssen. Die folgende Abb. 4.3 stammt von 3d-architectural-rendering (www.archiform3d.com). 4.1. HERLEITUNG DES VERFAHRENS UND MODELLGLEICHUNG 59 Abbildung 4.2. Darstellung einer Museumsbeleuchtung (Cornell University). In Abb. 4.4 ist die so genannte Cornell Box dargestellt, die als Benchmark für das Lösen der RadiosityGleichung dient. Um realistische Bilder zu erzeugen, wird die Strahlungstransportgleichung für jeden einzelnen Farbkanal berechnet. Dadurch wird der als Colorbleeding bekannte Effekt erzielt: Farbige Wände strahlen ihre Farbe auf hellere Objekte ab. Bemerkung 4.1 Während Raytracing mit globaler Spiegelung arbeitet, aber kein Streulicht kennt, versucht das Radiosity-Modell global diffuse Reflexion zu behandeln. Der Nachteil besteht in einem nochmals höheren Aufwand als beim Raytracing. Zudem muss Spiegellicht gesondert behandelt werden. Daher eignet es sich eher für matte Objekte. Vorteile sind der überzeugende Realismus und die betrachterunabhängige Berechnung. 4.1 Herleitung des Verfahrens und Modellgleichung Radiosity wird betrachterunabhängig einmal für alle Objekte durchgeführt. Die vollständige Lösung in 3D wird in einem zweiten Schritt an ein Darstellungsprogramm übergeben, das ein projiziertes und mit Radiosity-Werten schattiertes Bild in 2D liefert. 60 KAPITEL 4. RADIOSITY Abbildung 4.3. Mit Radiosity-Verfahren gerenderter Wohnbereich eines Appartments. Definition 4.1 Als Radiosity definiert man die Energie pro Flächeneinheit, die ein Element je Zeiteinheit als Summe aus emittierter und reflektierter Energie verlässt. Der Formel für die Radiosity liegt das Strahlungsgleichgewicht in einem abgeschlossenen System zugrunde. Auf den Seiten 23 bis 26 in [SP94] findet sich eine genaue Herleitung der Radiosity B aus der Strahlung (Radiance) L über Z B(x) = L(x, θ, φ) cos θ dω. Ω Das führt schließlich zu der Formel für Radiosity, die als Integral dargestellt anschließend diskretisiert werden kann. Z B(x) = E(x) + R(x) B(x0 ) cos φx cos φx0 V (x, x0 ) dA0 ZS = E(x) + R(x) B(x0 ) x0 ∈S 1 cos φx cos φx0 V (x, x0 ) dx0 πr2 B(x) Gesamte vom Punkt x abgestrahlte Energie (Radiosity), eine Summe aus Eigenstrahlung und Reflexion als Leistung pro Flächeneinheit (Einheit [W/m2 ]) A0 Fläche um den Punkt x0 (Einheit [m2 ]) 4.2. DISKRETE RADIOSITYGLEICHUNG 61 Abbildung 4.4. Diese Cornell Box zeigt Colorbleeding. Es wurden 2370 einzelne Patches mittels Gouraud Shading gerendert. E(x) Emittierte Energie oder Eigenstrahlung in x ohne Fremdeinwirkung (Einheit [W/m2 ]) R(x) Reflexionsfaktor, der angibt, welcher Teil des einfallenden Lichtes wieder abgestrahlt wird (dimensionslos) S Alle Oberflächen der Szene (Einheit [m2 ]) V (x, x0 ) Verdeckungsfunktion, die die Sichtbarkeit von x zu x0 mit 1 bewertet, falls kein Objekt den Sichtstrahl blockiert. Sonst ist V = 0. ( 1 falls x von x0 aus sichtbar V (x, x0 ) = 0 sonst Die Verdeckungsfunktion ist eine Heavyside-Funktion. 4.2 Diskrete Radiositygleichung In einem ersten Schritt muss eine Aufteilung der Geometrie in Teilflächen (Dreiecke oder Quadrate) geschehen. Je feinmaschiger dabei das Gitter gewählt wird, desto genauer wird das Ergebnis, aber um so aufwändiger ist das Verfahren. Die Unterteilung der Szene bestimmt also den Aufwand des Algorithmus. Anders als beim Raytracing kann man keinen Vorteil aus der Darstellung einer Szene mit analytischen Primitiven wie z.B. Kugeln, Kegeln und Zylindern ziehen. Auch Flächen, die eine analytische Beschreibung haben, müssen unterteilt werden, wobei eine sehr feine Unterteilung für einen gleichmäßigen Verlauf der Schattierung auf der gekrümmten Fläche nötig ist. Wo die Feinheit der Unterteilung nicht durch die Krümmung vorgegeben ist, unterteilt man nur dort, wo es aus anderen Gründen erforderlich ist, also z.B. entlang der Begrenzung von Schatten auf einer an sich ebenen 62 KAPITEL 4. RADIOSITY Wand (siehe Abb. 4.7). Gleichmäßiges Verfeinern führt natürlich zu viel zu komplexen Strukturen und ist bei geringfügigen Änderungen der Radiosity nicht nötig. Daher wird meist adaptiv verfeinert, und zwar abhängig von • der Größe des Radiosity-Gradienten benachbarter Flächenstücke, • Diskontinuitäten im Lichtverlauf und bei • ungünstigen Netzen (z.B. T-Junctions). Abbildung 4.5. Zentralperspektivische Szene. Abbildung 4.6. Zerlegung der Szene. Abbildung 4.7. Eine adaptive Verfeinerung der Szene erhöht den Realismus bei begrenztem zusätzlichen Rechenaufwand, links: 145, mitte: 1021, rechts: 1306 Einzelflächen. In einem zweiten Schritt werden zur Lösung der Radiosity-Gleichung finite Elementverfahren angewendet. Meist wählt man konstante Basisfunktionen auf den einzelnen Flächenstücken, aber es sind auch lineare oder quadratische Funktionen denkbar. 4.3. BERECHNUNG DER FORMFAKTOREN 63 Unterteilt man die gesamte Szene in einzelne Flächenelemente Ai , so ergibt sich bezogen auf das i-te Flächenstück die Formel: Z Bi dAi = Ei dAi + Ri Bj Fji dAj j Darin bezeichnet Ei die von Ai emittierte Energie, der zweite Term die reflektierte Energie oder Reflektivität von Ai , die sich aus dem Reflexionsfaktor der Fläche Ai und der Radiosity aller übrigen Flächen Aj zusammensetzt, die gemäß ihrer geometrischen Lage über sogenannte Formfaktoren F gewichtet werden. In diesen Formfaktoren sind die Neigungswinkel sowie die Verdeckungsfunktionen der Flächen Ai und Aj zueinander zusammengefasst. Fläche Ai P Bj Aj Fji HH H H H j @ @ @ R @ Ai Ei Ri Ai P Bj Fij Abbildung 4.8. Berechnung der Radiosity für die Fläche Ai . Zur Berechnung der Radiosity-Werte Bi sind häufig gemachte Annahmen, dass jedes Ai planar ist und Bi sowie Ri über Ai konstant sind. Außerdem besteht die folgende reziproke Relation, bei der man sich leicht merken kann, dass der Formfaktor immer mit der Größe der abstrahlenden Fläche gewichtet wird. Ai Fij = Aj Fji Mit dieser reziproken Relation wird man die Abhängigkeit von der jeweiligen Größe der Flächen Aj los und kann das Ganze einzig aus der Sicht der aussendenden Fläche Ai beschreiben. Das Maß der Fläche Ai kürzt sich nun aus der Gleichung heraus und als diskrete Implementierung für insgesamt n Flächenstücke in der Szene ergibt sich die Formel (siehe [SP94], Seite 30) Bi = Ei + Ri n X Bj Fij . j=1 4.3 Berechnung der Formfaktoren Der Hauptanteil der Arbeit beim Lösen der obigen Gleichung besteht in der Berechnung der sogenannten Formfaktoren Fij . Diese Faktoren sind rein geometrisch motiviert, dimensionslos und be- 64 KAPITEL 4. RADIOSITY schreiben den Anteil der Energie, der vom i-ten Flächenstück abgestrahlt auf dem j-ten Flächenstück eintrifft. Diese Formfaktoren werden auch Gestalt- oder Winkelfaktoren genannt. Abbildung 4.9. Berechnung der Formfaktoren aus der Lage der Flächen. Definition 4.2 (Formfaktor oder Gestaltfaktor oder Winkelfaktor) Sei Ai ein Lambertscher Emitter, der eine bestimmte Menge eines Strahlungsflusses Φi emittiert. Sei Aj das Flächenelement, das einen Anteil Φij von Ai erhält. Der dimensionslose Quotient Fij := Φij Φi wird Formfaktor genannt. Eine generelle Lösung für die Formfaktoren wurde mithilfe analytischer Geometrie von Schröder und Hanrahan erst 1993 gefunden. FAi →Aj 1 = Fij = Ai Z Ai Z Aj 1 cos φi cos φj V (i, j) dAj dAi 2 πrij Darin ist rij der Abstand von dAi und dAj , φi der Winkel zwischen der Normalen Ni und dem Vektor in Richtung dAj . Der Winkel φj ist analog definiert. Der beim Formfaktor erstgenannte Index ist immer der Sender, der zweite der Empfänger. Bemerkung 4.2 Wenn man in planare Teilflächen unterteilt hat, sind alle Fii = 0, (i = 1, . . . , n) also alle Diagonalelemente = 1, da eine planare Fläche sich nicht selbst beleuchten kann. 4.3. BERECHNUNG DER FORMFAKTOREN 65 Bemerkung 4.3 Aufgrund der Definition der Formfaktoren und aufgrund der Energieerhaltung gilt folgende wichtige Eigenschaft n X Fij = 1 (1 ≤ i ≤ n). j=1 Die Berechnung der Formfaktoren ist der weitaus aufwändigste Teil des Radiosity-Verfahrens. Beschreibt man die Formfaktoren für beschränkte Flächen i und j in einer konvexen Umgebung, bei der sich keine Objekte gegenseitig verdecken, entfällt die Verdeckungsfunktion Vij . Die exakte Berechnung der Integrale erweist sich als ziemlich schwierig. Deswegen sucht man nach alternativen Berechnungsmethoden, um die Formfaktoren ausreichend gut annähern zu können. 4.3.1 Brute Force Ansatz Das simpelste Verfahren ist nur für Flächen korrekt, die relativ klein und relativ weit entfernt sind. Partielle Verdeckung wird ausgeschlossen, Winkel und Entfernungen werden nur zwischen zwei repräsentativen Punkten (z.B. den Mittelpunkten) beider Flächen ermittelt. Fij ≈ Aj 4.3.2 cos φi cos φj V (i, j) 2 π rij Methode nach Nusselt Eine weitere, genauere Möglichkeit, die Formfaktoren zu berechnen, beruht auf folgender geometrischer Beobachtung: Abbildung 4.10. Skizze zum Analogon von Nusselt, Fij ≈ FdAi Aj 66 KAPITEL 4. RADIOSITY Satz 4.1 (Analogon von Nusselt) Der Formfaktor von einer infinitesimal kleinen Fläche dAi zu einer Fläche Aj wird durch die Formel Z FdAi ,Aj = Aj cos φi cos φj V (i, j) dAj 2 πrij beschrieben. Dieser Wert ist äquivalent zu einem Flächenverhältnis, das sich wie folgt berechnet. Zunächst projiziert man diejenigen Teile der Fläche Aj , die von dAi aus sichtbar sind, auf eine Einheitshalbkugel, deren Zentrum sich im Mittelpunkt von dAi befindet. Diese Projektion wird nochmals senkrecht auf die Grundfläche der Halbkugel projiziert und die entstehende Fläche durch die Grundfläche der Halbkugel dividiert. 4.3.3 Hemicube Verfahren Das Nusselt Verfahren ist analytisch schwer zu beschreiben und umständlich zu implementieren. In einer weiteren Vereinfachung approximiert man daher die Halbkugel durch einen Halbwürfel (Hemicube-Verfahren). Die Außenflächen des Halbwürfels sind uniform in Zellen pi eingeteilt. Jede Zelle speichert einen Delta-Formfaktor, also den Anteil, der von der Fläche Aj auf das Zentrum dAi projiziert wird. Der endgültige Formfaktor errechnet sich somit aus der Summe der DeltaFormfaktoren all dieser betroffenen Zellen. FdAi ,Aj ≈ X ∆Fpi i Abbildung 4.11. Simulation der Halbkugel durch einen Halbwürfel 4.4. BERECHNUNG DER RADIOSITY-WERTE 4.3.4 67 Sillions Verbesserung und weitere Methoden Eine zusätzliche, von François Sillion gemachte Vereinfachung lässt sich erzielen, wenn man nur den Deckel des Würfels, also nur eine Ebene betrachtet. Dadurch verliert man einen Teil der Szeneninformation, aber der Rechenaufwand vermindert sich erheblich. In der Abb. 4.12 sind noch diverse andere Methoden aufgezeigt, wie man Formfaktoren berechnen kann. Dabei überwiegen die verschiedenen numerischen Verfahren, die zunächst grob in differentielle und totale Verfahren eingeteilt werden können. Die differenziellen Verfahren werden schließlich danach eingeteilt, ob sie die über dem Flächenstück Ai befindliche Hemisphäre abtasten oder die gesamte Fläche über einem differentiellen Flächenstück dAi . Abbildung 4.12. Berechnung der Formfaktoren, nach Cohen/Wallace: Radiosity and Realistic Image Synthesis [CW93]. 4.4 Berechnung der Radiosity-Werte Zur numerischen Berechnung der Radiosity-Werte Bi betrachten wir wieder die Gleichung Bi = Ei + Ri n X Bj Fij . j=1 Die Gleichung lässt sich umformen zu Bi − Ri n X j=0 Bj Fij = Ei (1 ≤ i ≤ n). 68 KAPITEL 4. RADIOSITY In Matrixschreibweise löst man dazu ein Gleichungssystem 1 − R1 F11 −R2 F21 .. . −Rn Fn1 −R1 F12 ··· −R1 F1n B1 E1 1 − R2 F22 .. . ··· −R2 F2n .. . B2 .. . = E2 .. . −Rn Fn2 ··· .. . 1 − Rn Fnn Bn En Gesucht werden Radiosity-Werte Bi für n Flächenstücke i ∈ {1, . . . , n}. Dabei sind die Emissionswerte Ei nur für Lichtquellen von Null verschieden. Der Formfaktor eines Flächenstücks muss nur einmal berechnet werden, es sei denn, dass sich die Geometrie der Szene ändert. Da der Reflexionsfaktor Ri und der Emissionswert Ei wellenlängenabhängig sind, muss das Gleichungssystem für jeden Wellenlängenbereich ausgewertet werden, der im Beleuchtungsmodell vorkommt. Dabei kann man sich auf die drei üblichen Primärfarben Rot, Grün und Blau beschränken, da sie für die Wahrnehmung und Darstellung ausreichen. Somit muss das Gleichungssystem nur drei Mal ausgewertet werden. Bemerkung 4.4 Die Formfaktoren Fij werden allein von der Geometrie einer Szene bestimmt. Sie müssen nicht neu berechnet werden, wenn sich nur die Beleuchtung ändert. Für ebene oder konvexe Flächenstücke gilt Fii = 0, d.h. Strahlung, die ein Flächenstück verlässt, trifft nicht wieder auf dieses Flächenstück zurück. Bemerkung 4.5 Der Reflexionsfaktor Ri und der Emissionsfaktor Ei sind grundsätzlich von der Wellenlänge abhängig. Dazu werden die einzelnen Farbkanäle gesondert behandelt. Ri wird vereinfacht monochromatisch betrachtet1 . Die Radiosity einer Fläche setzt sich somit aus der eigenen Energie (falls sie eine Lichtquelle ist) und der gewichteten Summe aller auf diese Fläche auftreffenden Energiewerte von anderen Flächen zusammen. Ein mögliches Lösungsverfahren für ein Gleichungssystem der Form (I − T ) · B = E ist das Gauß’sche Eliminationsverfahren. Die Variable (Unbekannte) ist hier die Radiosity B, die rechte Seite ist die Emission E, die lineare Matrix lautet (I − T ). Damit ist die Gleichung von der Form A · x = b und A bezeichne im Folgenden eine lineare Matrix. Gaußelimination ist jedoch nur bei vollbesetzten n × n Matrizen sinnvoll, da es bei dünnbesetzten Matrizen (also Matrizen, deren Anzahl der Nicht-Null-Einträge von O(n) ist) zu sogenannten “Fill-Ins“ kommt. Außerdem spricht auch der hohe Rechenaufwand von O(n3 ) gegen diese Methode. Die Invertierung der Matrix A löst ebenfalls das Gleichungssystem x = A−1 b. Jedoch ist dies bei zu großen Matrizen (also 1000 × 1000) unpraktisch, da der Aufwand auch bei O(n3 ) liegt. Eine 1 Für genauere Berechnungen muss wellenlängenabhängig vorgegangen werden. 4.4. BERECHNUNG DER RADIOSITY-WERTE 69 bessere Möglichkeit zur Lösung sind Iterationsverfahren. Dazu zählen das Jacobi- und das GaußSeidel Verfahren. 4.4.1 Allgemeine Iterationsverfahren Gegeben sei eine nichtsinguläre n × n-Matrix A und ein lineares Gleichungssystem Ax = b mit der exakten Lösung x = A−1 b. Ausgehend von einem Startvektor x(0) wird eine Folge von Vektoren x(0) → x(1) → x(2) → . . . erzeugt, die gegen die gesuchte Lösung x konvergiert, d.h. es werden Fixpunktverfahren der Form x(i+1) = Φ(x(i) ) (i = 0, 1, . . .) betrachtet, wobei eine Iterationsfunktion Φ so konstruiert wird, dass sie genau einen Fixpunkt besitzt und dieser gerade die gesuchte Lösung x = A−1 b ist. Durch Hinzunahme einer beliebigen nichtsingulären n × n-Matrix M erhält man eine solche Iterationsvorschrift aus der Gleichung M x + (A − M )x = b, (4.1) M x(i+1) + (A − M )x(i) = b (4.2) indem man setzt und nach x(i+1) auflöst ⇔ x(i+1) = x(i) − M −1 (Ax(i) − b) = (I − M −1 A)x(i) + M −1 b x(i+1) = S x(i) + M −1 b, wobei zur Vereinfachung die Matrix S := (I − M −1 A) eingeführt wird. Definition 4.3 Ein Iterationsverfahren zur Lösung von Ax = b heißt konsistent genau dann wenn x ein Fixpunkt der Iteration ist. Um die Konsistenz des Verfahrens oder anders ausgedrückt die Konvergenz der Iteration gegen die Lösung anhand der Matrix S erkennen zu können, werden Spektralradius und Matrixnorm definiert. 70 KAPITEL 4. RADIOSITY Definition 4.4 (Spektralradius) Sei A ∈ Cn×n eine beliebige Matrix. Der Spektralradius ρ einer Matrix A ist das Maximum über sämtliche Eigenwerte λi von A ρ(A) := max |λi |. 1≤i≤n Definition 4.5 (Matrixnorm) Sei A ∈ Cn×n eine beliebige Matrix. Für x ∈ Cn und einer gegebenen . Vektornorm kxk wird die Matrixnorm definiert durch k|A|k := sup kAxk kxk x6=0 Jetzt kann man das Konvergenzkriterium in einem Satz formulieren. Satz 4.2 1. Das Verfahren x(i+1) = S x(i) + M −1 b ist genau dann konvergent, wenn ρ(S) < 1. 2. Hinreichend für die Konvergenz des Verfahrens ist die Bedingung k|S|k < 1 für beliebige Matrizen M . Zum Beweis dieses Satzes benötigt man nun folgende zwei Sätze: Satz 4.3 (Hirsch) Für alle Eigenwerte λ von A gilt |λ| ≤ k|A|k . Satz 4.4 1. Zu jeder Matrix A und jedem > 0 existiert eine Vektornorm mit k|A|k ≤ ρ(A) + . 2. Hat jeder Eigenwert λ von A mit der Eigenschaft |λ| = ρ(A) nur lineare Elementarteiler, so existiert sogar eine Vektornorm mit k|A|k = ρ(A). Beweis von Satz 4.2: Für den Fehler fi := x(i) − x folgt durch Subtraktion der Gleichung (4.1) von der Gleichung (4.2) fi+1 = Sfi 4.4. BERECHNUNG DER RADIOSITY-WERTE 71 bzw. durch wiederholtes Anwenden der Matrix S auf den anfänglichen Fehler fi = S i f0 i = 0, 1, . . . Sei nun x(i+1) = S x(i) + M −1 b konvergent. Dann ist lim fi = 0 für alle f0 . Wählt man f0 als i→∞ Eigenvektor zum Eigenwert λ von S, dann folgt daraus fi = λi f0 . Da lim fi = 0, muss |λ| < 1, und daraus folgt schließlich ρ(S) < 1. i→∞ Sei umgekehrt ρ(S) < 1, so folgt aus Satz 4.4 sofort lim S i = 0 und so lim fi = 0 für alle f0 . Die i→∞ i→∞ hinreichende Bedingung für die Konvergenz des Verfahrens k|S|k < 1 folgt unmittelbar aus Satz 4.3. Es werden nun spezielle Verfahren erläutert, die von der Wahl der Matrix M abhängen. Dabei wird die Matrix A = L + D + R in eine linke untere Matrix L, eine Diagonalmatrix D = diag(a11 , . . . , ann ) und eine rechte obere Matrix R, in Matrixschreibweise 0 a12 . . . a1n a11 0 . . . 0 0 ... 0 0 .. .. .. .. .. . . . . . . . 0 0 0 a22 . . a21 . . L= . . , R = . , D = . . . . . .. . . an−1,n .. .. 0 .. .. .. .. 0 0 0 0 ... 0 an1 . . . an,n−1 0 0 . . . 0 ann zerlegt. Die Matrix M sollte nun eine leicht zu invertierende Matrix sein und es sollte gelten M ≈ A, denn dann würde das Verfahren die exakte Lösung liefern. 4.4.2 Jacobiverfahren Wählt man nun für M = D, so resultiert daraus das Jacobiverfahren mit der Vorschrift x(i+1) = (I − D−1 A)x(i) + D−1 b = −D−1 (L + R)x(i) + D−1 b. Das Jacobiverfahren wird synonym auch als Gesamtschrittverfahren bezeichnet. Erst wenn alle vorherigen Werte x der i-ten Iteration bekannt sind, wird der neue Wert x(i+1) in einem Gesamtschritt ermittelt. 72 KAPITEL 4. RADIOSITY Definition 4.6 (Diagonaldominanz) Eine Matrix A ∈ KI×I heißt stark diagonaldominant, wenn X |aii | > |aij | ∀i ∈ I j∈I,i6=j Eine Matrix A ∈ KI×I heißt schwach diagonaldominant, wenn X |aii | ≥ |aij | ∀i ∈ I j∈I,i6=j Für das Jacobiverfahren gilt der Konvergenzsatz: Satz 4.5 Das Jacobiverfahren konvergiert für alle stark diagonaldominanten Matrizen A. 4.4.3 Gauß-Seidel Verfahren Für das Gauß-Seidel-Verfahren wählt man M = L + D und die dazugehörige Iterationsvorschrift x(i+1) = (I − (D + L)−1 A)x(i) + (D + L)−1 b = −(D + L)−1 Rx(i) + (D + L)−1 b. Damit ist das Gauß-Seidel Verfahren ein Einzelschrittverfahren, denn aufgrund der speziellen Struktur können bereits ermittelte Werte der (i + 1)-ten Iteration in die Berechnung der noch fehlenden Werte dieser Iteration eingehen. Für das Gauß-Seidel Verfahren gilt: Satz 4.6 Das Gauß-Seidel Verfahren konvergiert für alle stark diagonaldominanten Matrizen A und es gilt k|SG |k∞ ≤ k|SJ |k∞ < 1. 4.4.4 SOR-Verfahren (Successive Overrelaxation) bzw. Relaxationsverfahren Eine weitere Möglichkeit, bessere Konvergenzbedingungen, als mit dem Gauß-Seidel-Verfahren zu erzielen, ist eine ganze Klasse von Matrizen M (ω) in Abhängigkeit eines Parameters ω zu betrachten. Die Kunst liegt nun darin, ω so zu wählen, dass R(I − M (ω)−1 A) möglichst klein wird. Man wählt M (ω) folgendermaßen: 1 M (ω) = D(I + ωL) ω Man kann jedoch beweisen, dass das Verfahren nur für 0 < ω < 2 konvergiert und R(I − M (ω)−1 A) minimal wird, wenn 2 ω= 2 − λmin − λmax 4.4. BERECHNUNG DER RADIOSITY-WERTE 73 gewählt wird. Für ω < 1 spricht man von Unterrelaxation und für ω > 1 von Überrelaxation. Jedoch gelten diese Sätze nur, falls A positiv definit ist. 4.4.5 Anwendbarkeit der Iterationsverfahren auf Radiosity Um das Jacobi- oder das Gauß-Seidel Verfahren auf die Berechnung der Radiosity-Werte anwenden zu können, muss noch gezeigt werden, dass die Radiosity-Matrix A wirklich stark diagonaldominant ist. Sei aij ∈ A (1 ≤ i, j ≤ n). Man betrachtet dazu die Diagonalelemente der Matrix A. aii = 1 − Ri Fii = n X Fij − Ri Fii > j=1 da n X Ri Fij − Ri Fii = j=1 n X n X Ri Fij , j=1,j6=i Fij = 1 und Fij > Ri Fij (Ri < 1) j=1 ⇒ |aii | > n X |aij | j=1,j6=i Also sind beide Verfahren auf die Radiosity-Matrix anwendbar. Das Jacobiverfahren benötigt in jeder Iteration zwei Vektoren, da der neue immer aus dem alten berechnet wird. Das Gauß-Seidel Verfahren braucht dagegen nur einen Vektor, da es in jedem Iterationsschritt sofort die bis dahin errechneten Werte für die weitere Berechnung benutzt. D.h. das Jacobiverfahren errechnet immer nur eine Reflexion pro Iteration, während das Gauß-Seidel Verfahren mehrere Reflexionen pro Iteration berechnet. Das ist auch der Grund, warum das Gauß-Seidel Verfahren im Allgemeinen fast doppelt so schnell konvergiert wie das Jacobiverfahren. Dafür ist das Jacobiverfahren sehr leicht parallelisierbar. 4.4.6 Progressive Verfeinerungen Die hohen Kosten der Radiosity-Methode liegen in der Berechnung der Formfaktoren. Daher werden sie einmal berechnet und danach gespeichert. Auch wenn viele Formfaktoren aus Sichtbarkeitsgründen Null gesetzt werden können, ist der potenzielle Speicherbedarf das Quadrat aus der Anzahl der Patches. In konventionellen Algorithmen werden alle Formfaktoren im Voraus berechnet. Eine Abschätzung der Radiosity-Werte ist daher erst nach der ersten vollständigen Iteration des GaußSeidel Verfahren möglich. Um schnell eine Szene mit Radiosity rendern zu können, kann man die Formfaktoren on-the-fly berechnen lassen, wobei der Halbwürfel über einem Flächenstück Ai nach und nach verfeinert wird. In den Abbildungen 4.13 bis 4.18 werden Bildbeispiele aus der Veröffentlichung von Cohen et al. über Progressive Refinement [CCWG88] gezeigt, in denen jeweils für 1, 2, 24 und 100 Halbwürfel Aufnahmen der Szene gemacht worden sind. 74 KAPITEL 4. RADIOSITY Die Radiosity Berechnung mit Progressive Refinement macht es nötig, zwischen zwei Typen von Oberflächen (Faces) zu unterschieden: Definition 4.7 (Patch) Ein Patch ist ein Drei- oder Viereck, das in der Lage ist Energie auszusenden. Die Energie des Patches wird nur vom Zentrum des Patches emittiert. Um eine schnelle Lösung berechnen zu können, sollte man die Szene in so wenig Patches wie möglich unterteilen. Das Patch muss klein genug sein, eine Energieverteilung auf seine gesamte Fläche realistisch erscheinen zu lassen. Wenn beispielsweise ein kleines Objekt über dem Zentrum des Patches die Abstrahlung vollständig blockiert, muss das Patch unterteilt werden. Definition 4.8 (Element) Elemente sind Drei- oder Vierecke welche Energie erhalten. Jedes Element ist einem Patch zugeordnet, Patches sind in mehrere kleine Elemente aufgeteilt. Wenn ein Element Energie empfängt, wird ein Teil davon absorbiert. Die restliche Energie wird dem Patch zugeführt, und von dort wieder abgestrahlt. Mit der für die Elemente berechneten Radiosity werden die Oberflächen dargestellt, daher ist es wichtig, dass diese so klein wie möglich sind. Nur so können fein abgestufte Schattengrenzen und Lichtverläufe errechnet werden. Bei der Methode des Progressive Refinement werden zunächst alle verfügbaren Patches untersucht. Das am stärksten aufgeladene Patch schießt nun seine Energie in die Umgebung. Die vom Patch aus sichtbaren Elemente erhalten diese Energie und fügen sie ihrer eigenen Energie hinzu. Dieser Prozess wird itteriert, bis die unverbrauchte Energie einen bestimmten Wert unterschritten hat. Mit Hilfe von Halbwürfeln wird berechnet, wieviel Energie jedes Patch an ein Element abstrahlt. Jeder Halbwürfel besteht aus fünf kleinen Bildern der Umgebung, die vom Zentrum des Patches aus durch diese Würfelfläche zu sehen ist. Für jedes Pixel dieser Bilder wird ein bestimmtes Element farbkodiert und die transmittierte Energie berechnet. Diese Methode ist eine Vereinfachung der richtigen Radiosity Formel (der Form-Faktor Berechnung). Deshalb ist die Auflösung des Halbwürfels, also die Anzahl an Pixeln in seinen Bildern, immer nur eine Annäherung. Die Größe der Patches und Elemente bestimmen die Qualität der Radiosity Lösung. Deshalb wurden Methoden zur automatischen Unterteilung entwickelt. Einerseits kann man die emittierenden Patches unterteilen. Dazu wird Lichtenergie in die Umgebung geschossen, und der über den Halbwürfel berechnete Wert mit den Werten eines nächst feiner unterteilten Patches verglichen. Wird eine Fehlerschranke unterschritten, kann man die Verfeinerung beenden. Andererseits kann es nötig sein, die empfangenden Elemente zu verfeinern. Wenn innerhalb eines Patches sehr starke Energieunterschiede (Gradienten) zwischen den Elementen gefunden werden, werden die Elemente dieses Patches unterteilt. Das führt zu kleineren Elementen und einer längeren Lösungszeit, aber einer größeren Detailliertheit. 4.4. BERECHNUNG DER RADIOSITY-WERTE 75 Abbildung 4.13. Gauß-Seidel nur mit Gathering-Verfahren, für 1, 2, 24 und 100 Hemikuben. 4.4.7 Gathering Verfahren (= Einsammeln) Jacobi- und Gauß-Seidel Verfahren sind so genannte Gathering-Methoden (siehe [CCWG88]). Damit ist gemeint, dass ein Patch die Radiosity der übrigen Patches in der Szene einsammelt. Die Lösung einer Zeile des Gleichungssystems beim Gauß-Seidel Verfahren liefert den Radiosity-Wert eines Patches. Genauer: Gathering über einen Hemi-Cube erlaubt es die Radiosity über einen Patch zu aktualisieren. x x x = + x x x x x x x x x x x x x x x x Abbildung 4.14. Links Pn die Skizze des Gathering Verfahrens und rechts die Matrizenbelegung im Fall des Gathering, Bi = Ei + Ri j=1 Fij Bj . Der Pseudo-Code für das Gathering sieht wie folgt aus: for (i = 0, i < n; i++) B[i] = E[i]; while (no convergence) { for (i = 0; i < n; i++) 76 KAPITEL 4. RADIOSITY { B_sum = 0; for (j = 0; j < n; j++) B_sum += F[i][j] * B[j]; B[i] = E[i] + R[i] * B_sum; } render(B); } 4.4.8 Shooting Verfahren (= Aussenden) Abbildung 4.15. Gauß-Seidel nur mit Shooting Verfahren, für 1, 2, 24 und 100 Hemikuben. Beim Shooting wird jeweils das Licht des Patches mit der höchsten Energie in die Umgebung verschossen. Genauer: Shooting über einen Hemi-Cube erlaubt es, die Radiosity mehrerer Patches zu aktualisieren. x x x x x x x x x x x = + x x x x x x x x x x x x x x x x x Abbildung 4.16. Links die Skizze des Shooting Verfahrens und rechts die Matrizenbelegung im Fall des Shooting, Bj = Bj + (Rj Fji )Bi . Wie auch im Gathering-Verfahren wird der Wert für die Radiosity der Fläche Ai mit dem Emissionsterm initialisiert. Darüberhinaus wird auch die von dieser Fläche nicht über dieses Element verschos- 4.4. BERECHNUNG DER RADIOSITY-WERTE 77 sene Energie mit dem Emissionsterm initialisiert. Der Pseudo-Code für das Shooting sieht wie folgt aus: for (i = 0, i < n; i++) B[i] = dB[i] = E[i]; // dB[i]: unshot radiosity while (no convergence) { set i as dB[i] is the largest { for (j = 0; j < n; j++) { db = R[j] * F[j][i] * dB[i]; dB[j] += db; // update change since last time patch j shot // light B[j] += db; // update total radiosity of patch j } dB[i] = 0; // reset unshot radiosity for patch i to zero } render(B); } Bei der Benutzung von einfachem Gauß-Seidel Verfahren bleibt die Szene auch mit 100 Halbwürfeln relativ dunkel (siehe Abb. 4.13). Wenn man das Shooting ohne die Sortierung nach dem größten Energiewert verwendet, wird kein allzu großer Unterschied zum Gathering sichtbar (siehe Abb. 4.15). Aber wenn man beim Shooting-Verfahren zusätzlich nach der Helligkeit der auftretenden Patches sortiert, erhellt sich auch die Szene schneller. Man erkennt deutlich den Unterschied zum reinen Shooting-Verfahren (siehe Abb. 4.17). In Abb. 4.18 wurde auch noch ein konstanter ambienter Anteil von Anfang an aus Sichtbarkeitsgründen in die Szene eingerechnet. Er hängt in jedem Verfeinerungsschritt von den jeweils bis dahin berechneten Radiosity-Werten aller Patches und der Reflektivität der Umgebung ab. Er geht aber nicht in die Lösung des Gleichungssystems ein und wird nur in jedem Iterationsschritt in geringerem Maß in der Rendergleichung verwertet. Abbildung 4.17. Kombination aus Shooting mit Sortierverfahren, für 1, 2, 24 und 100 Hemikuben. 78 KAPITEL 4. RADIOSITY Abbildung 4.18. Hier wurde Shooting und Sorting kombiniert und mit einem ambienten Anteil bei der Darstellung verrechnet, ebenfalls für 1, 2, 24 und 100 Hemikuben. 4.5 Rendern mit Radiosity-Werten Da der Radiosity-Wert pro Flächenstück konstant ist, kann er auf Vertices abgebildet und dann dem Renderer übergeben werden. Die Berechnung der Vertex-Radiosities erfolgt beispielsweise nach einem Ansatz von Cohen und Greenberg [CG88]. Dabei wird unterschieden, ob der Vertex im Inneren einer zusammenhängenden Fläche oder am Rand oder in einer Ecke liegt. • Die Radiosity für einen Vertex BM im Inneren einer Fläche wird über die angrenzenden Flächenstücke gemittelt. • Der Mittelwert der Vertex-Radiosity eines Randpunktes und des nächstliegenden inneren Punktes entsprechen dem Mittelwert der Radiosity aller an diesem Randpunkt angrenzenden Flächen. Abbildung 4.19. Berechnung der Vertex-Radiosity. Zu dieser Berechnung sei hier das Beispiel aus der Abb. 4.19 in Formeln dargestellt. Die Indizes M , und N O bezeichnen die Vertex-Radiosity in den Knoten Mitte, Nord und Nord Ost, während die Ziffern die Radiosity auf den jeweiligen Flächenstücken bezeichnen. N 1 BM = (B1 + B2 + B3 + B4 ) 4 1 1 (BN + BM ) = (B1 + B2 ) ⇒ BN = B1 + B2 − BM 2 2 1 (BN O + BM ) = B2 ⇒ BN O = 2B2 − BM 2 4.6. ÜBUNGSAUFGABEN 4.5.1 79 Lichtlecks und Diskontinuitäten Typische Fehler, die beim Rendern auftreten können, betreffen die Art wie die Gitter die Geometrie widerspiegeln. Sogenannte Lichtlecks entstehen, wenn ein Gitterpunkt die gemittelte VertexRadiosity von Flächen bekommt, die beispielsweise durch eine Wand getrennt jeweils ganz unterschiedlichen Beleuchtungen ausgesetzt sind (siehe Abb. 4.20 links). Abhilfe schafft hier die Modellierung geschlossener Räume bzw. eine Wandstärke, die so groß wie die Maschenweite der angrenzenden Wände ist. Ein anderer schwerer zu entdeckender und zu behebender Fehler betrifft die Unterteilung aneinander angrenzender Flächen (siehe Abb. 4.20 rechts). Ein Sprung oder Versatz von Gitterpunkten wird bei anschließender linearer Interpolation der Farbwerte diskontinuierliche Verläufe zeigen. Abbildung 4.20. Links Lichtlecks, rechts Diskontinuitäten, die als Fehler beim Rendern mit Radiosity-Werten auftreten können (aus Cohen/Wallace: Radiosity and Realistic Image Synthesis [CW93]). 4.6 Übungsaufgaben Aufgabe 4.1 Formfaktoren Für Radiosity spielen die sogenannten Formfaktoren Fij eine wichtige Rolle. Für eine Szene, die aus n Flächenstücken besteht, definiert man Z Z 1 cos θi cos θj Fij = dAj dAi (1 ≤ i, j ≤ n). 2 Ai Ai Aj πrij Dabei wird volle Sichtbarkeit des Flächenstücks Ai von Aj vorausgesetzt. Der Abstand zwischen den Flächenstücken i und j ist rij und der Winkel θi befindet sich zwischen der Normalen der Fläche Ai 80 KAPITEL 4. RADIOSITY und dem Richtungsvektor auf die Fläche Aj . (a) Leiten Sie eine Beziehung zwischen Fij und Fji her. (b) Um die Sichtbarkeit zu garantieren, wird eine Verdeckungsfunktion Vij unter dem Integral eingeführt. ( 1 falls Flächenstück i von j aus voll sichtbar Vij = 0 sonst Schreiben Sie jetzt die vollständige Definition hin. Wie groß ist Fii für ebene oder konvexe Flächen? (c) Die Formel für Radiosity Bi der Teilfläche i lautet Bi Ai = Ei Ai + Ri n X Bj Aj Fji (1 ≤ i ≤ n) j=0 mit einer emittierten Energie Ei und dem Reflexionsfaktor Ri . Aus der Definition der Formfaktoren und der Energieerhaltung im System leiten Sie die folgende Beziehung her: n X j=1 Fij = 1 (1 ≤ i ≤ n) Kapitel 5 Photon Mapping Die größten Schwächen des Raytracing bestehen darin, dass es KEINE diffusen Abstrahlungen und KEINE Kaustik wiedergeben kann. Während man für die diffusen Abstrahlungen, dem sogenannten Color bleeding oder Ausbluten von Farbe auf benachbarte Flächen, mit Radiosity Abhilfe schaffen kann, indem man mit finite Elementmethoden Strahlungsgleichgewichte zwischen einzelnen Flächenstücken berechnet, hatte man für die Kaustik, also das Bündeln oder Fokussieren von Lichtstrahlen keine wirklich gute Methode. Lichtreflexe auf dem Boden eines Schwimmbeckens oder am Fuß eines Cognacglases, eine Lupe, die als Brennglas dient, konnten nicht wirklich wiedergegeben werden. Das Photon Mapping ist eine Methode, die als Ergänzung zum Raytracing zu sehen ist. Sie wurde in den Jahren 1993/94 in der Dissertation von Henrik Wann Jensen entwickelt und 1995 veröffentlicht. Beide oben genannten Probleme, das Ausbluten und die Kaustik, können mit Photon Mapping gelöst werden: es sind indirekte Beleuchtungen diffuser Oberflächen. Außerdem können auch Streuungen an Volumen in ähnlicher Weise in diese Technik einbezogen werden und so Nebel und Rauch realistisch erscheinen lassen (Participating Media). Zudem ist sie einfach parallelisierbar. Dieses Skript lehnt sich eng an die Ausführungen im SIGGRAPH Course 38 von 2001 an (siehe [JCS01]). Die Idee ist denkbar einfach: man stelle sich Licht in Form von Teilchen vor, die von der Lichtquelle in zufällige Richtungen emittiert werden und dabei Energie nach Farbkanälen aufgespalten transportieren. In einem ersten Schritt wird eine Photon Map erstellt, die alle Ereignisse des Aufpralls eines zufällig gestreuten Photons auf ein nichtreflektierendes Objekt registriert. Der zweite Schritt besteht im Rendering Pass, der mit statistischen Techniken die Informationen über hereinkommenden Fluss und reflektierte Strahlung an jedem Punkt berechnet. Die Photon Map ist von der geometrischen Repräsentation entkoppelt. Dadurch ist sie bei komplexen Szenen der Methode des Radiosity klar überlegen, denn Photon Mapping benötigt kein Gitter und skaliert daher besser, wenn die Anzahl der Objekte groß ist. Außerdem ist noch anzumerken, dass das Verfahren nicht patentiert ist und daher bereits in viele gängige Raytracingalgorithmen übernommen wurde (beispielsweise in Povray und Renderpark). 81 82 KAPITEL 5. PHOTON MAPPING Abbildung 5.1. Henrik Wann Jensen 5.1 Die Spur der Photonen Ziel des Photonenverfolgens ist die Berechnung von indirekter Beleuchtung auf diffusen Oberflächen, die beispielsweise auch durch die Bündelung von Licht an spiegelnden oder transparent fokussierenden Objekten entsteht. 5.1.1 Photonemission Photonen werden von einer Lichtquelle über eine Verteilungsfunktion emittiert, die von der emissiven Lichtstärke bestimmt wird. Hier muss zwischen der Lichtstärke und dem Photonenfluss vermittelt werden. Man unterscheidet (a) punktförmige und (b) gerichtete Lichtquellen, (c) Schlaglichter oder (d) generelle Lichtobjekte (für die man über goniometrische Diagramme die Emission bestimmt). Während man für die Photonen bei (a) gleichmäßig verteilte zufällige Richtungen von einem Punkt aus wählt, haben die Photonen im Fall (b) alle dieselbe Richtung, nämlich die aus der das Licht einstrahlt (mit vierten Koordinate w = 0, also unendlich weit entfernt). Im Fall (c) eines Schlaglichts (z.B. ein rechteckiges Fenster), nimmt man zufällig verteilte Positionen innerhalb der ausgedehnten Fläche des Schlaglichts an und ermittelt zufällige Richtungen mit einer über den Kosinus verteilten Wahrschein- 5.1. DIE SPUR DER PHOTONEN 83 lichkeit (die Null ist, für parallel zur Fläche emittierte Photonen und höchste Wahrscheinlichkeit für senkrecht abgestrahlte Photonen hat). Im allgemeinen Fall (d) variiert man die Wahrscheinlichkeit der Position auf der Lichtquelle und die Richtung des Photons. Die Stärke des Lichts (in Watt, [w]) muss von den emittierten Photonen reproduziert werden. In einer Formel ausgedrückt muss gelten Pphoton = Plight ne (5.1) mit der Lichtstärke Pphoton für ein einzelnes Photon, während Plight die gesamte Lichtstärke der Quelle und ne die Anzahl der emittierten Photonen ist. Abbildung 5.2. Mögliche Lichtquellen von links nach rechts: (a) Punktförmige Lichtquelle, (b) gerichtete Lichtquelle, (c) Schlaglicht, (d) generelles Lichtobjekt Pseudocode für das Aussenden von Photonen: emit_photons_from_diffuse_point_light(){ ne = 0; // number of emitted photons while (not enough photons) { do { x = random number between -1 and 1; y = random number between -1 and 1; z = random number between -1 and 1; } d = <x,y,z>; p = light source position; trace_photon_from_p_in_direction_d(); ne= ne + 1; } scale power of stored photons with 1/ne } 84 KAPITEL 5. PHOTON MAPPING Bemerkung 5.1 Szenen mit vielen Lichtquellen benötigen nicht mehr Photonen als Szenen mit nur einer Lichtquelle, da jede Lichtquelle zur gesamten Beleuchtung weniger beiträgt. Wenn nur wenige Lichtquellen für die gesamte Beleuchtung von Bedeutung sind, kann man die Bedeutung in einer Abbildung festhalten (Importance sampling map), um danach die Photonen zu konzentrieren. Bemerkung 5.2 Statt Photonen unterschiedlicher Energieniveaus für schwächere und stärkere Lichtquellen zu speichern, kann man auch einfach die Anzahl der emittierten Photonen bei schwächeren Quellen reduzieren. Tausend Photonen mit halber Energie entsprechen fünfhundert Photonen mit voller Energie. In Szenen mit wenigen Objekten treffen viele der emittierten Photonen auf gar kein Objekt. Um diese Verschwendung von Rechenleistung zu reduzieren, optimiert man die Emission über sogenannte Projection maps. Definition 5.1 Eine Projection map ist eine Abbildung der Geometrie aus Sicht einer Lichtquelle. Sie besteht aus vielen einzelnen Zellen, die angeschaltet sind, falls geometrische Objekte in dieser Richtung liegen, und ausgeschaltet sind, falls das nicht der Fall ist. In der Praxis hat sich das Clustern von Objekten und ein Arbeiten mit Bounding spheres oder Bounding boxes als nützlich erwiesen. Mit der Projection map erhält man eine konservative Abschätzung für die Richtung, in der es nötig ist, Photonen zu emittieren. Das generelle Vorgehen sieht bei dünn besetzten Szenen eine Schleife über alle angeschalteten Zellen vor. Es werden zufällig Photonen in den Bereich dieser Zellen emittiert. Das kann allerdings zu verzerrten Ergebnissen führen, wenn die Anzahl angestrebter Photonenereignisse bereits erreicht ist, bevor alle Zellrichtungen abgearbeitet sind. Daher wird man bei dicht besetzten Szenen zunächst eine zufällige Richtung generieren, dann testen, ob die Zelle in dieser Richtung angeschaltet ist. Andernfalls generiert man eine neue Richtung. Dieses Testen ist für dünn besetzte Szenen zu kostspielig und bringt im dicht besetzten Fall nur dann einen Vorteil gegenüber dem Arbeiten ohne Projection map, wenn man die Objekte in Clustern und begrenzenden Volumina organisiert. Jedenfalls aber muss man die Gleichung 5.1 mit dem Verhältnis aus angeschalteten Zellen zur Gesamtzahl der Zellen wichten. Pphoton = Plight # of cells with objects ne total # of cells (5.2) Ein weiterer Vorteil von Projection maps besteht darin, dass man Objekte mit spiegelnden Eigenschaften leicht identifizieren kann. Diese meist wenigen Objekte sind wichtig für das Erzeugen von Kaustiken. 5.1. DIE SPUR DER PHOTONEN 5.1.2 85 Photonenverfolgung mit russischem Roulette Die Photonenverfolgung basiert auf dem Raytracing ganz ähnlichen Verfahren, mit dem Unterschied, dass hier die emittierten Photonen in die Szene verfolgt werden. Dieses Verfahren wird von den verschiedenen Autoren meist als Light ray tracing oder Forward ray tracing manchmal auch Backward path tracing bezeichnet. Beim Verfolgen des Strahls müssen im Wesentlichen Schnittpunkte mit Objekten berechnet werden, an denen ein Richtungswechsel des Strahls geschieht. Dabei transportieren Photonen Energie in Form eines Energieflusses, während Sichtstrahlen, die durch jeweils alle Pixel in eine Szene verfolgt werden, eine Strahlungsdichte an den jeweiligen Schnittpunkten einsammeln. Beispiel 5.1 Die Wechselwirkung eines Photons mit einem Material ist anders als bei einem Sichtstrahl: Für den Strahl existiert ein Brechungsindex, für das Photonenteilchen nicht. Wenn ein Photon auf ein Objekt trifft, wird es entweder (a) diffus oder spiegelnd reflektiert, (b) diffus oder spiegelnd transmittiert oder (c) absorbiert (ausgelöscht). Die Wahrscheinlichkeit für die drei Fälle hängt von den jeweiligen Materialeigenschaften ab. Wenn wir zunächst den monochromatischen reflektierenden Fall betrachten, so gilt kd + ks ≤ 1. Dabei ist kd der diffuse und ks der spiegelnde Reflexionskoeffizient. Sei nun ξ ∈ [0, 1] eine gleichmäßig verteilte Zufallsvariable (die man z.B. mit drand48() berechnet). Man unterscheidet ξ ∈ [0, kd ] ξ ∈ [kd , kd + ks ] ξ ∈ [kd + ks , 1] → → → diffuse Reflexion spiegelnde Reflexion Absorption. Diese Methode ist bekannt als Russisches Roulette. Die Energie eines Photons muss dabei nicht modifiziert werden! Beispiel 5.2 Ein Material, dessen Oberfläche 50 % des eingestrahlten Lichts reflektiert, wird auch nur die Hälfte der ankommenden Photonen reflektieren (mit voller Energie). Die restlichen 50 % werden absorbiert. 86 KAPITEL 5. PHOTON MAPPING Im chromatischen Fall (z.B. mit drei Farbkanälen RGB) bestimmt man jeweils eine Wahrscheinlichkeit für diffuse und spiegelnde Reflexion, statt einfach kd und ks einzusetzen. Daher erhält man für den diffusen Fall: Pd = max(kdr Pr , kdg Pg , kdb Pb ) max(Pr , Pg , Pb ) spiegelnden Fall: Ps = max(ksr Pr , ksg Pg , ksb Pb ) , max(Pr , Pg , Pb ) und den wobei (kdr , kdg , kdb ) die diffusen, (ksr , ksg , ksb ) die spiegelnden Reflexionskoeffizienten sind und das Tupel (Pr , Pg , Pb ) die Energie des einfallenden Photons nach Farbkanälen aufgespalten darstellt. Die Wahrscheinlichkeit der Absorption bei reflektierenden (nicht transmittierenden) Oberflächen beträgt P a = 1 − Pd − Ps mit einer Zufallsvariablen ξ ∈ [0, 1] und ξ ∈ [0, Pd ] ξ ∈ [Pd , Pd + Ps ] ξ ∈ [Pd + Ps , 1] → → → diffuse Reflexion spiegelnde Reflexion Absorption. Jetzt muss allerdings die Energie des reflektierten Photons angepasst werden, denn entweder wird das Photon mit voller Energie gespiegelt oder mit voller Energie diffus gestreut. Sollte spiegelnde Reflexion ausgewählt worden sein, ergibt sich: Prefl,r = Pin,r /Ps Prefl,g = Pin,g /Ps Prefl,b = Pin,b /Ps Diese Vorgehensweise ist natürlich auf transmittierte Strahlung erweiterbar. Auch das Aufspalten in nur drei Farbkanäle kann auf generelle Wellenlängenabhängigkeit erweitert werden. Für spezielle Reflexionseigenschaften wie glänzende oder richtungsabhängige diffuse Reflexion wurden ebenfalls geeignete Modelle auf Basis von Wahrscheinlichkeiten entwickelt. Vorteil von Russischem Roulette: Die gespeicherten Photonenereignisse haben immer vergleichbare Energie. Damit wird die Abschätzung der Strahldichte einfacher und selbst bei wenigen Photonen erzielt man eine bessere Qualität, als würde man auch die Energie der Photonen je Ereignis abnehmen 5.1. DIE SPUR DER PHOTONEN 87 lassen und schließlich viel Rechenleistung in das Verfolgen von energetisch geringwertigen Photonen verschwenden. Würde man nämlich ein Photon beim Auftreffen auf eine Fläche beispielsweise in ein diffuses und ein spekulares Photon aufspalten, wobei die Energie jeweils in gleicher Weise aufgespalten wird, würde man für jedes Photon einen binären Baum erzeugen, dessen Einzelereignisse in jeder Stufe entsprechende Anteile der Energie verlieren würden. Nachteil von Russischem Roulette: Allerdings wird über den Wahrscheinlichkeitsansatz eine Varianz in die Lösung eingebracht, da zur Skalierung der Photonenenergie anstelle von exakten Werten für Reflexion und Transmission eine Wahrscheinlichkeit eingesetzt wird, die erst bei großer Anzahl von Ereignissen gegen den korrekten Wert konvergiert. 5.1.3 Speichern von Photonen Das Auftreffen eines Photons auf eine diffuse Oberfläche wird als Photonenereignis oder als Spur des Photons bezeichnet. Diese Photonen, oder besser: Photonenereignisse, werden in einer sogenannten Photon Map gespeichert. Photon Maps zeichnen sich also NUR an DIFFUSEN Oberflächen ab, nicht aber an spiegelnden Flächen, denn die Wahrscheinlichkeit dafür, dass ein Photon von einer spiegelnden Fläche direkt durch ein Pixel den Betrachter erreicht, ist identisch null. Bemerkung 5.3 Um korrekte spiegelnde Reflexion zu erzielen, verfolgt man einen Strahl vom Pixel in die Spiegelrichtung (Backward Raytracing). Photon Mapping spielt hier praktisch keine Rolle. Die Wechselwirkung eines Photons mit einer diffusen Oberfläche wird in einer globalen Datenstruktur, der Photon Map gespeichert. Für das emittierte Photon können mehrfache Ereignisse entlang eines Pfades gespeichert werden. Auch Absorption an einer diffusen Oberfläche wird aufgezeichnet. Die Anzahl der Photonen in einer Photon Map bezieht sich auf die Anzahl sämtlicher solcher Ereignisse. Definition 5.2 Eine Photon Map ist eine globale Datenstruktur, die die Position, die eingestrahlte Photonenenergie und die einfallende Richtung einer Wechselwirkung mit einer diffusen Oberfläche speichert. Zudem ergänzt man häufig eine Flag zum Sortieren innerhalb eines kd-trees. Die Struktur einer Photon Map hat folgende Gestalt: struct photon{ float x, y, z; // Position char p[4]; // Power packed in Ward’s RGB-format char phi, theta; // compressend incident direction short flag; // used in kd-tree } 88 KAPITEL 5. PHOTON MAPPING Abbildung 5.3. Photonenpfade: (a) LDDD mit anschließender Absorption, (b) LSR DR DR und Verlassen der Box, (c) LST ST D mit anschließender Absorption. Dabei sind die Raumwinkel φ und θ jeweils in die Länge eines char gepackt. phi = 255 * (atan2(dx, dy) + PI) / 2 * PI; theta = 255 * acos(dx) / PI; Man unterscheidet aus Effizienzgründen drei verschiedene Photon Maps, die in abkürzender Schreibweise die folgenden Ereignisse verzeichnen: • Kaustische Photon Map: LS + D • Globale Photon Map: L{S|D|V }∗ D • Volumenbezogene Photon Map: L{S|D|V }+ V Die Schreibweise zählt dabei jeweils die Art und Häufigkeit des Ereignisses auf, das in der jeweiligen Photon Map gespeichert ist. Dabei ist L = Emission von einer Lichtquelle S = Spiegelnde Reflexion oder Transmission D = Diffuse Reflexion oder Transmission V = Streuung an einem Volumenelement 5.2. PHOTONEN IM RENDERING PASS 89 {x|y|z} eines der Ereignisse x+ mindestens ein x oder mehrfache Wiederholung von x x∗ kein x oder mehrfache Wiederholung von x. In der kaustischen Photon Map sind gezielt Photonen in die Richtung von spiegelnden Objekten verfolgt worden, um das Phänomen der Lichtbündelung möglichst präzise wiederzugeben. Die globale Photon Map streut die Photonen völlig zufällig in alle Raumrichtungen und würde die Lichtbündelung nur unzureichend oder erst bei sehr hoher Anzahl von Photonen abbilden können. Streuung an Volumenelementen ist sehr aufwändig und wird nur in den wenigsten Fällen in die Strahlungsabschätzung im Rendering Pass eingehen. Abbildung 5.4. Links: Darstellung des Raums mit farbigen Wänden und einer Kugel aus Chrom, einer aus Glas mit Raytracing ohne Auswertung der Photon Map, rechts: Darstellung der Photonenereignisse als entsprechende farbige Punkte. Man erkennt in der Photon Map sehr gut die Kaustik als Bündelung weißer Photonenereignise unter der Glaskugel. Außerdem sind die Ereignisse an der Decke und in den Schatten der Kugeln je nach Nähe zu einer der farbigen Wände unterschiedlich gefärbt. Spiegelnde Objekte verzeichnen keine Photonenereignisse, daher wurden sie hier schwarz dargestellt. Wie sich die Photon Map beim Rendern auswirkt, zeigt Abb. 5.5. Hiermit ist der Photon Tracing Pass abgeschlossen, die Photon Maps sind vorbereitet und der zweite Schritt, das Rendern mithilfe der Photon Maps beginnt. 5.2 Photonen im Rendering Pass Die Idee im Rendering Pass besteht darin, die Strahlung unter Berücksichtigung von jeweils n nächsten Photonen zum Punkt x abzuschätzen. 90 KAPITEL 5. PHOTON MAPPING Abbildung 5.5. Bezieht man die globale Photon Map und die kaustische Photon Map in die Berechnungen des Raytracing ein, ist sowohl die Decke beleuchtet, die Schatten unterschiedlich farbig als auch ein durch Kaustik hervorgerufenes Glanzlicht unter der Glaskugel zu sehen. Der helle Punkt an der blauen Wand resultiert aus der Spiegelung der Kaustik an der Glaskugel und dem Transport dieses Lichtpunktes durch die Photonen der kaustischen Photon Map durch die Glaskugel auf die Wand. 5.2.1 Abschätzung der Strahlung an einer Oberfläche Die Photon Map stellt eine Repräsentation des eingestrahlten Energieflusses dar. Die Formel für reflektierte Strahlung Z Lr (x, ω) = fr (x, ω 0 , ω)Li (x, ω 0 )|Nx · ω 0 |dω 0 Ωx berechnet die Abstrahlung in einem Punkt x und in eine Raumrichtung ω aus dem Integral über die Hemisphäre Ωx aller einstrahlenden Raumrichtungen um x. Der Ausdruck unter dem Integral ergibt sich aus der einstrahlenden Energie Li je festem Raumwinkel ω 0 , die von der BRDF fr umgelenkt und mit dem Einstrahlwinkel |Nx · ω 0 | gewichtet wird. Mit der Beziehung zwischen der Einstrahlung Li und dem hereinkommenden Photonenfluss Li (x, ω 0 ) = erhält man d2 Φi (x, ω 0 ) cos θi dωi0 dAi 5.2. PHOTONEN IM RENDERING PASS 91 Z fr (x, ω 0 , ω) Lr (x, ω) = Ωx d2 Φi (x, ω 0 ) dAi und daraus schätzt man jetzt die reflektierte Strahlung mit den n nächsten Photonen zum Punkt x ab. Jedes dieser Photonen hat dabei die Energie ∆Φp (ωp ) und es wird angenommen, dass es die Fläche in x trifft. Dazu dehnt man eine Kugel um x solange aus, bis sie n Photonen enthält. Lr (x, ω) ≈ n X fr (x, ωp , ω) p=1 ∆Φp (x, ωp ) ∆A Abbildung 5.6. Die nächsten n Photonenereignisse in der Nähe des Punktes x gehen in die Abschätzung ein. Bemerkung 5.4 Unter der Annahme, dass Oberflächen lokal eben sind, kann man sich auf die Projektion der Kugel in die Ebene, also einen Kreis beschränken. Damit ist ∆A = πr2 und r der Radius der Kugel. Daher gilt verkürzt: n 1 X fr (x, ωp , ω)∆Φp (x, ωp ) Lr (x, ω) ≈ 2 πr p=1 Mögliche Fehlerquellen oder die Beeinträchtigung der Genauigkeit hängen von (a) der Gesamtanzahl der Photonen in der Photon Map oder von (b) der Anzahl n der Photonen ab, die in die Abschätzung einbezogen werden. 92 KAPITEL 5. PHOTON MAPPING Zudem ist die Annahme, dass Oberflächen lokal eben sind, in Ecken und an scharfen Kanten einfach falsch. Hier werden Photonenereignisse an Wänden für die Berechnung des Bodens einbezogen und umgekehrt, was zu fehlerhaft weichen Kanten und Farbverläufen führt. Eine Abhilfe für all diese Fehlerquellen besteht über das Gesetz der großen Zahl: Je mehr Photonen in die Abschätzung einbezogen werden und je mehr Photonen in der Photon Map vorhanden sind, um so genauer ist das Ergebnis der Näherungsformel. Im Limes gilt sogar α bN c 1 X fr (x, ωp , ω)∆Φp (x, ωp ) = Lr (x, ω), lim N →∞ πr 2 p=1 α ∈]0, 1[ mit der Gesamtanzahl N Photonen in der Photon Map. Im Beweis geht ein, dass x lokal eine zweidimensionale Umgebung hat und die BRDF keine Diracsche Deltafunktion ist (das schließt den perfekten Spiegel aus). Die verschiedenen Grade von unendlich werden über N α kontrolliert, womit garantiert wird, dass die Gesamtanzahl der Photonen der Photon Map schneller gegen unendlich geht, als die Anzahl der in die Abschätzung einbezogenen. Insgesamt folgert man, dass man hinreichend gute Ergebnisse erzielen kann, wenn man nur genügend Photonen benutzt. Bemerkung 5.5 Vergleicht man die Fehlerquellen mit denen aus der Radiosityberechnung (siehe voriges Kapitel), so fällt auf, dass es in finite Elementmethoden komplizierter ist, hinreichende Genauigkeit zu erzielen. Der Fehler hängt dann nämlich (1) von der Auflösung des Gitters, (2) von der Auflösung der gerichteten Strahlungsenergie und (3) von der Genauigkeit der Simulationsgleichungen ab. Bemerkung 5.6 Anstelle einer Kugel um x kann man auch ein Ellipsoid oder eine Box oder eine Scheibe nehmen, um die Photonen für die Abschätzung zu finden. Dadurch kann man zum einen den Suchalgorithmus beschleunigen, zum anderen erzielt man bessere Ergebnisse in Ecken und Kanten. Allerdings muss ∆A an die neue Geometrie angepasst werden und man verliert die Vorteile der Kugelgeometrie, nämlich die einfache Distanzbestimmung und die einfache Projektion. 5.2.2 Filter für die Abschätzung Wenn die Anzahl der Photonen in der Photon Map zu niedrig ist, wird die Abschätzung an den Kanten verschwommen. Das ist durchaus manchmal wünschenswert, da es weniger sterile Computerbilder generiert, aber bei Kaustiken mit scharfen Abgrenzungen ist es unerwünscht. Eine Abhilfe besteht im Einsatz von Filtern, um näher am Auswertungspunkt x liegende Photonen stärker zu wichten. Da Photonen auf Oberflächen registriert werden, benötigt man 2D-Filter, wie sie aus der Bildverarbeitung bekannt sind. 5.2. PHOTONEN IM RENDERING PASS 93 Beim Cone-Filter wird jedes Photon in der Abschätzung mit einem Gewicht wpc = 1 − dp kr multipliziert, wobei dp die Distanz zwischen dem Punkt x und dem Photonenereignis p ist. Der Parameter k ≥ 1 stellt eine charakteristische Filterkonstante und r eine maximale Entfernung dar. Aus 2 im Nenner der Abschätzung: der 2D-Verteilung ergibt sich ein Normalisierungsfaktor 1 − 3k Pn Lr (x, ω) ≈ p=1 fr (x, ωp , ω)∆Φp (x, ωp )wpc (1 − 2 )πr2 3k Die Wichtungsfunktion wpg des Gauß-Filters schreibt sich mit den gleichen Termen aber etwas komplizierter, nämlich wpg = α 1 − −β d2 p 2r 2 1−e , 1 − e−β wobei die Parameter α, β beispielsweise die Werte α = 0.918 und β = 1.953 annehmen können. Dieser Filter ist bereits normalisiert und ergibt die Abschätzung Lr (x, ω) ≈ n X fr (x, ωp , ω)∆Φp (x, ωp )wpg . p=1 Der Variationsansatz (Differential checking) hat sich speziell bei Kaustiken bewährt. Er beruht auf der Beobachtung, dass sich das Monotonieverhalten der Helligkeit je nach Ort x nahe einer Kante (der Kaustik) ändert, wenn man den Radius vergrößert und damit die Anzahl der Photonen erhöht, die in die Abschätzung einbezogen werden: x außerhalb der Kaustik → x innerhalb der Kaustik → monoton wachsend monoton fallend Der Grund liegt für einen Punkt außerhalb der Kaustik in einer unproportional erhöhten Anzahl Photonen beim Eintritt des Radius in den Bereich der Kaustik. Umgekehrt wird für einen Punkt innerhalb der Kaustik die Anzahl der Photonen bei einem Austritt des Radius aus dem Bereich der Kaustik unproportional erniedrigt. 94 KAPITEL 5. PHOTON MAPPING Abbildung 5.7. Das bekannte Cognacglas von Henrik Wann Jensen besteht aus 12000 Dreiecken, die kaustische Photon Map besteht aus 200000 Photonen und 40 Photonen wurden in der Abschätzung verwendet. Auf Basis dieser Beobachtung bricht man das Vergrößern des Radius (= Einbeziehung weiterer Photonen in die Abschätzung) ab und nimmt lieber erhöhtes Rauschen im Grenzbereich der Kanten/Kaustik in Kauf. 5.2.3 Strahlungsabschätzung im Volumenfall Nebel oder Rauch brechen das Licht je nach Dichte in ganz unterschiedlicher Weise. Hierdurch wird erst der Lichtkegel auch im Raum sichtbar, der sich sonst nur an einer 2D-Oberfläche zeigt. Der Qualm einer Zigarette in einem Spotlight oder Bodennebel im Autoscheinwerfer benötigen daher 3D Berechnungen mit sogenannten Participating media. Dazu muss zunächst die Gleichung für die Strahlungsabschätzung abgeändert werden. 5.2. PHOTONEN IM RENDERING PASS 95 Abbildung 5.8. Diese Berechnung der Cornell Box mit Nebel benötigte 100000 Photonen in der globalen Photon Map, 150000 Photonen in der Volumenmap und 44 Minuten für den Renderprozess. Z Lins (x, ω) = f (x, ω 0 , ω)L(x, ω 0 )dω 0 ZΩ d2 Φ(x, ω 0 ) dω 0 f (x, ω 0 , ω) 0 dV σ (x) dω s Ω Z d2 Φ(x, ω 0 ) 1 f (x, ω 0 , ω) = σs (x) Ω dV n ∆Φp (x, ωp0 ) 1 X ≈ f (x, ωp0 , ω) 4 σs (x) p=1 πr3 3 = Dabei bezeichnet Lins (x, ω) die in die Umgebung gestreute (in-scattered) Abstrahlung und σs (x) den Streukoeffizienten, der anstelle des Produkts aus Einfallswinkels und abstrahlender Fläche im 2D-Oberflächenfall in die Gleichung eingeht. Der Rechenaufwand, der beim Rendern mit einer solchen Volumenabschätzung nötig wird, ist extrem groß. Daher versucht man ihn nach Möglichkeit zu vermeiden und nur für spezielle Effekte einzusetzen. 5.2.4 Auffinden der n nächsten Photonen Um eine Photon Map effizient auszuwerten, sind effektive Strategien nötig: 96 KAPITEL 5. PHOTON MAPPING • Durchsuchen von kd-trees (k-dimensionale Bäume) • Balancieren von kd-trees über Median (= Zentralwert) Ansatz • max-heap (oder priority queue) Ansatz: Das am weitesten entfernte Photon wird am ehesten wieder herausgeschmissen, wenn der max-heap erreicht ist. Bemerkung 5.7 Es empfiehlt sich hierbei immer mit quadrierten Distanzen zu rechnen, das erspart teures Wurzelziehen. Außerdem kann man den maximal nötigen Suchradius nach oben abschätzen. Wenn man sich einen Schwellwert Lt für die Abstrahlung vorgibt, erhält man 1 rm = π r n Pmax Lt für den ebenen Fall und r rm = 3 3 n Pmax . 16 π 2 σ Lt im Fall isotrop streuender Volumenelemente. 5.2.5 Auswertung der Strahlungsabschätzung: Rendering Das Photon Mapping ist eine Erweiterung des Raytracing. Daher wird für das eigentliche Rendern ein verteiltes Raytracing (Distributed Raytracing) vorgenommen. Die Pixelstrahlung ist dabei das arithmetische Mittel über verschiedene Einzelabschätzungen. Bemerkung 5.8 Die Photon Map ist unabhängig von der Betrachterposition! Eine einmal berechnete Photon Map kann für das Rendern einer Szene aus (a) jeder möglichen Blickrichtung hergenommen werden und kann (b) für verschiedenste Rendertechniken benutzt werden, z.B. für die Berechnung von Radiositywerten in Gitterpunkten. Allgemein gilt, dass für jedes Pixel vom Auge des Betrachters ein Strahl durch das Pixel in die Szene verfolgt wird (sogenanntes backward raytracing). Die abstrahlende Energie wird hier mit dem Index o für outgoing bezeichnet. Dann ergibt sich Lo (x, ω) = Le (x, ω) + Lr (x, ω) 5.2. PHOTONEN IM RENDERING PASS 97 die von einem Pixel ausgehende Strahlung als Summe der emittierten Le (x, ω) und der reflektierten Lr (x, ω) Strahlung. Die reflektierte Strahlung kann jetzt nach der bewährten Formel als Integral aus der einstrahlenden Energie berechnet werden: Z Lr (x, ω) = fr (x, ω 0 , ω)Li (x, ω 0 )|Nx · ω 0 |dω 0 Ωx Die BRDF fr wird dabei in einen spekularen und einen diffusen Anteil zerlegt. fr (x, ω 0 , ω) = fr,s (x, ω 0 , ω) + fr,d (x, ω 0 , ω) Auch die Einstrahlung Li = Li,l +Li,c +Li,d wird in drei Terme aufgespalten, die direkte Beleuchtung Li,l (x, ω) durch eine Lichtquelle, die kaustische Beleuchtung Li,c (x, ω), also indirekte Beleuchtung durch spiegelnde Reflexion, und die indirekte Beleuchtung Li,d (x, ω), bei der wenigstens einmal diffus reflektierte Photonenereignisse berücksichtigt werden. In der Kombination ergeben sich vier Terme: Z fr (x, ω 0 , ω)Li (x, ω 0 )cos θi dω 0 Lr (x, ω) = Ωx Z fr (x, ω 0 , ω)Li,l (x, ω 0 )cos θi dω 0 = (I) Ωx Z + fr,s (x, ω 0 , ω)(Li,c (x, ω 0 ) + Li,d (x, ω 0 ))cos θi dω 0 (II) Ωx Z + fr,d (x, ω 0 , ω)Li,c (x, ω 0 )cos θi dω 0 (III) Ωx Z + fr,d (x, ω 0 , ω)Li,d (x, ω 0 )cos θi dω 0 (IV) Ωx Der erste Term (I) besteht aus der direkten Illumination. Hier geht der direkte Anteil der Lichtquelle ein. Das sogenannte Raycasting, das nur einen einfachen Strahl von der Lichtquelle auf den betrachteten Punkt wirft, bestimmt die Lokalfarbe an dieser Stelle. Verdeckt ein anderes Objekt diese Lichtquelle aus Sicht dieses Punktes, wird dieser Punkt nicht direkt von dieser Lichtquelle erreicht und der Term entfällt. Das motiviert das Aussenden sogenannter Schattenstrahlen Shadowcasting von einem Punkt in Richtung sämtlicher Lichtquellen. Treffen sie auf ein Objekt, das nicht die Lichtquelle ist, erhalten diese Punkte kein Licht von dieser Quelle. Diesen Ansatz kann man weiter verfolgen und Shadowphotons berechnen. Der zweite Term (II) stellt das spekulare oder Glanzlicht dar. Hier wird das Photon Mapping NICHT eingesetzt!!! Dieses Integral wird mit den Standard Monte Carlo Methoden des Raytracing berechnet. 98 KAPITEL 5. PHOTON MAPPING Abbildung 5.9. Skizzen zu den Strahlen des Raytracing und der Auswertung der Photon Map an diesen Stellen, links die direkte Beleuchtung/Verdeckung (I), rechts die spiegelnde Reflexion OHNE Photon Mapping (II). Die Funktion fr,s erzeugt dabei einen engen Peak in Spiegelrichtung. Der dritte Term (III) betrifft das kaustische Integral. Wenn die Anzahl der Photonen in der Caustic map hoch ist, erzielt man hiermit eine gute Qualität der Abschätzung. Der vierte Term (IV) berechnet sich aus der vielfach diffusen Reflexion. Eine ungefähre Abschätzung erfolgt mit der globalen Photon Map, eine genauere Abschätzung bezieht Monte Carlo Methoden des Raytracing ein. Abbildung 5.10. Links die Skizze für das kaustische Integral (III), rechts das globale diffuse Photon Mapping (IV). 5.3 Übungsaufgaben Aufgabe 5.1 Russisches Roulette Berechnen Sie für eine einfache Szene mit einer Glaskugel und einer Lichtquelle in einer Raumecke (z.B. die Cornell Box) eine (globale) Photon Map, wobei Sie einzig die einzelnen Photonenereignisse mit ihren Farbwerten als Punkte in einem OpenGL Programm darstellen. 5.3. ÜBUNGSAUFGABEN 99 Aufgabe 5.2 BRDF Eine Bidirectional Reflectance Distribution Function (BRDF) ist die Funktion fr (θi , φi ; θr , φr ), die sich aus dem Quotienten der reflektierten differentiellen Strahldichte dLr in Betrachterrichtung und der differentiellen Bestrahlungsstärke dEi aus der Lichtrichtung ergibt. Sie kann mit Gonioreflektometern gemessen oder aufgrund ideller Annahmen für ein Material modelliert werden. (a) Ein Lambert-Strahler ist das Modell für einen diffus reflektierenden Körper und zeichnet sich durch folgende Eigenschaften aus: 1. Der Körper absorbiert kein Licht. Das auf den Körper einfallende Licht wird komplett reflektiert. 2. Der Körper erscheint von allen Betrachtungsrichtungen aus gleich hell. Leiten Sie daraus die BRDF eines Lambert-Strahlers her. (b) Das Ward Modell von 1992 sieht für isotrope spiegelnde Reflexion die BRDF tan2 δ − e α2 1 fiso (θi , φi ; θr , φr ) = √ cosθi cosθr 4πα2 vor. Anders als das Phong-Modell ist es physikalisch gültig aber trotzdem einfach. Dabei ist α der Rauhigkeitskoeffizient der isotropen Fläche, δ der Winkel zwischen der Normale N und dem HalfwayVektor H. Leiten Sie daraus eine Formel für faniso (θi , φi ; θr , φr ) mit Rauhigkeitskoeffizienten αx und αy ab. (c) Die Faktorisierung einer BRDF lautet fiso (θi , φi ; θr , φr ) = n X pj (θi , φi )qj (θr , φr ) j=1 Welche Vorteile kann man daraus ziehen? Hinweis: Denken Sie an GPU-Programmierung und Environment-Mapping. 100 KAPITEL 5. PHOTON MAPPING Aufgabe 5.3 Maximalradius Bestimmen Sie für die Rendergleichung mit Photon Mapping einen maximalen Radius rm . Schätzen Sie dazu die Formel für Lr (x, ω) mit der BRDF eines perfekt diffusen Strahlers und bekannten Maximalwerten (wie maximaler Photonenenergie) sowie einem vorgegebenen Schwellwert von Lt (x, ω) ab. (a) Wie lautet die Formel für rm ? (b) Es sei σ(x) das Streuereignis in einem beteiligten Medium (participating medium). Wie lautet eine entsprechende Formel für rm bei Streuung an einem Volumen? Kapitel 6 Nichtphotorealistisches Rendering Nichtphotorealistisches Rendern (NPR) ist inspiriert durch Stilrichtungen der bildenden Kunst, der technischen Zeichnung und dem Comic und Zeichentrickfilm. Begonnen hat diese Entwicklung Ende der achtziger Jahre, als Photorealismus immer mehr ausgereizt war. Ein bekannter erster Kurzfilm ist Technological Threat von 1988, die erster Veröffentlichung zum Thema war Paint by Numbers: Abstract Image Representation, SIGGRAPH 90. Langfilme griffen die Technik erst kürzlich auf, so in Sin City, einer Comic-Verfilmung des Autors Frank Miller (Regie: Robert Rodriguez, 2005) und in A Scanner Darkly von Richard Linklater (2006) nach dem gleichnamigen Roman von Philip K. Dick. Der Begriff Nichtphotorealismus ist einer Veröffentlichung von Salesin, Winkenbach, 1994, entnommen. Abbildung 6.1. Phong Shading versus Toon Shading verdeutlicht die unterschiedliche Zielsetzung. 101 102 6.1 KAPITEL 6. NICHTPHOTOREALISTISCHES RENDERING Zweidimensionale NPR-Techniken, Bildbearbeitung Input ist ein Bild oder eine Sequenz von Bildern, Output ist ein stilisiertes Bild oder ein Film. Filterverfahren auf der Basis von Rasterinformation werden in Bildbearbeitungsprogrammen wie gimp oder Photoshop geführt. Diese sogenannten Artistic Filter versuchen Farbstiftzeichnungen, Frescotechnik, Pastellbilder oder Wasserfarben zu imitieren. Andere Bildbearbeitungsprogamme wie Impressionist versuchen den Entstehungsprozess eines Bildes zu imitieren, indem sie zunächst den Bildträger (Untergrund) simulieren und ein mit der Maus (oder anderen Eingabegeräten) zu führendes Werkzeug zur Auswahl stellen. Nass-in-Nass Techniken bei Aquarellzeichnungen benötigen jetzt Simulationen des Trocknungsverhaltens und der Diffusion von Farbpigmenten in verschiedenen Schichten (im feuchten Papier oder im Wasserfilm oder an der Wasseroberfläche; zur korrekten Behandlung muss sogar die Oberflächenspannung berücksichtigt werden). Variablen für die Bildbearbeitung sind Strichstärke, -länge und -richtung (Brush strokes), die Anzahl der Farbtöne, die Größe und Gestalt einzelner Flächenelemente sowie die Art der Begrenzung der Flächen. Abbildung 6.2. Die goldene Kugel des NGG-Logos links im Original, dann als Papierschnitt, Untermalung auf Leinwand, Pastell auf Sandstein und Aquarell auf rauhem Papier. 6.2 Dreidimensionale NPR-Techniken Der Input hier ist ein 3D-Modell, das computergeneriert, aber auch aus vermaschten Laserscans oder stereographisch erfassten Bilddaten erzeugt sein kann. Als mögliches Zwischenergebnis wird ein in seiner 3D-Geometrie verändertes Modell gespeichert. Diese Veränderungen sind entweder • betrachterabhängig und durch die Projektionen bedingte Deformationen, • überdimensionierte Detaildarstellungen oder • angeschnittene Objekte. Sie richten sich nach der Sichtbarkeit wichtiger Details oder dem Wiedererkennungseffekt einer Abstraktion. Auf dieses Zwischenergebnis wirken nun veränderte Lichtmodelle, die mit den Informationen aus dem Tiefenspeicher oder dem Normalenfeld Silhouetten und Krümmungen der Oberfläche interpretieren können. Der Output ist wieder ein stilisiertes Bild oder ein Film. 6.3. KONTURLINIEN 103 Anwendungen finden diese Techniken in Konzeptzeichnungen, z.B. für architektonische Entwürfe, in Bedienungsanleitungen und technischen Zeichnungen, medizinischen Handbüchern oder in Zeichentrickfilmen und Computerspielen. Häufig wird das 3D-Modell unverändert übernommen und nur beim Rendern auf verfremdende Verfahren zurückgegriffen. 6.3 Konturlinien Die Umrisslinie ist die einfachste Form der Zeichnung. Diese kann man aus der einfachen Umrandung gewinnen, die als Schattenriss wirklich nur eine geschlossene Linie ergibt. Wie aber kann man mathematisch eine Silhouette definieren, der ein 3D-Modell zugrunde liegt? Definition 6.1 Die Silhouette S eines 3D-Objekts ist die Vereinigung aller Punkte xi auf der Oberfläche O, deren Normale ni senkrecht zum Sichtstrahl liegt und deren Krümmung echt positiv (konvex) ist. S = {xi ∈ O | Ni · (xi − V ) = 0} Abbildung 6.3. Eine Silhouette wird von Punkten xi gebildet, die auf der Oberfläche eines Objekts tangential zur Blickrichtung liegen. Bemerkung 6.1 In dieser Definition werden Falten nur erfasst, wenn sie lokal echt konvex sind. Die Definition gilt nur für glatte, unberandete Objekte. Ränder von zweidimensionalen, endlichen Mannigfaltigkeiten werden nicht erfasst, z.B. eine Kreisscheibe hätte keinen Rand. 6.3.1 Silhouetten mit OpenGL Die Idee hinter diesem einfachen Algorithmus besteht darin, alle blickabgewandten Polygone als dickes Drahtgittermodell, alle zugewandten Polygone ausgefüllt mit beliebigen Shadern zu zeichnen. 104 KAPITEL 6. NICHTPHOTOREALISTISCHES RENDERING Dieses Verfahren eignet sich gut für sogenannte Polygonsuppe, da es recht robust mit einer großen Anzahl von Dreiecken zurechtkommt. glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glPolygonMode(GL_FRONT, GL_FILL); glDepthFunc(GL_LESS); cgGLBindProgram(cg_vertex_program); // cgGLEnableProfile(cg_vertex_profile); // cgGLBindProgram(cg_fragment_program); // cgGLEnableProfile(cg_fragment_profile);// {Zeichne 3D-Objekt} cgGLDisableProfile(cg_fragment_profile); cgGLDisableProfile(cg_vertex_profile); Einbinden eines Vertexshaders Einbinden eines Fragmentshaders glLineWidth(5.0); glPolygonMode(GL_BACK, GL_LINE); glDepthFunc(GL_LEQUAL); glCullFace(GL_FRONT); glColor3f(0.0, 0.0, 0.0); {Zeichne 3D-Objekt} glPointSize(5.0); glPolygonMode(GL_BACK, GL_POINT); {Zeichne 3D-Objekt} Bemerkung 6.2 (Linienstärke) Die Linienstärke wird bei einer Rastersteigung von −1 < m ≤ 1 senkrecht zum linienrelevanten Pixel bemessen, für die restlichen Steigungen wird sie waagerecht bestimmt. Daher variiert die Stärke der Silhouette mit der Steigung. Das Einfügen von Punkten in gleicher Punktgröße vermeidet hässliche einspringende Ecken beim Zusammentreffen von Linien größerer Stärke. Wenn die Punkte und Linien antialiased gezeichnet werden, wird ebenfalls der störende Effekt beim Abknicken der Linien vermieden. 6.3.2 Exaktes Verfahren für Dreiecksgitter Ein exaktes Verfahren für Dreiecksgitter ermittelt für jeden Knoten den Wert di (xi ) = ni · (xi − V ) kni k kxi − V k 6.3. KONTURLINIEN 105 und betrachtet dann das Vorzeichen 1 sgn (di ) = 0 −1 falls di > 0 falls di = 0 . falls di < 0 Der Fall di = 0 kommt dabei generisch nicht vor. Aber unabhängig davon genügt es, die Dreiecke P zu finden, für die | i sgn (di )| ≤ 2 ist. Das sind genau die Dreiecke mit einem Vorzeichenwechsel. Abbildung 6.4. Rechts ein Dreiecksgitter. Die darin verlaufende Silhouette führt durch solche Dreiecke, deren Eckpunkte einen Vorzeichenwechsel für d aufweisen. Für reguläre Dreiecksgitter, deren Eckpunkte also immer mit den Eckpunkten anderer Dreiecke zusammen treffen, ergibt sich eine Bandstruktur in Form eines Trianglestrips. Für alle Kanten mit einen Vorzeichenwechsel findet man den Knoten x̃ auf der Silhouette durch lineare Interpolation mit den Werten d(xj ) = dj und d(xk ) = dk der Eckpunkte. Dann ist d(x̃) = 0. x̃1 = |dj | |dk | xj + xk |dj | + |dk | |dj | + |dk | x̃2 = |dk | |di | xi + xk |di | + |dk | |di | + |dk | Die Silhouette ist jetzt die Verbindungslinie zwischen x̃1 und x̃2 . Da benachbarte Dreiecke gemeinsame Kanten haben, setzt sich die Silhouette durch alle Dreiecke des Strips fort. 106 6.3.3 KAPITEL 6. NICHTPHOTOREALISTISCHES RENDERING Bildbasierter Konturalgorithmus Die Idee eines bildbasierten Konturalgorithmus ist eine Kantendetektion an Rasterbildern. Die relevanten Informationen für Konturen sind (a) im Tiefenspeicher und (b) im Normalenfeld enthalten. Abbildung 6.5. Kantenextraktion aus einem Tiefenbild und einem Bild mit in Farbwerte umgesetzten Normalenfeld. Algorithmus 1. Schritt: Erzeuge ein Schwarz-Weißbild des Tiefenspeichers wie in Abb. 6.5 oben links (z.B. mit glReadPixels(GL DEPTH COMPONENT);) 2. Schritt: Erzeuge ein Bild des Normalenfelds als Farbbild wie in Abb. 6.5 unten links, bei dem die (x, y, z)-Werte betragsmäßig in (R, G, B)-Werte übersetzt werden. 3. Schritt: Bestimme die Kanten in beiden Bildern. 4. Schritt: Vereinige beide Kantenbilder. Im ersten Schritt wird die Silhouette komplett erfasst, wenn sich das Objekt von seinem Hintergrund genügend weit abhebt. Das gilt allerdings nicht für z.B. einen Bilderrahmen an einer Wand. Hierfür braucht man den Richtungswechsel im Normalenfeld. Bemerkung 6.3 Dieser Algorithmus zeichnet mehr als nur die reine Silhouette, da auch Sprünge im Normalenfeld registriert werden. Sie sind hilfreich für die Interpretation eines 3D-Objekts. Da sie betrachterunabhängig sind, kann man sie auch direkt dem Objekt zuordnen, statt sie aus der Kantendetektion eines Bildes zu gewinnen. 6.3. KONTURLINIEN 107 Abbildung 6.6. Das vollständige Kantenbild entsteht aus einer Kombination der Kantenbilder aus Tiefenwert und Normalenfeld, Bilder aus der Dissertation von Aaron Hertzmann. Bemerkung 6.4 Durch die Kombination beider Kantenbilder werden die jeweiligen Schwächen ausgeglichen. Bemerkung 6.5 Im allgemeinen Fall ist eine Kante eine hinreichend starke Schwankung der Intensität benachbarter Pixel, die NICHT notwendig mit den geometrischen Eigenschaften der dargestellten Objekte korreliert, sondern eine • Textur, • Schattenkante oder • scharfe Begrenzung von Highlights (bei stark spiegelnden Objekten) sein kann. Abhilfe kann in der reinen Bildverarbeitung nur durch weitere Bildinformation (z.B. Stereobilder und daraus geschätzte Tiefen oder Normaleninformation) gewonnen werden. Ein eindimensionales Bild f (x) mit exakt einer Kante bei x = 0 wird mit der Errorfunktion modelliert: Z erf(x) = 0 Damit ist x 2 e−t dt 108 KAPITEL 6. NICHTPHOTOREALISTISCHES RENDERING Ir − Il f (x) = 2 x + 1 + Il erf √ 2σ mit Intensität Ir am rechten und Il am linken Rand. Parameter σ ist der Unschärfeparameter der Kante. Mit diesem Idealfall werden nun einzelne Bildzeilen (oder -spalten) verglichen. Dabei wählt man einen Schwellwert und einen Unschärfebereich, um die tatsächliche Kante auszuzeichnen. Um Rauschen zu entfernen, werden Bilder vorgeglättet. Bemerkung 6.6 Tatsächlich vorhandene geometrische Kanten können unscharf oder gar nicht erscheinen, wenn sie • außerhalb des Tiefenschärfebereichs liegen, • von anderen Objekten verschattet werden oder • überstrahlt mit einem anderen hellen Objekt oder dem Hintergrund verschmelzen. Abbildung 6.7. Kantenextraktion mit dem Sobel-Filter, links das Original, rechts das gefaltete Bild. Ein bis heute gebräuchliches und sehr elaboriertes Verfahren ist die Canny Edge Detection von Canny, Deriche, 1987. Es sucht nach optimalen Glättern und bestimmt Kanten als lokale Maxima im Gradientenfeld. Damit fällt es in die Klasse der differentiellen Kantendetektoren und ist hier ein Verfahren erster Ordnung, da es auf zentralen Differenzen beruht, die letztlich lokale erste Ableitungen darstellen. 1 1 Ix (x, y) = − I(x − 1, y) + 0 · I(x, y) + I(x + 1, y) 2 2 1 1 Iy (x, y) = − I(x, y − 1) + 0 · I(x, y) + I(x, y + 1) 2 2 6.4. NICHTPHOTOREALISTISCHES SHADING 109 Mit entsprechenden Filtermasken schreibt man nun 1 2 Ix = − 12 0 1 2 ∗ I, 0 ∗I Iy = − 12 Andere Filtermasken sind die sogenannten Sobel Kernel. −1 Sx = −2 −1 0 0 0 1 2 , 1 1 2 1 0 0 Sy = 0 −1 −2 −1 Die Terme Ix (x, y) und Iy (x, y) sind dann die Faltung mit den Filtermasken und entsprechen ebenfalls einer Diskretisierung des Grauwertgradienten in Richtung von x bzw. y. Ix (x, y) = I(x, y) ∗ Sx , Iy (x, y) = I(x, y) ∗ Sy q |∇I| = Ix 2 (x, y) + Iy 2 (x, y) Stellt man sich die Faltung als Überlappung zweier Funktionen vor, so erzeugt das Vorzeichen in den Filtermasken ein Über- oder Unterbewerten des linken (unteren) Pixels. Somit wird eine Kante auf Pixellevel entweder früher oder später angeschaltet. ( Edge (x, y) = 1 falls |∇I| ≥ T 0 falls |∇I| < T Eine Kante liegt vor, wenn ein Schwellwert T (Threshold) überschritten wurde. Auch die Richtung des Gradienten θ kann aus diesen Werten abgelesen werden, nämlich θ = arctan IIxy . Für θ = 0 besteht eine senkrechte Kante, die links dunkel, rechts hell begrenzt ist. 6.4 Nichtphotorealistisches Shading Die Vorteile nichtphotorealistischer Darstellungen bestehen in der Einflussnahme auf das resultierende Bild. Damit sind sie in der Lage, Abstraktionen vom realen Detail zu leisten. Das angestrebte 110 KAPITEL 6. NICHTPHOTOREALISTISCHES RENDERING Shading sollte plakativ sein, also nur wenige Abstufungen zulassen. Außerdem empfiehlt sich eine klare Abgrenzung von der meist schwarz gezeichneten Kontur. 6.4.1 Cel-Shading oder Toon-Shading Klare Konturen erfordern eine Abgrenzung des Shading, das man daher Cel-Shading nennt (Cel steht dabei für Contour Enhancing Lines). Seit ungefähr 1999 wird ein an Cartoons (daher Toon-Shading) erprobtes Shading in Animationsfilmen eingesetzt, seit dem Jahr 2000 fand es auch in Computerspielen Verbreitung. Abbildung 6.8. Toon Shading verwendet nur wenige Graustufen, die der Objektfarbe überlagert werden. Ausgangspunkt ist ein konturiertes 3D-Modell. Dann legt man drei bis vier Helligkeitsstufen fest, z.B. weiß, hellgrau und dunkelgrau. Dabei sollte die dunkelste Stufe deutlich von schwarz entfernt bleiben, um sich auch in verschatteten Bereichen immer noch deutlich von der Kontur abzuheben. Die Graustufen werden nun in einer eindimensionalen Textur gespeichert, die dazu dient, den Grauwerten eine (eindimensionale) Ausdehnung zu geben. Über den Winkel (N · L) wird die Schattierung dem Objekt zugeordnet und mit einer Objektfarbe verrechnet. Highlights werden üblicherweise über (H · N )n berechnet und weiß dargestellt, ohne Material- oder Lichtfarbe zu berücksichtigen. Dieses Verfahren ist leicht auf Graphikkarten implementierbar. 6.4.2 Gooch Shading Das nach den Autoren benannte Gooch Shading verwendet einen der Objektfarbe überlagerten kaltzu-warm Farbgradienten, um die Krümmung wiederzugeben (siehe [GGSC98]). Wie für das Toon Shading gilt auch hier, dass der Spekularterm aus dem Blinn-Phong Modell übernommen und aus (H·N )n berechnet wird. Die resultierenden Highlights bekommen eine weiße Farbe, die sich gegen die üblicherweise schwarzen Konturen auch dann gut abhebt, wenn das Highlight an den Rand einer Fläche stößt. 6.4. NICHTPHOTOREALISTISCHES SHADING 111 Abbildung 6.9. Der unvermeidliche Teapot in Gooch Shading. Abbildung 6.10. Ein komplizierteres technisches Objekt links in Phong, rechts in Gooch Shading, Bilder von Amy und Bruce Gooch. Ein begrenzter Luminanzwert wird jetzt zur Darstellung der Krümmung der Oberfläche genutzt. Dazu verfährt man wie folgt: 1. Schritt: Wähle eine Objektfarbe, die wenige weiß/schwarz-Anteile hat. In Formelschreibweise heißt das: Der Schwarzanteil K = min(C, M, Y ) = min(1 − R, 1 − G, 1 − B) = 1 − max(R, G, B) soll minimal sein, aber auch der Weißanteil W = min(R, G, B). 2. Schritt: Lege einen kalt-zu-warm Farbgradienten fest, beispielsweise von Blau zu Gelb. 3. Schritt: Die kalt-zu-warm Rampe wird zur diffusen Farbkomponente addiert. Dabei wird für jede Farbe eine Wichtung vorgenommen, damit die resultierende warme und kalte Objektfarbe nicht ins Weiße überstrahlt. 4. Schritt: Highlights werden über (H · N )n berechnet und weiß eingefärbt. 112 KAPITEL 6. NICHTPHOTOREALISTISCHES RENDERING Abbildung 6.11. Verschieden farbige Kugeln, oben in Phong, unten in Gooch Shading. Man erkennt deutlich sowohl die Objektfarbe als auch die schwarze Silhouette. Bilder von Amy und Bruce Gooch. Damit ergeben sich die folgenden Formeln für das Gooch Shading: kfinal kcool = kblue + α kdiffuse kwarm = kyellow + β kdiffuse 1 + (N · L) 1 + (N · L) = 1− kcool + kwarm 2 2 Darin ist kcool die Objektfarbe im unbeleuchteten Teil, wobei die gewählte Objektfarbe kdiffuse mit α gewichtet und zur kalten Farbe der Rampe addiert wird. Genauso ist kwarm die Objektfarbe im beleuchteten Teil, die aus der Summe einer warmen Farbe und der mit β gewichteten gewählten 1 + (N · L) ∈ [0, 1]. Damit ist kfinal die Objektfarbe kdiffuse entsteht. Da (N · L) ∈ [−1, 1] liegt 2 lineare Interpolation zwischen beiden Extremen der Objektfarbe und wird im diffusen Farbanteil des Beleuchtungsmodells eingesetzt. (Anmerkung: Obige Formel ist die korrigierte lineare Interpolation, die von der (fehlerhaften) Originalveröffentlichung abweicht: dort sind kcool und kwarm vertauscht.) Eine weitere Möglichkeit ist der Einsatz von einer warmen und einer kalten Lichtquelle, die das in Grundfarbe gehaltene Objekt aus zwei verschiedenen Richtungen beleuchtet. Ifinal = ka Ibasic + (N · L1 )(I warm − k1 Ibasic )k2 + (N · L2 )(I cool − k3 Ibasic )k4 Auch hier wird zur Vermeidung von Übersättigung mit geeigneten Parametern k1 , k3 gewichtet. 6.5 Line-Art Rendering Um Handzeichnungen zu imitieren, wird neben der Konturlinie auch die Schattierung aus Linien, Schraffuren erzeugt. Die einfachste Art ist die Texturierung einer Fläche mit einer Schraffur von geeigneter Helligkeit. 6.5. LINE-ART RENDERING 6.5.1 113 Kreuzschraffur Eine bekannte Zeichentechnik des 19. Jahrhunderts, die aus dem Stahlstich herrührt, ist die Kreuzschraffur. Anders als die in der Kaltnadelradierung eingesetzten Kupferplatten ist Stahl ein härteres Material, das viel mehr Abzüge des einzelnen Druckstocks als das weiche Kupfer zulässt. Dafür ist es in der Bearbeitung entsprechend schwieriger, geschwungene Linien entlang einer Krümmung einzusetzen. Man beschränkte sich daher auf Helligkeitsabstufungen aus parallelen Linien in gleichen Abständen, die einander überlagert wurden. Meist sind es fünf Hellligkeitsstufen, nämlich gar keine Schraffur (weiß), eine horizontale, darüber eine vertikale und dann zwei diagonale Schraffuren (siehe Abb. 6.12). Traditionell wird die diagonale Schraffur zunächst von links unten nach rechts oben geführt, gemäß dem Lichteinfall in barocken Handzeichnungen. Die von links oben nach rechts unten geführte Schraffur blockiert das Licht und wird für die dunkelsten Schatten benutzt. Hier sei auf wahrnehmungspsychologische und kulturell bedingte Unterschiede verwiesen, die sich in starkem Maß in der Handzeichnung niederschlagen. Abbildung 6.12. Mit der Kreuzschraffur lassen sich fünf Helligkeitsstufen erstellen. Ganz rechts ist ein Grauwertgradient in Kreuzschraffur dargestellt. Die Kreuzschraffur ist computertechnisch recht einfach umzusetzen, in dem man die vier nötigen Texturen periodisch anlegt und die Objekte (z.B. im Fragmentshader) entsprechend der Intensitäten auf Pixelbasis texturiert. 6.5.2 Krümmungsangepasste Schraffur Die Federzeichnung ist eine der frühesten Handzeichnungen und lässt durch den weichen Federkiel das An- und Abschwellen der Linie in natürlicher Weise zu. Seit der Frührenaissance ist die Zeichnung perfektioniert worden. Martin Schongauer (Oberdeutsche Schule), Albrecht Dürer, Leonardo da Vinci sind die bekanntesten Vertreter, wobei Rembrandt im Barock und Van Gogh für die klassische Moderne nochmal neue Impulse gesetzt haben. Mit dem An- und Abschwellen einer gekrümmten Linie kann zugleich Helligkeitsintensität und Krümmung der Objekte wiedergegeben werden. Um das auch computertechnisch umzusetzen, wird 114 KAPITEL 6. NICHTPHOTOREALISTISCHES RENDERING 3D-Information benötigt, die man aus Stereoaufnahmen, vermaschten Laserscandaten oder computergenerierten Modellen bezieht. Die folgende Technik und die Bilder sind dem Artikel Line-Art Rendering von Rössel und Kobbelt [RK00] entnommen. Die Geometrie wird zunächst mit einem tangentialen Vektorfeld überzogen. Daraus gewinnt man in jedem Punkt die Hauptkrümmungsrichtungen. Die betragsmäßig kleinere Krümmung bestimmt das Rückgrat (backbone) eines Objekts. In Richtung der betragsmäßig größeren Krümmung können nun beliebig viele Linien als Rippen angesetzt werden, um die Gestalt des Objekts wiederzugeben (siehe Abb. 6.13 links). Dadurch werden aber meist zu dichte Schraffuren erzeugt, die hellere Bereiche der Objekte nicht adäquat wiedergeben. Abbildung 6.13. Rückgrat (blau) und Rippen (rot) orientieren sich an den Hauptkrümmungsrichtungen. Für die zweidimensionale Projektion werden nur wenige charakteristische Referenzlinien benötigt. Rechts ist die Interpolation in der 2D-Projektion dargestellt. Es empfielt sich daher, die in einer bestimmten 2D-Projektion relevanten Rippen z.B. aufgrund einer in dieser Projektion deutlichen Krümmungsänderung auszuwählen und die dazwischen zu platzierende Anzahl von Linien abhängig vom zu erzielenden Grauwert zu machen. Die charakteristische Form einer ausgezeichneten (roten) Rippe wird über einen Punkt auf dem Rückgrat b(0), eine Orientierung E0 und eine Folge von Winkeln αi gegeben. Sei eine zweite, benachbarte Rippe an dem Punkt b(1) mit Orientierung F0 und eine Folge von Winkeln βi bekannt. Die dazwischen zu zeichnenden Rippen werden gemäß eines Parameters t ∈ [0, 1] interpoliert, wobei p0 = b(t) ist. Den Punkt p1 findet man nun, indem man die Orienierung G0 linear zwischen E0 und F0 interpoliert. Die Winkel γi sind einfach das arithmetische Mittel aus den Winkeln (1 − t)αi und tβi . Damit ist pk (l) = p0 + G0 ± h P i j=1 k−1 cos γj X Pi sin i=1 j=1 γj bei konstanter Schrittweite h der k-te Punkt auf der l-ten Linie. Wenn man jetzt die Anzahl der Rip- 6.5. LINE-ART RENDERING 115 pen entsprechend der gewünschten Intensität bestimmt, kann man mit obiger Formel alle Punkte der einzufügenden Rippen berechnen. Der Vorzeichenwechsel beruht auf der Annahme von zum Rückgrat symmetrischer Rippen. Dabei entsteht das Problem, dass das Rückgrat selbst gekrümmt ist und unerwünschte Intensitätsschwankungen auftreten, wenn sich bedingt durch die 2D-Projektion die Rippen einseitig (oder beidseitig) stärker häufen (siehe Abb. 6.15, ganz links). Eine Abhilfe schafft die Verwendung von Texturen, die aus einem zentralen schwarzen Band und weißen Rändern besteht (siehe Abb. 6.14). Die Weite w0 der schwarzen Linie wird über den lokalen Grauwert c und eine maximale Breite w gesteuert. w0 = (1 − c)w Damit wird einerseits das An- und Abschwellen der Linie bewirkt, andererseits überlagern die weißen Bänder in Regionen dichter Linien zum Teil andere Linien und erhellen dadurch den Grauwert. Schwierigkeiten entstehen bei zu starkem Überlapp bei ungünstiger Reihenfolge des Zeichnens (siehe Abb. 6.15, zweites Bild von links). Abbildung 6.14. Linientextur mit Schwarz-Weiß-Bändern. Um hier erneut Abhilfe zu schaffen, wird in jedem Helligkeitslevel zunächst mit dem hellsten, weit auseinanderliegenden Linienmuster begonnen, um dann je nach Intensität weitere Linien einzufügen. So entsteht nach und nach eine gleichmäßige Intensität des Grauwerts bei gekrümmter Obefläche (siehe die drei rechten Bilder in Abb, 6.15). Abbildung 6.15. Verschiedene Graustufen mit Überlagerungen von Schwarz-Weiß-Bändern. 116 KAPITEL 6. NICHTPHOTOREALISTISCHES RENDERING Abbildung 6.16. Endergebnis der krümmungsangepassten Schraffur für einen Motorblock. 6.6 Transformationen der Geometrie Um Okklusionen zu vermeiden oder künstliche 2D-Übertreibungen zu ermöglichen, muss die 3DGeometrie eines Objekts verändert werden. Die folgenden Bilder zur blickrichtungsabhängigen Geometrieveränderung sind dem Artikel View-Dependent Geometry von Paul Rademacher [Rad99] entnommen. 6.6.1 Blickpunktsänderung In Comiczeichnungen oder Zeichentrickfilmen ist es zum einfachen Wiedererkennen der Charaktere nötig, dass wesentliche Merkmale prompt erkannt werden. Ein typisches Beispiel sind die Ohren einer Micky Maus. Diese flachen, annähernd kreisrunden Gebilde würden in der Seitenansicht zu antennenartigen Strichen reduziert erscheinen, im Halbprofil würden sie sich teilweise überdecken. Beides beeinträchtigt das schnelle Erkennen der Figur. Computergenerierte 3D-Modelle werden daher für verschiedene Blickrichtungen aus einem Basismodell abgeleitet. Dazu geht man wie folgt vor: 6.6. TRANSFORMATIONEN DER GEOMETRIE 117 1. Schritt: Erstelle Referenzzeichnungen für verschiedene Ansichten. 2. Schritt: Transformiere das Basismodell manuell in diese verschiedenen Ansichten und überlagere es mit den Referenzzeichnungen. 3. Schritt: Deformiere das Basismodell in diese Key Deformationen. Dazu wähle entsprechende Knoten mit einem Skalierungsfaktor (1 − d/r)2 um einen zentralen Knoten aus. Abbildung 6.17. Das 3D-Basismodell der Comicfigur wird manuell den Referenzzeichnungen aus verschiedenen Blickrichtungen angepasst, Bilder von Paul Rademacher. Dabei ist d die Distanz zum Zentralknoten und r der maximale Radius der Einflussnahme. Dadurch wird garantiert, dass beim Deformieren der Ohren des Hasen aus Abb. 6.17 alle Nachbarknoten zur Spitze des Ohrs mitgeführt werden, bis sie aus dem Einflussbereich der Ohrspitze austreten und an das undeformierte Basismodell harmonisch anschließen können. Man benötigt ungefähr acht Key Deformationen pro Basismodell, um dazwischen sinnvoll weitere Blickrichtungen und resultierende Projektionen interpolieren zu können. Die Zahl acht ergibt sich relativ natürlich, wenn man eine begrenzende Box um das Basismodell legt und durch alle acht Ecken auf das Zentrum der Figur schaut. Bei der Interpolation geht man dann in folgender Weise vor: 1. Schritt: Finde die drei Punkte i, j, k aus den vorgegebenen Key Viewpoints, die das Dreieck aufspannen, dessen Normale die geringste Abweichung von der aktuellen Blickrichtung hat. 2. Schritt: Gehe zu baryzentrischen Koordinaten (t1 , t2 , t3 ) dieses Dreiecks über. 3. Schritt: Für ein gewichtetes schnelles (α > 1) oder langsames (α < 1) Überblenden werden diese Koordinaten exponentiell skaliert. t̃i = ti α /(t1 α + t2 α + t3 α ) 118 KAPITEL 6. NICHTPHOTOREALISTISCHES RENDERING 4. Schritt: Jeder Knoten wird durch eine Menge von N Key Deformationen {ν 1 , ν 2 , . . . , ν N } beschrieben. Der aktuelle Knoten ν errechnet sich nun aus ν = ν i t̃1 + ν j t̃2 + ν k t̃3 . . Abbildung 6.18. Aus acht verschiedenen Ansichten werden drei ausgewählt, deren Dreiecksfläche möglichst orthogonal zur Blickrichtung liegt. Die baryzentrischen Koordinaten sind dabei als Verhältnisse von Teildreiecksflächen definiert. Seien A1 , A2 , A3 die Massen in den Eckpunkten des Dreiecks und P das geometrische Zentrum, dann wird die dem Punkt A1 gegenüberliegende Kante im Verhältnis t3 : t2 geteilt. Entsprechend wird die dem Punkt A2 gegenüberliegende Kante im Verhältnis t1 : t3 und die dem Punkt A3 gegenüberliegende Kante im Verhältnis t2 : t1 geteilt. Die entsprechenden Teilungsstrecken durch Punkte und Kanten schneiden sich in P . Lässt man sie von jedem Eckpunkt aus in P enden, entstehen drei Teildreiecke, deren Flächenverhältnisse zueinander gerade t1 : t2 : t3 beträgt. Die Eckpunkte des Dreiecks lauten in baryzentriscen Koordinaten A1 = (1, 0, 0), A2 = (0, 1, 0) und A3 = (0, 0, 1). Damit sind diese Koordinaten in natürlichr Weise gegeinet, um gewichtete Interpolationen im Dreieck vorzunehmen. 6.6.2 Animationen In Animationen ist es häufig nötig, einen Bewegungsablauf übertrieben darzustellen, um alle abgewinkelten Gliedmaßen aus entsprechenden Blickrichtungen vollständig sehen zu können. Dazu müssen für einen gesamten Bewegungszyklus Key Deformationen aus den verschiedenen Blickrichtungen angefertigt werden. Die Zeitinterpolationen können dabei schon vorberechnet sein. Dreht sich jetzt während des Bewegungsszyklus die Kamera, so werden zusätzlich betrachterabhängige Interpolationen zur Laufzeit benötigt. 6.7. ÜBUNGSAUFGABEN 119 Abbildung 6.19. Oben: Blickpunktsänderung und optimale Verzerrung aus Kamerasicht, unten: das 3D-Modell aus immer der gleichen Perspektive. 6.7 Übungsaufgaben Aufgabe 6.1 Gooch Shading Implementieren Sie einen Silhouettenalgorithmus für einfache Objekte, indem Sie abwechselnd mit Backface und Frontface Culling arbeiten und dabei entsprechend den Polygonmodus von gefüllten Vordergrundpolygonen zu Linienobjekten (mit Linienstärke 5) wechseln. Ändern Sie außerdem die Testfunktion für den Tiefenspeicher von glDepthFunc(GL LESS) zu glDepthFunc(GL LEQUAL). Stellen Sie nun drei verschiedene und verschieden farbige, von einer bewegten Lichtquelle beleuchtete Objekte mit schwarzer Silhouette dar. Durch Drücken der Taste g wird die gleiche Szene in Gooch Shading, also einer Kalt-Warm Schattierung dargestellt, erneutes Drücken von g stellt das ursprüngliche Phong Modell wieder her. Aufgabe 6.2 Cross Hatching Verschaffen Sie sich vier periodische Texturen in der Manier der Kreuzschraffur. Stellen Sie nun drei verschiedene, von einer zentralen Lichtquelle beleuchtete Objekte mit schwarzer Silhouette und in Plastik Shading mit grauer (default) Objektfarbe dar. Durch Drücken der Taste c wird die gleiche Szene mit der Kreuzschraffur texturiert, erneutes Drücken von c stellt das ursprüngliche Phong Modell wieder her. Gehen Sie dabei ähnlich wie beim Toon Shading mit einer Lookup-Table für die fünf Intensitätsstufen vor. 120 KAPITEL 6. NICHTPHOTOREALISTISCHES RENDERING Abbildung 6.20. Blickpunktsänderung bei einer einzelnen Aufnahme eines Bewegungszyklus, oben die optimale Verzerrung aus Kamerasicht, unten das 3D-Modell aus immer der gleichen Perspektive. Kapitel 7 Splines In den 50er Jahren des 20. Jahrhunderts wurde besonders im Automobilbau und im Schiffbau eine exakte Beschreibung von Freiformflächen benötigt. Eng mit der Entwicklung verbunden sind die Namen Bézier und de Casteljau. Pierre Étienne Bézier, der bei Renault in Frankreich beschäftigt war, wurde zum Namensgeber des Bézier-Spline. Ebenfalls im französischen Automobilbau bei Citroën hat Paul de Casteljau über Splines gearbeitet und wurde Namensgeber für einen Konstruktionsalgorithmus. Abbildung 7.1. Dachflächen eines BMW werden mit dem Programm CATIA (Computer Aided Three-Dimensional Interactive Application) der französischen Firma Dassault Systèmes entwickelt. Der Begriff Spline stammt ursprünglich aus dem Schiffbau und ist die englische Bezeichnung für eine Straklatte, eine lange dünne Latte, die an mehreren Punkten eingespannt wird und sich zwischen diesen ihren freien Kräften überlassen ausformt. Eingang in die mathematische Wissenschaft und 121 122 KAPITEL 7. SPLINES erste Erwähnung in einer Veröffentlichung fand der Begriff 1946 durch Isaac Jacob Schoenberg. Das praktische Vorgehen im Schiff- und Karosseriebau ist geprägt durch die Kontrolle des Prototypen unter Streifenlicht: Man dreht das Objekt in einer Halle, deren Decke mit Neonröhren dicht besetzt ist. Hier wird auch der enge Zusammenhang zur Computergraphik deutlich. Eine glatte Freiformfläche wird über den Grad der Differenzierbarkeit in jedem Punkt und damit über die Eigenschaften des Tangentialfelds erreicht. Das Tangentialfeld an eine Fläche ist über das orthogonale Normalenfeld leicht sichtbar zu machen, denn der Term (L · N ) gibt das diffuse, der Term (H · N )n gibt das Highlight wieder. Sprünge im Tangentialfeld stellen auch Sprünge im Normalenfeld dar. Notwendig für eine auch an Wendepunkten (von positiver zu negativer Krümmung) glatte Fläche ist zweifach stetige Differenzierbarkeit (oder C 2 Stetigkeit) und damit ein kubischer Spline. Definition 7.1 Ein Spline n-ten Grades ist die Parametrisierung einer Mannigfaltigkeit (Kurve, Fläche), deren Koordinatenfunktionen stückweise aus Polynomen mit maximalem Grad n zusammengesetzt sind. Die Gestalt der Polynome wird von Kontrollpunkten bestimmt. 7.1 Splinekurven Zunächst beschränken wir uns auf ebene Splines, wobei sich der Ansatz auf den Rn einfach übertragen lässt, da jede Koordinatenfunktion mit dem gleichen Parameter t parametrisiert werden kann. Betrachtet man nun eine Folge von Kontrollpunkten Pi ∈ R2 , so besteht das Ziel darin, diese Kontrollpunkte durch eine Funktion S : R → R2 zu interpolieren (d.h. die von der Funktion beschriebene Kurve läuft durch die Punkte) oder zu approximieren (die Funktion nähert die Folge der Kontrollpunkte). Ein interpolierender oder approximierender Spline ist stückweise aus Polynomen zusammengesetzt und wird so konstruiert, dass er die geforderten Eigenschaften erfüllt. Bemerkung 7.1 Viele Versuche im CAD sind motiviert durch die an S gestellten gewünschten Eigenschaften, interpolierend, approximierend, hinreichend glatt oder uniform (gleiche Abstände der Kontrollpunkte zueinander) zu sein. Sei f (t) = (x(t), y(t)). Dann kann man die Koordinatenfunktionen x und y mit den Kontrollpunkten Pi = (xi , yi ) komponentenweise darstellen als X x(t) = bi (t)xi i y(t) = X bi (t)yi i Werden die Basisfunktionen bi so gewählt, dass sie lokalen Träger haben (d.h. nur lokal von Null verschieden sind), beschränkt sich der Einfluss, den ein Kontrollpunkt Pi auf die Kurve hat, auf eine kleine Umgebung dieses Kontrollpunkts. Die Stetigkeit von f ergibt sich aus der Stetigkeit der bi . Einen weichen Kurvenverlauf erhält man, wenn die bi hinreichend glatt sind. 7.1. SPLINEKURVEN 7.1.1 123 Kubisch hermitesche Splines Eine wichtige Rolle spielen kubisch hermitesche Splines, wobei jedes Polynom auf dem Intervall t ∈ [0, 1] von zwei Kontrollpunkten P0 , P1 und zwei Kontrolltangenten mit Steigung m0 , m1 bestimmt wird. Diese interpolierenden Splines sind von der Form f (t) = (2t3 − 3t2 + 1)P0 + (t3 − 2t2 + t)m0 + (−2t3 + 3t2 )P1 + (t3 − t2 )m1 = h00 (t)P0 + h10 (t)m0 + h01 (t)P1 + h11 (t)m1 mit den vier in obiger Gleichung aufgeführten hermiteschen Basisfunktionen {hij , i, j ∈ {0, 1}}. Abbildung 7.2. Die vier hermiteschen Polynome vom Grad 3 auf dem Intervall [0, 1]. Hat man nun eine beliebige Menge von Kontrollpunkten {Pk , k = 1, . . . , n}, ordnet man dieser einen Knotenvektor (xk ) zu, der die Reihenfolge und die parametrisierten Abstände der Punkte zueinander festlegt. Die Interpolation dieses Datensatzes (xk , Pk ) für k = 1, . . . , n geschieht zwischen je zwei Punkten Pk , Pk+1 , indem man die räumliche Schrittweite h = xk+1 − xk auf dem Knotenvektor und den Parameter t = (x − xk )/h dem Intervall anpasst. Ein Punkt f (t) ergibt sich jetzt aus f (t) = h00 (t)Pk + h10 (t)h mk + h01 (t)Pk+1 + h11 (t)h mk+1 , wobei die Steigung jeweils mit der Schrittweite h multipliziert werden muss. Stimmen nun die Tangenten in den jeweiligen End- und Anfangspunkten überein, erhält man einen interpolierenden Spline dritten Grades für eine beliebige Anzahl von Kontrollpunkten. Einfachste Bedingung an die Tangente, die auch für nicht uniforme Knotenvektoren stimmt, ist die finite Differenz mit 124 KAPITEL 7. SPLINES mk = Pk − Pk−1 Pk+1 − Pk + . 2(xk+1 − xk ) 2(xk − xk−1 ) Zu den kubisch hermiteschen interpolierenden Splines zählen aber auch die Kardinalsplines mit mk = (1 − c) Pk+1 − Pk−1 2 mit c ∈ [0, 1[ und als einfachster Spezialfall die Catmull-Rom Splines mit c = 0. Bemerkung 7.2 Die Tangentialbedingung bedeutet beispielsweise für den Kardinalspline, dass er Rundungen nur mit einer großen Anzahl von Punkten gut nähern kann, da er bei starkem Richtungswechsel zum Überschießen neigt. 7.1.2 Bézier-Splines Bézier-Splines sind approximierende Splines, die allerdings ihren Anfangs- und Endpunkt interpolieren. Sie setzen die Bernsteinpolynome als Basis ein. Diese Polynome wurden 1911 von Sergei Natanowitsch Bernstein für den konstruktiven Beweis des Weierstraß’schen Approximationssatzes entwickelt. Definition 7.2 Bernsteinpolynome Bi,n sind für alle 0 ≤ i ≤ n definiert als Bi,n : R → R n i t 7→ t (1 − t)n−i i und werden üblicherweise auf dem Intervall [0, 1] betrachtet. Für ein beliebiges Intervall [a, b] verallgemeinert sich die Formel zu [a,b] Bi,n : R → R 1 t → 7 (b − a)n n (t − a)i (b − t)n−i . i Wichtige Eigenschaften, die man zum Teil direkt aus Abb. 7.3 ablesen kann, sind die Basiseigenschaft, die Positivität, die Partition der Eins und die Symmetrie. Basis: Die Bernsteinpolynome {Bi,n : 0 ≤ i ≤ n} sind linear unabhängig und bilden eine Basis vom Raum Πn der Polynome vom Grad kleiner gleich n. 7.1. SPLINEKURVEN 125 Abbildung 7.3. Die sechs Bernsteinpolynome vom Grad 5 auf dem Intervall [0, 1]. Positivität: Alle Bi,n sind auf dem Einheitsintervall positiv, Bi,n (t) > 0 ∀ t ∈ ]0, 1[. Partition der Eins: Sie bilden eine Zerlegung der Eins, also n n X X n i Bi,n (t) = t (1 − t)n−i = 1. i i=0 i=0 Symmetrie: Zu jedem Basispolynom gibt es ein an der Achse t = 0.5 gespiegeltes Basispolynom Bi,n (t) = Bn−i,n (1 − t). Es gibt zahlreiche Java-Applets, um sich die verschiedenen Splines und die Manipulationsmöglichkeiten anzeigen zu lassen. Eine empfehlenswerte Webseite für Bézier-Splines befindet sich unter http://www.gris.uni-tuebingen/edu/projects/grdef/applets/bezier/html/index.html. 7.1.3 Konstruktionsalgorithmus nach Casteljau Der Bézier-Spline geht durch den Anfangs- und Endpunkt A und B und approximiert die dazwischen liegenden Kontrollpunkte. Ein Punkt C auf der Kurve ist dabei eine affine Kombination aus den Kontrollpunkten. C = tA + (1 − t)B t ∈ [0, 1[ Werden nur zwei Punkte angegeben, ist die Kurve die (lineare) Verbindung und der Spline hat den Grad eins. Der Konstruktionsalgorithmus von Casteljau sieht nun vor, dass beim Einfügen eines weiteren Kontrollpunkts der Linienzug jeweils bis zum Parameter t durchlaufen wird, um eine neue 126 KAPITEL 7. SPLINES Strecke zwischen den Geraden einzufügen, die den Punkt auf der Kurve ebenfalls bei t bezeichnet. Dabei erhöht sich der Grad jeweils um eins. Bemerkung 7.3 Ein Bézier-Spline vom Grad n benötigt n+1 Kontrollpunkte, geht durch den Anfangsund Endpunkt und approximiert die dazwischenliegenden n − 1 Punkte. Abbildung 7.4. Casteljau Algorithmus mit zugehörigen Bernsteinpolynomen links für drei und rechts für vier Kontrollpunkte. Es wird deutlich, dass beim Einfügen eines neuen Punktes der Grad des Splines automatisch zunimmt. Die Koordinaten des Punktes wirken sich auf die gesamte Kurve aus. Will man einen festen Grad n und beliebig viele Punkte vorgeben, müsste man die stückweise konstruierten Bézier-Kurven in ihren Endpunkten hinreichend glatt, nämlich C n−1 , verkleben, was mit dem Ansatz der Bernsteinpolynome als Basis unnötig kompliziert ist. 7.1.4 B-Splines Will man den Grad des Splines beschränken und dennoch eine glatte Kurve durch beliebig viele Kontrollpunkte bestimmen, muss man die Auswirkung der einzelnen Basisfunktionen in natürlicher Weise begrenzen. Isaac Jacob Schoenberg hat den Begriff B-Spline (für Basis-Spline) geprägt und über das Faltungsintegral motiviert, Carl de Boor hat 1978 die algorithmische und numerisch stabile Konstruktion der Basis geliefert. Die in besonderer Weise konstruierte Basis hat einige Eigenschaften, die man auch bei subdivision surfaces benötigt. Definition 7.3 Für einen gegebenen Knotenvektor aus m + 1 aufsteigend sortierten Werten ti ∈ [0, 1] des Einheitsintervalls 0 ≤ t0 ≤ t1 ≤ · · · ≤ tm ≤ 1 7.1. SPLINEKURVEN 127 Abbildung 7.5. Maßgeblich an der Entwicklung von Splines beteiligt waren links: Pierre Étienne Bézier (1910– 1999), mitte: Isaac (Iso) Schoenberg (1903–1990) und rechts: Carl de Boor (* 1937). ist ein B-Spline vom Grad n eine parametrisierte Kurve f : [tn , tm−n [ → t 7→ R2 m−n−1 X bi,n (t) Pi i=0 mit m − n Kontrollpunkten {P0 , . . . , Pm−n−1 } und rekursiv definierten Basispolynomen ( 1 für tj ≤ t < tj+1 bj,0 (t) := 0 sonst bj,n (t) := t − tj tj+n+1 − t bj,n−1 (t) + bj+1,n−1 (t). tj+n − tj tj+n+1 − tj+1 Für identische Knoten tj ≡ tj+1 wird bj,0 (t) ≡ 0 und es reduziert sich bj,1 zu bj,1 (t) := tj+2 − t bj+1,0 (t). tj+2 − tj+1 Was an dieser Definition gegenüber der Bézierkurve auffällt, ist dass man den Grad vorschreiben und beliebig viele Kontrollpunkte entlang des Splines positionieren kann, solange man einen Kontrollvektor zur Verfügung stellt, der die Summe aus der Anzahl der Kontrollpunkte und dem geforderten Grad um mindestens eins übersteigt. Es fällt weiter auf, dass der B-Spline nicht auf dem gesamten Intervall [t0 , tm [ definiert ist, sondern nur auf [tn , tm−n [. Definition 7.4 Wenn die Knoten das Intervall zur Parametrisierung der Kurve äquidistant unterteilen, heißt der B-Spline uniform, sonst wird er nichtuniform genannt. Ein offen uniformer B-Spline wiederholt den ersten und letzten Knoten entsprechend der Gradzahl, also (n + 1)mal, um den Spline bis an diese Punkte heranzuführen. Dieser offen uniforme B-Spline, 128 KAPITEL 7. SPLINES bei dem die Anzahl der Kontrollpunkte den Grad um genau eins übersteigt, degeneriert zu einem Bézier-Spline. Abbildung 7.6. Die Veränderung des Knotenvektors bei vier identischen Kontrollpunkten zeigt sich in der Ausdehnung des Trägers und der Basisfunktionen: Links ein kubischer B-Spline mit äquidistantem Knotenvektor, rechts ein zum Bézier-Spline degenerierter B-Spline mit (0, 0, 0, 0, 1, 1, 1, 1) als Knotenvektor. Beispiel 7.1 Für einen kubischen Spline vom Grad n = 3 benötigt ein Bézier-Spline vier Kontrollpunkte. Daher muss der Knotenvektor für einen B-Spline wegen m−3 = 4 ⇒ m = 7, also m+1 = 8 die Länge acht haben. Der dazugehörige offen uniforme Knotenvektor auf dem Einheitsintervall ist (0, 0, 0, 0, 1, 1, 1, 1). Bemerkung 7.4 Die Länge des Knotenvektors ergibt sich aus dem gewünschten Grad n des B-Splines und der Anzahl der Kontrollpunkte k = m − n ⇔ m + 1 = k + n + 1. Da die Anzahl der Kontrollpunkte den Grad um mindestens eins übersteigen muss, ist die Länge des Knotenvektors mindestens 2n + 2. Wie man im linken Teil der Abb. 7.6 sieht, besteht die Basis eines uniformen B-Spline für einen gegebenen Grad n aus m − n (= Anzahl der Kontrollpunkte) identischen, verschobenen Kopien. Alle diese Kopien haben lokalen Träger, der sich über ]tj , tj+n+1 [ erstreckt. Dadurch bleibt der Einfluss jedes Kontrollpunkts Pi lokal begrenzt und richtet sich nur nach dem Grad des gewünschten Splines. Die sogenannten Blendfunktionen sind auf jedem Intervall zwischen zwei Knoten gleich (siehe den rechteckig hervorgehobenen Bereich zwischen i3 und i4 im linken Teil von Abb. 7.6). Es sind n + 1 disjunkte Abschnitte einer Kopie dieser Basisfunktion. Mit ihnen lässt sich der i-te Abschnitt des kubisch uniformen Splines in Matrixform schreiben als fi (t) = [t3 t2 −1 3 −3 1 Pi−1 1 3 −6 3 0 Pi t 1] 3 0 Pi+1 6 −3 0 1 4 1 0 Pi+2 für t ∈ [0, 1[, wobei der allen gemeinsame Träger ]tj+n , tj+n+1 [ der Einfachheit halber mit dem Einheitsintervall identifiziert wird. Es wirken sich hier die zentral um den Punkt Pi (für n gerade) oder die Punkte 7.1. SPLINEKURVEN 129 Pi , Pi+1 angeordneten n + 1 Punkte aus. Hier wird nochmal deutlich, dass der Knotenvektor keinen direkten Zusamenhang mit den Kontrollpunkten sondern eher mit den Basisfunktionen hat. Ein nichtuniformer Spline kann sukzessiv kleiner werdende Intervalle nutzen, um Kontrollpunkte zu interpolieren. Allgemein kann man die uniformen bj,n auch schreiben als bj,n (t) = bn (t − tj ), j = 0, . . . , m − n − 1 und nicht rekursiv sondern direkt ermitteln als n+1 n+1X bn (t) := ai,n (t − ti )n+ n i=0 mit ai,n = n+1 Y 1 . t l − ti l=0,l6=i Dabei bezeichnet (t − ti )n+ die positive Potenzfunktion (negative Teile werden abgeschnitten). Definition 7.5 Ein Polygonzug durch die Kontrollpunkte oder de Boor Punkte wird de Boor Polygon genannt. 7.1.5 Konstruktion der Basisfunktionen Um die Basisfunktionen Bi der B-Splines zu konstruieren, bedient man sich der Faltung, da durch die Integration die gewünschten Eigenschaften ganz unterschiedlicher Funktionen auf das Faltungsprodukt übertragen werden. Das Faltungsprodukt zweier Funktionen f und g ist definiert als Z f ∗ g (t) := f (s)g(t − s)ds. Sei nun B0 : R → R die charakteristische Funktion auf [− 21 , 12 [ ( 1 für − B0 (t) := 0 sonst 1 2 ≤t< 1 2 mit lokalem Träger, nämlich genau dem Einheitsintervall. Nun erhält man B1 durch Faltung von B0 mit sich selbst. Z B1 (t) := B0 ∗ B0 (t) = B0 (s)B0 (t − s)ds War B0 noch unstetig an den Stellen − 21 und 12 , so ist B1 stetig und ist eine sogenannte Hutfunktion mit einem Maximum bei B1 (0) = 1 und einem Träger, der aus dem Intervall ] − 1, 1[ besteht. Faltet man 130 KAPITEL 7. SPLINES nun B1 mit B0 so erhält man eine einmal stetig differenzierbare Funktion B2 mit einem Maximum bei b2 (0) < 1 und einem Träger ] − 32 , 32 [. Allgemein gilt Z Bl (t) := Bl−1 ∗ B0 (t) = Bl−1 (s)B0 (t − s)ds, , l+1 [ wobei die Funktionen Bl alle gerade Funktionen sind und der Träger aus dem Intervall ] − l+1 2 2 besteht. Eine wichtige Eigenschaft dieser Konstruktionsmethode ist, dass man mit jeder Faltung einen zusätzlichen Grad in der Differenzierbarkeit gewinnt. Wenn eine Funktion f k-mal stetig differenzierbar ist, also f (t) ∈ C k , dann ist f ∗ B0 (t) ∈ C k+1 . War die Funktion B1 (t) ∈ C 0 , also stetig, so ist B2 (t) ∈ C 1 , also stetig differenzierbar. Für die Funktion Bn gilt damit Bn (t) ∈ C n−1 . Die Basisfunktionen Bl werden zentrierte Kardinal B-Splines genannt, ein Ausdruck, der auf Schoenberg zurückgeht. Die Funktionen bn erhalten wir nun aus einem der Bn durch Verschieben und Stauchen bj,n (t) = bn (t − tj ) = Bn (m(t − tj+ n+1 )). 2 7.1.6 Verfeinerbarkeit von B-Splines Eine wichtige Eigenschaft der B-Splines ist ihre Verfeinerbarkeit. Diese Eigenschaft ist es, die BSplines mit Subdivisionsalgorithmen eng verbindet. Man versteht darunter, dass man neue Kontrollpunkte so einfügen kann, dass sich die durch den B-Spline beschriebene Kurve nicht ändert. Die oben konstruierten Basisfunktionen erfüllen die Verfeinerungsgleichung n+1 1 X n+1 Bn (2t − k). Bn (t) = n 2 k=0 k Eine B-Spline Basisfunktion kann also als Summe über gestauchte und verschobene Kopien von sich selbst geschrieben werden. Eine Anleitung zum Beweis dieser wichtigen Eigenschaft wird in Aufgabe 7.2 gegeben. Abbildung 7.7. Die (blaue) Hutfunktion B1 (t) kann als Linearkombination aus gestauchten und verschobenen (rot gestrichelten) Hutfunktionen 12 B1 (2t) + B1 (2t − 1) + 12 B1 (2t − 2) dargestellt werden. 7.1. SPLINEKURVEN 7.1.7 131 Subdivision für Spline-Kurven Betrachtet man einen (uniformen) B-Spline in der Darstellung X f (t) := Bn (t − i) Pi i und es sei P der Vektor aus Kontrollpunkten um einen zentralen Punkt P0 . .. P−1 P P= 0 P1 .. . und Bn (t) der Vektor aus Basisfunktionen Bn (t) = [. . . , Bn (t + 2), Bn (t + 1), Bn (t), Bn (t − 1), Bn (t − 2), . . .] , so kann man die Kurve f auch schreiben als f (t) = Bn (t)P. Der neue Vektor Bn (2t) ist durch die Verfeinerungsgleichung motiviert Bn (2t) = [. . . , Bn (2t + 2), Bn (2t + 1), Bn (2t), Bn (2t − 1), Bn (2t − 2), . . .] und fasst doppelt so viele Elemente wie Bn (t). Jetzt stellt man über eine Matrix S den Zusammenhang Bn (t) = Bn (2t)S her. Die Einträge der Matrix S sind durch die Verfeinerungsgleichung ! 1 n+1 S2i+k,i = sk = n 2 k gegeben, wobei n den Grad der Basisfunktionen bezeichnet. Die Kurve f lässt sich nun schreiben als f (t) = Bn (t)P = Bn (2t)SP. Wie man sieht, geht man mit der neuen Basis von den alten Kontrollpunkten P auf die neuen Kontrollpunkte SP über, verändert aber die beschriebene Kurve nicht. Sie wird nur mit doppelt so vielen Basisfunktionen beschrieben, deren Träger jeweils halb so groß sind und die doppelt so schnell durchlaufen werden. 132 KAPITEL 7. SPLINES Diesen Schritt kann man beliebig oft wiederholen. f (t) = = .. . Bn (t)P0 Bn (2t)P1 Bn (2t)SP0 = = Bn (2j t)Pj = Bn (2j t)S j P0 Dabei gibt der hochgestellte Index j an dem Kontrollpunktevektor Pj das Level der Verfeinerung an. Für die Beziehung zwischen zwei aufeinanderfolgenden Subdivisionslevel ergibt sich Pj+1 = SPj . Betrachtet man nun gesondert die Punkte mit geradem Index (die den alten Kontrollpunkten aus Pj entsprechen) und die Punkte mit ungeradem Index (Punkte, die in Pj+1 durch Verfeinerung neu hinzugekommen sind), so erhält man X X P2ij+1 = S2i,l Plj = s2(i−l) Plj l l für die geraden und j+1 = P2i+1 X l S2i+1,l Plj = X s2(i−l)+1 Plj l für die ungeraden Knoten. Für lineare Splines sind die Punkte mit geradem Index identisch mit den Punkten des vorhergehenden Levels und die neuen Punkte liegen immer mittig zwischen den alten Punkten. Für interpolierende Splines gilt ebenfalls, dass einmal auf dem Spline befindliche Punkte identisch bleiben. Im approximierenden Fall (also für alle B-Splinebasen vom Grad n ≥ 2 sind alle Punkte des Levels j + 1 eine Linearkombination aus den Punkten des Levels j, also auch die mit geradem Index, und also gilt P2ij+1 6= Pij . Abbildung 7.8. Ein Linienzug mit anschließenden Verfeinerungsstufen für eine kubische (approximierende) BSplinebasis. Bemerkung 7.5 Wenn der Prozess der Verfeinerung wiederholt wird, erhält man eine immer dichter werdende Folge von Kontrollpunkten, die gegen die Spline-Kurve konvergiert. Der Abstand der Kontrollpunkte zur Kurve nimmt dabei um einen konstanten Faktor pro Verfeinerungsschritt ab. Schon nach wenigen Schritten wird es schwer, die Kontrollpunkte von der Kurve zu unterscheiden. Darin besteht auch der Sinn der Verfeinerung: Statt die Punkte auf der Kurve mit den entsprechenden Splinebasen höheren Grades aus wenigen Kontrollpunkten zu berechnen, verfeinert man hinreichend häufig und interpoliert die Punkte linear. 7.1. SPLINEKURVEN 133 Beispiel 7.2 Bei kubischen Splines (Grad 3) ergibt sich für die Einträge der Subdivision Matrix 1 s0 = , 8 4 s1 = , 8 6 s2 = , 8 4 s3 = , 8 1 s4 = . 8 Für die geraden Knoten ergibt sich so 6 1 j 1 j + Pij + Pi+1 . P2ij+1 = Pi−1 8 8 8 Für die ungeraden ergibt sich 1 1 j j+1 P2i+1 = Pij + Pi+1 . 2 2 Mit zentralen fünf Kontrollpunkten des Levels j kann man fünf neue Punkte des nächsten Levels j + 1 ganz einfach über Matrixmultiplikation gewinnen. j+1 j 1 6 1 0 0 P−2 P−2 j+1 j P−1 0 4 4 0 0 P−1 1 j+1 j P0 = 0 1 6 1 0 P0 8 P j+1 0 0 4 4 0 Pj 1 1 j+1 j P2 P2 0 0 1 6 1 7.1.8 Nichtuniforme rationale B-Splines Nichtuniforme rationale B-Splines (NURBS) werden aus den einfacheren uniformen nichtrationalen B-Splines abgeleitet, die wir im vorigen Abschnitt ausführlich behandelt haben. Wenn man zusätzlich Gewichte wi einfügt, kann man den Spline für wi > 1 stärker an einen Punkt Pi heranführen (oder für 0 > wi > 1 den Einfluss mindern) als im ungewichteten Fall. Weniger intuitiv (aber genauso richtig) kann man die Gewichte auch den Basisfunktionen zuordnen, da es genauso viele Basisfunktionen wie Kontrollpunkte gibt. Lokal allerdings ist die Anzahl der von null verschiedenen Basisfunktionen immer um eins größer als der Grad des Splines. Letztlich erzeugt man diese Wichtung auch durch ein nicht uniformes Unterteilen des Knotenvektors. Dadurch werden ebenfalls einzelne Basisfunktionen gegenüber den benachbarten Basisfunktionen stärker oder schwächer bewertet. Erstaunlicherweise 2 2 aber können Kreise oder Ellipsen (in Koordinaten xa2 + yb2 = 1) und Hyperbeln (in Koordinaten 2 x2 − yb2 = 1) nur schlecht von Splines approximiert werden. Ihre Koordinatendarstellungen legen a2 nahe, sie als rationale Splines darzustellen, also Nennerpolynome aus gewichteten Basisfunktionen zuzulassen. Definition 7.6 Die rationalen B-Spline Basisfunktionen Ri,n errechnen sich aus den B-Spline Basisfunktionen bi,n über wi bi,n (t) Ri,n (t) = Pk−1 . j=0 wj bj,n (t) 134 KAPITEL 7. SPLINES Eine NURBS-Kurve ist die Summe der mit rationalen B-Spline Basisfunktionen Ri,n gewichteten k Kontrollpunkte {P0 , . . . , Pk−1 } k−1 X f (t) = Ri,n (t)Pi , i=0 wobei der Parameter t ∈ [a, b[ einen monoton steigenden Knotenvektor T = { a, . . . , a , tn+1 , . . . , tm−n−1 , b, . . . , b } | {z } | {z } n+1 n+1 der Länge m + 1 = k + n + 1 durchläuft. Bemerkung 7.6 Gewichte an den einzelnen Knoten verändern bereits den Einfluss der Punkte. Dennoch können NICHTrationale Splines nur schlecht Kreise und Kegelschnitte approximieren. Eine Abhilfe schaffen rationale B-Splines mit Zähler- und Nennerpolynom von der Form k−1 X f (t) = wi bi,n (t) Pi i=0 k−1 X = p(t) . q(t) wi bi,n (t) i=0 Wenn die gewichteten Basisfunktionen wieder eine Partition der Eins darstellen, entspricht der rationale wieder dem einfachen B-Spline. 7.2 Flächen als bivariate Splines Die an Kurven dargestellte Theorie lässt sich natürlich auch auf Flächen ausdehnen, wobei die Parametrisierung über einem Rechteck statt einem Intervall geschieht, um den zwei linear unabhängigen Raumrichtungen auch (bivariate) unabhängige Krümmungen zuordnen zu können. Steven Anson Coons war einer der Pioniere der Computergraphik und Lehrer von Ivan Sutherland (dessen Dissertation als Beginn der interaktiven Computergraphik gilt). Mit seiner analytischen Metode zur Berechnung der Ränder einer doppelt gekrümmten Oberfläche ist er vom Einheitsquadrat ausgegangen und hat mit den Monomen bis Grad sieben jede beliebige Fläche approximieren können. Die sogenannten Coons Pflaster stellen die grundlegende Formulierung zur Oberflächenbeschreibung interpolierender oder approximierender Flächen dar. Es wundert daher nicht, dass der Steven A. Coons Award die höchste Auszeichnung auf dem Gebiet der Computergraphik ist, die alle zwei Jahre auf der ACM SIGGRAPH vergeben wird, Preisträger waren u.a. Sutherland, Bézier, Evans, van Dam, Catmull, Foley, Blinn, Hanrahan. 7.2. FLÄCHEN ALS BIVARIATE SPLINES 7.2.1 135 NURBS-Flächen In vielen CAD-Werkzeugen speziell im Karosseriebau werden bevorzugt NURBS-Flächen zur Modellierung eingesetzt, so z.B. in dem Programm CATIA der französischen Firma Dassault Systèmes. Eine NURBS-Fläche ist ein bivariater Spline, der in zwei Richtungen mit den Parametern u und v aufgespannt wird. f (u, v) = k−1 X r−1 X Ri,n;j,t (u, v) Pi,j i=0 j=0 Dabei liegen die k mal r Punkte Pi,j auf einem Kontrollgitter, das sich durchaus selbst durchdringen, berandet oder unberandet sein kann. Die rationalen Basisfunktionen sind durch wi,j bi,n (u) bj,t (v) Ri,n;j,t (u, v) = Pk−1 Pr−1 i=0 j=0 wi,j bi,n (u) bj,t (v) gegeben. Die Gewichtematrix ist ebenfalls zweidimensional. Die Länge der Knotenvektoren U und V sind vom Grad n oder vom Grad t abhängig, wobei natürlich auch beide Richtungen vom gleichen Grad sein können. Sie besitzen jeweils m + 1 = k + n + 1 oder s + 1 = r + t + 1 monoton wachsende Einträge. U = { a, . . . , a , un+1 , . . . , um−n−1 , b, . . . , b } | {z } | {z } n+1 V n+1 = { c, . . . , c , vt+1 , . . . , vs−t−1 , d, . . . , d } | {z } | {z } t+1 t+1 Die in dieser Weise formulierten Knotenvektoren interpolieren jeweils die Randpunkte des Gitters und approximieren die inneren Gitterpunkte. In OpenGL Implementierungen sind Evaluatoren für Splinekurven und -flächen enthalten, die auf Bernsteinpolynomen aufbauen. Nachdem die Theorie hier behandelt wurde, sollte es leicht möglich sein, die entsprechenden Kontrollpunkte und Parameter für die Bibliotheksfunktionen glMap1*() und glMap2*() bereitzustellen. Die GLU Bibliothek stellt ein Interface für NURBS bereit, das auf diesen Evaluatoren aufbaut. Die Parameter werden mit gluNurbsProperty() eingestellt, die eigentlichen Flächenspezifischen Kontrollpunkte und -parameter zwischen gluBeginSurface() und gluEndSurface() über gluNurbsSurface() bereitgestellt. Man kann auch beliebige Kurven zwischen gluBeginTrim() und gluEndTrim() mit gluPwlCurve() oder gluNurbsCurve() aus einer Fläche herausschneiden (die Fläche trimmen). 136 KAPITEL 7. SPLINES Abbildung 7.9. Die mit OpenGL dargestellte grüne NURBS-Fläche vom Grad 4 approximiert 36 Kontrollpunkten über einem zweidimensionalen Gitter. 7.3 Subdivisionflächen Subdivision surfaces (Unterteilungsflächen) dienen der Beschreibung von glatten Oberflächen beliebiger Topologie. Mittels eines so genannten Kontrollgitters oder control mesh lässt sich die Topologie sowie die ungefähre Form der Flächen vorgeben. Indem man von dem Kontrollgitter ausgehend wiederholt verfeinert und nach jeder Verfeinerung die Punkte des neuen Gitters nach gewissen Regeln verschiebt, erhält man - bei passender Wahl des Regelwerks - eine glatte, das Kontrollgitter approximierende oder auch interpolierende Oberfläche. Das erste Mal wurden subdivision surfaces 1978 in Arbeiten von Doo und Sabin [DS78] sowie Catmull und Clark [CC78] beschrieben. Aber erst 1995 gelang es Ulrich Reif, grundlegende Fragen über das Verhalten von subdivision surfaces in der Umgebung außerordentlicher Knoten zu beantworten. Seither wurden viele neue Schemata entwickelt sowie die Glattheit der meisten Verfahren untersucht. Abbildung 7.10. Ein Tetraeder aus Vierkantengestänge mit anschließenden Verfeinerungsstufen. Auch für die Filmindustrie sind subdivision surfaces interessant. In Subdivision Surfaces in Character Animation [DKT98] (auch zu finden in [ZSD+ 00]) werden Vorteile von subdivision surfaces über traditionelle Oberflächenbeschreibungen (wie z.B. NURBS) bezüglich Animation und Editierbarkeit herausgestellt. 7.3. SUBDIVISIONFLÄCHEN 137 Definition 7.7 (Mesh) Ein Mesh beschreibt eine stückweise lineare Oberfläche. Er besteht aus Knoten (Vertices), Kanten (Edges) und Flächenstücken (Faces). Jede Kante eines Meshes hat höchstens zwei, mindestens aber ein benachbartes Flächenstück. Definition 7.8 (Glattheit) Eine Oberfläche O ⊂ R3 wird als glatt bezeichnet, wenn zu jedem Punkt P ∈ O eine offene Umgebung U ⊂ R3 und eine offene Nullumgebung V ⊂ R2 existieren, so dass eine stetig differenzierbare C 1 Abbildung ϕ : R2 → R3 existiert mit ϕ(V ) = U ∩ O. Bemerkung 7.7 In der Computergraphik ist man häufig eher an Gn statt C n -Stetigkeit interessiert. Für die Analyse der Flächen ist aber die C n -Stetigkeit einfacher handhabbar. Der Unterschied besteht in der Definition: die mathematische C n -Stetigkeit wird über die n-ten Ableitungen definiert, die stetig sein müssen. Darin sind solche Spezialfälle möglich, bei denen ein Tangentialvektor in einem Punkt gegen die Länge Null konvergiert und optisch eine Ecke entstehen kann. G1 -Stetigkeit besagt, dass in jedem Punkt eine eindeutige Tangente positiver Länge existiert. Die entsprechend höheren Gn Stetigkeiten sind wieder über n-te Ableitungen definiert. Das Ziel ist eine stückweise lineare Oberfläche so fein zu unterteilen, dass sie den Eindruck einer glatten Oberfläche erzeugt, also lokal wie ein Stück der Ebene aussieht, bei der es keine Knicke an Kanten gibt. Der wichtigste Unterschied von Subdivisionsalgorithmen zu NURBS-Flächen besteht in der allgemeineren Beschreibung einer zweidimensionalen Mannigfaltigkeit. Wird die Fläche aus einzelnen NURBS-Flächen zusammengestückelt, muss man sich beim Verkleben der einzelnen Patches immer genau über den Glattheitsgrad am Rand von einer zur nächsten Fläche kümmern. Bei Subdivisionsalgorithmen gibt man ein Regelwerk vor, mit dem die Unterteilung gegen eine Fläche beliebiger Glattheit konvergiert. Um sinnvoll angewendet werden zu können, sollten subdivision surfaces einigen Anforderungen genügen. Einfachheit: Das Regelwerk sollte möglichst klein sein. Effizienz des Regelwerks: Die Berechnung der neuen Positionen der Knoten nach einem Verfeinerungsschritt sollte wenige Operationen benötigen. Kompakter Träger: Die Umgebung, in der ein Knoten die Form der resultierenden Oberfläche beeinflusst, sollte möglichst klein, in jedem Fall endlich sein. Lokale Definition: Die Regeln für die Positionierung neuer Knoten sollte nicht auf weit entfernten Knoten beruhen. Entfernung meint hier die Anzahl der Kanten auf dem Mesh. Affine Invarianz: Wird das Kontrollgitter M einer affinen Transformation (z.B. Translation, Skalierung, Rotation) unterzogen, so sollte sich auch die subdivision surface durch die selbe Transformation in die aus dem transformierten Kontrollgitter resultierende subdivision surface transformieren lassen. Stetigkeit: Aussagen über den Grad der Stetigkeit (Glattheit) der resultierenden subdivision surface sollten (fast überall) möglich sein. 138 7.3.1 KAPITEL 7. SPLINES Subdivision Schemata Hat im eindimensionalen Fall (also bei Unterteilungskurven) noch jeder Knoten genau zwei Nachbarn (insofern es sich nicht um einen Randknoten handelt) kann es im zweidimensionalen Fall zu einem Knoten beliebig viele Nachbarn geben. Im Folgenden werden Merkmale und Eigenschaften unterschiedlicher Subdivision Schemata aufgeführt, mit deren Hilfe eine grobe Klassifizierung der verschiedenen Verfahren vorgenommen werden kann. Zunächst benötigen wir weitere Begriffe: Dreiecks-Mesh: Alle Faces des Meshes sind Dreiecke. Vierecks-Mesh: Alle Faces des Meshes sind Vierecke. Face Split: Bei Verfeinerung werden Faces in mehrere kleinere Faces zerlegt. Alte Knoten bleiben bei Verfeinerung erhalten. Vertex Split: Bei Verfeinerung werden pro Face vier neue Knoten eingefügt (bei Vierecks-Mesh). Neue Faces werden erstellt, indem die neuen Knoten verbunden werden. Alte Knoten kommen im verfeinerten Mesh nicht mehr vor. Abbildung 7.11. Flächenbezogenes Aufspalten der Unterteilungsalgorithmen, links für reguläres Dreiecksgitter, rechts für Rechtecksgitter. Abbildung 7.12. Beim knotenbezogenen Aufspalten werden die Knoten des vorigen Levels durch neue Knoten ersetzt. Definition 7.9 (Reguläre Knoten) Ein Knoten heißt regulär, wenn sechs Kanten in einem DreiecksMesh bzw. vier Kanten in einem Vierecks-Mesh von ihm ausgehen (siehe Abb. 7.11). 7.3. SUBDIVISIONFLÄCHEN 139 Für die irregulären Fälle müssen gesonderte Regeln in die Schemata eingeführt werden. Da für jede Zielsetzung unterschiedliche Subdivision Schemata entwickelt wurden, ist es sinnvoll, eine grobe Typisierung anhand der folgenden Merkmale vorzunehmen: • Art der Verfeinerungsregel (Face Split oder Vertex Split) • Typ des zugrunde liegenden Meshes (Dreiecks- oder Vierecks-Mesh) • Approximierende oder interpolierende Schemata • Glattheit der Grenzfläche bei regulären Meshes Die große Anzahl verschiedener Schemata lassen sich mit dieser Klassifizierung grob einordnen. Face split Dreiecksgitter Vierecksgitter 2 Approximierend Loop (C ) Catmull-Clark (C 2 ) Interpolierend Modified Butterfly (C 1 ) Kobbelt (C 1 ) Vertex split Doo-Sabin, Midedge (C 1 ) Biquartic (C 2 ) 7.3.2 Catmull-Clark Subdivision Abbildung 7.13. Zwei Stadien beim Modellieren eines Fischmauls mit zbrush, die unterschiedlich feine Unterteilungen zeigen. 140 KAPITEL 7. SPLINES Modellierungssoftware wie beispielsweise zbrush benutzt Catmull-Clark Unterteilungsflächen. Der Nutzer kann zwischen den einzelnen Level der Verfeinerung leicht hin- und herspringen. Während das Modell zur Visualisierung in vielen Bereichen grob vorgehalten und schnell gerendert wird, können in interessierenden Bereichen viele Details modelliert und gespeichert werden. Dabei erscheint das ganze Objekt als stetige glatte Fläche. Das Catmull-Clark Schema ist ein approximierendes Verfahren, das auf dem Tensorprodukt von bikubischen box splines basiert. Damit ist die Fläche C 2 -stetig bis auf die irregulären Punkte, an denen man nur C 1 -Stetigkeit erhält. In Matrixform kann ein bikubischer B-Spline Patch ausgedrückt werden als f (u, v) = U M GM t V t , wobei M die Koeffizienten der kubischen Basis enthält und die Vektoren U = (u3 , u2 , u, 1) und V = (v 3 , v 2 , v, 1) aus den Monomen bis zum Grad n = 3 bestehen. −1 3 −3 1 3 −6 3 0 1 M = 6 −3 0 3 0 1 4 1 0 Abbildung 7.14. Das Kontrollmesh dieser Unterteilung ist ein Würfel, der nach wenigen Schritten gegen eine allerdings viel kleinere Kugel konvergiert. Das Gitter G aus Kontrollpunkten P11 P12 P13 P14 P21 G = P 31 P22 P23 P32 P33 P24 P34 P41 P42 P43 P44 wird nun im Bereich 0 < u, v < 12 in der Hälfte verfeinert (die anderen Gitter ergeben sich aus Symmetriegründen in gleicher Weise, da die Basisfunktionen aufgrund der Verfeinerungsgleichung verschobene Kopien sind). Setzt man u1 = u2 und v1 = v2 , so erhält man in Matrixschreibweise jetzt f (u1 , v1 ) = U SM GM t S t V t , 7.3. SUBDIVISIONFLÄCHEN 141 wobei 1 8 0 0 0 0 S = 0 1 4 0 0 1 2 0 . 0 0 0 1 0 Dieser Patch muss wieder ein bikubischer B-Spline mit eigenem Kontrollgitter G1 sein, also der Gleichung f (u, v) = U M G1 M t V t genügen. Daraus ergibt sich M G1 M t = SM GM t S t . Da M invertierbar ist, berechnet man G1 = M −1 SM GM t S t M −t = H1 GH1t mit M −1 4 4 0 0 1 SM = H1 = 0 6 1 4 4 0 . 0 0 1 6 1 Dadurch ergeben sich für das neue Gitter G1 zwei neue Flächenpunkte Q11 = P11 + P12 + P21 + P22 4 und Q13 = P11 + P13 + P23 + P23 , 4 ein neuer Kantenpunkt Q12 Der neue Knoten Q22 = Q 4 + R 2 + 1 = 2 P22 4 1 R= 4 Q11 + Q13 P12 + P22 + 2 2 . wird mit Q= und Q11 + Q13 + Q31 + Q33 4 P22 + P12 P22 + P21 P22 + P32 P22 + P23 + + + 2 2 2 2 gebildet. Man kann leicht nachvollziehen, dass jeder neue Knoten eines Verfeinerungsgitters G1 in einer dieser Arten interpoliert werden kann. Daraus ergeben sich jetzt die Regeln für die Verfeinerung eines beliebigen Gitters und auch entsprechende Ausnahmeregeln, wenn die Kantenzahl an einem Knoten im irregulären Fall nicht vier ist. 142 7.3.3 KAPITEL 7. SPLINES Subdivision nach Loop Charles Loop hat 1987 ein einfaches Verfahren für Dreiecks-Meshes eingeführt, das Loop Schema. Mittels eines Face-Splits wird in einem Verfeinerungsschritt jedes Dreieck des alten Meshes in vier neue unterteilt. Abbildung 7.15. Nach dem Loop Schema verfeinerte Fläche. Das Loop Schema ist ein approximierendes Verfahren, das auf dem three-directional quartic box spline basiert. Die generierende Funktion der zugehörigen Verfeinerungsgleichung lautet S(z1 , z2 ) = 1 (1 + z1 )2 (1 + z2 )2 (1 + z1 z2 )2 , 16 wobei generierende Funktionen mit zwei Variablen allgemein als A(x, y) = X an,m xn y m n,m=0 definiert sind. Im regulären Fall ergeben sich die in Abb. 7.16 angegebenen Gewichte. Definition 7.10 Ein Schema heißt stationär, wenn unabhängig vom Level für jeden Verfeinerungsschritt der gleiche Algorithmus verwendet wird. Bemerkung 7.8 Stationäre Schemata haben den Vorteil, dass sie Aussagen über die Qualität (Glätte, Differenzierbarkeit) einer Fläche bei beliebigem Verfeinerungsgrad für reguläre Bereiche treffen können. Für irreguläre Knoten müssen meist gesonderte Betrachtungen gemacht werden. 7.3. SUBDIVISIONFLÄCHEN 143 Abbildung 7.16. Wichtung der Knoten im regulären Fall. Abbildung 7.17. Vorschlag für die Wichtung der Knoten im irregulären Fall. Loop schlug für die Wahl von β den Koeffizienten β = Fall ergibt sich daraus wieder β = Grenzfläche. 1 . 16 1 k 5 8 − 3 8 + 14 cos 2π k 2 vor. Im regulären Für irreguläre Knoten garantiert diese Modellierung eine glatte Bemerkung 7.9 Wenn man ein Dreiecks- oder Vierecksgitter regulär verfeinert, fügt man überall nur reguläre Knoten ein. Die Anzahl der irregulären Knoten wird gegenüber dem Ausgangsgitter also nicht vergrößert, sondern bleibt gleich. 7.3.4 Weiche und scharfe Kanten Durch das Verständnis der zu Grunde liegenden mathematischen Theorie erkennt man in den Subdivisionsalgorithmen ein Verfahren, mit dem es möglich ist, glatte Oberflächen beliebiger Topologie nicht nur zu beschreiben, sondern mittels einfacher Algorithmen effizient zu approximieren. Um subdivision surfaces allgemeiner einsetzen zu können, muss man das Regelwerk erweitern. Hier wurde Subdivision ausschließlich für Meshes ohne Rand betrachtet. Auch fehlt eine Möglichkeit, scharfe Kanten auf der Oberfläche zu beschreiben. 144 KAPITEL 7. SPLINES Abbildung 7.18. Verfeinerung eines Kopfes mit einzelnen Gitterpunkten, bei denen mehr als sechs Nachbarn vorkommen (siehe Schläfenregion). Weiterführende Arbeiten zu diesem Thema sowie eine einfache und effiziente Lösung lassen sich beispielsweise in der Arbeit von Hoppe [HDD+ 94] über Piecewise Smooth Surface Reconstruction finden. Hier werden Verfahren vorgestellt, bei denen einzelne Punkte auf den Flächen zu Kurven zusammengefasst und diese Kurven nun weiter verfeinert werden. Dadurch werden sie nicht bivariat verfeinert, also nicht als zur angrenzenden Fläche gehörig aufgefasst. So kann eine Fläche beliebiger Topologie mit einem einzigen Kontrollgitter auskommen und trotzdem in einzelnen Bereichen Knicke und Kanten aufweisen, ohne den Grad des Splines zu ändern oder die Kontrollpunkte zu häufen (siehe Abb. 7.19). 7.4 Übungsaufgaben Aufgabe 7.1 Uniforme und nichtuniforme quadratische B-Spline Basisfunktionen (a) Ermitteln Sie die quadratischen Blendfunktionen eines uniformen B-Spline und notieren Sie den i-ten Abschnitt eines Splines, also den Bereich um den i-ten Kontrollpunkt in Matrixschreibweise. (b) Die Basisfunktionen ändern ihre Gestalt, wenn man zu nichtuniformen Knotenvektoren übergeht. Schreiben Sie für den Knotenvektor (0, 0.5, 0.5, 0.75, 1) die quadratischen Basisfunktionen eines BSpline auf. Aufgabe 7.2 Verfeinerungseigenschaft Beweisen Sie die Verfeinerungseigenschaft für Basisfunktionen der B-Splines, wobei Sie die Distributivität, den Time shift und die Skalierbarkeit 7.4. ÜBUNGSAUFGABEN 145 Abbildung 7.19. Oben ist eine Fläche mit dem Subdivisionverfahren nach Loop dargestellt, unten im Vergleich dazu die Erweiterungen mit den Arbeiten von Hoppe et al. [HDD+ 94]. f ∗ (g + h) (t) = f ∗ g (t) + f ∗ h (t) f (t − i) ∗ g(t − k) = f ∗ g (t − i − k) 1 (f ∗ g) (2t) f (2t) ∗ g(2t) = 2 Distributiviität Time shift Skalierbarkeit des Faltungsprodukts ausnutzen. Benutzen Sie dazu, dass sich die charakteristische Funktion einfach aus zwei skalierten und verschobenen Kopien erzeugen lässt B0 (t) = B0 (2t) + B0 (2t − 1) und zeigen Sie zunächst 2 1 X 2 B1 (t) = B0 ∗ B0 (t) = 1 B1 (2t − k). 2 k=0 k Zeigen Sie jetzt, dass die allgemeine Verfeinerungsgleichung n+1 1 X n+1 Bn (t) = n Bn (2t − k) 2 k=0 k aus (x + y) n+1 n+1 X n + 1 n+1−k k = x y k k=0 146 KAPITEL 7. SPLINES mit x = B0 (2t) und y = B0 (2t − 1) folgt, da Bn die (n + 1)fach wiederholte Faltung von B0 (mit sich selbst) ist. Aufgabe 7.3 NURBS in OpenGL Stellen Sie eine NURBS Fläche wie in Abb. 7.9 in OpenGL dar, wobei Sie das Kontrollgitter aus 36 Punkten ebenfalls als durchsichtige Zellen zeichnen. (a) Verändern Sie den Knotenvektor so, dass die Randpunkte alle interpoliert werden. (b) Schneiden Sie ein dreieckiges und ein herzförmiges Loch in diese Fläche. (c) Zeichnen Sie eine zu dieser Fläche verschobene Fläche, bei der Sie die Kontrollpunkte so verändert haben, dass eine unberandete (d.h. geschlossene) Fläche, beispielsweise ein Torus entsteht. (d) Bei einem Torus durchläuft man die Kontrollpunkte der gegenüberliegenden Ränder eines quadratischen Gitters in gleicher Orientierung. Für die Darstellung einer Kleinschen Flasche wird die Orientierung einer Kante gerade umgedreht. Im dreidimensionalen Raum kann diese zweidimensionale Fläche nicht ohne Selbsdurchdringung eingebettet werden. Verändern Sie die Kontrollpunkte entsprechend, um eine Kleinsche Flasche darzustellen. Abbildung 7.20. Links ist ein Einheitsquadrat und die Orientierung der Kanten gezeichnet, wodurch sich bei entsprechender Deformation rechts die Kleinsche Flasche ergibt. Literaturverzeichnis [Bli77] B LINN , JAMES F.: Models of Light Reflection for Computer Synthesized Pictures. Computer Graphics, 11, 1977. [CC78] C ATMULL , E. und J. C LARK: Recursively generated B-Spline surfaces on arbitrary topological meshes. Computer Aided Design, 10:350–355, 1978. [CCWG88] C OHEN , M. F., S. E. C HEN, J. R. WALLACE und D. P. G REENBERG: A Progressive Refinement Approach to Fast Radiosity Image Generation. Proceedings of SIGGRAPH 88, Seiten 75–84, 1988. [CG88] C OHEN , M. F. und D. P. G REENBERG: The Hemi-Cube: A Radiosity Solution for Complex Environments. Proceedings of SIGGRAPH 85, Seiten 31–40, 1988. [Coo84] C OOK , ROBERT L.: Shade Trees. Computer Graphics, 18:223–231, 1984. [CT82] C OOK , ROBERT L. und K ENNETH E. T ORRANCE: A reflectance model for computer graphics. ACM Transaction on Graphics, 1:7–24, 1982. [CW93] C OHEN , M. F. und J. R. WALLACE: Radiosity and realistic image synthesis. Morgan Kaufmann, San Francisco, 1993. [DKT98] D E ROSE , T., M. K ASS und T. T RUONG: Subdivision Surfaces in Character Animation. Proceedings of the 25th annual conference on Computer graphics and interactive techniques, Seiten 85–94, 1998. [DS78] D OO , D. und M. S ABIN: Analysis of the behaviour of recursive division surfaces. Computer Aided Design, 10:356–360, 1978. [FK03] F ERNANDO , R ANDIMA und M ARK J. K ILGARD: The Cg Tutorial. Addison-Wesley, 2003. [GGSC98] G OOCH , A MY, B RUCE G OOCH, P ETER S HIRLEY und E LAINE C OHEN: A NonPhotorealistic Lighting Model For Automatic Technical Illustration. SIGGRAPH, 1998. [GKM93] G REENE , N., M. K ASS und G. M ILLER: Hierarchical Z-buffer visibility. Computer Graphics (SIGGRAPH ’93 Proceedings), 27:231–238, 1993. 147 148 LITERATURVERZEICHNIS [GTGB84] G ORAL , C. M., K. E. T ORRANCE, D. P. G REENBERG und G. BATTAILE: Modeling the Interaction of Light Between Diffuse Surfaces. Proceedings of SIGGRAPH 84, Seiten 213–222, 1984. [HDD+ 94] H OPPE , H., T. D E ROSE, T. D UCHAMP, M. H ALSTEAD, H. J IN, J. M C D ONALD, J. S CHWEITZER und W. S TUETZLE: Piecewise Smooth Surface Reconstruction. SIGGRAPH, Seiten 295–302, 1994. [JCS01] J ENSEN , H. W., P. H. C HRISTENSEN und F. S UYKENS: A Practical Guide to Global Illumination using Photon Mapping. SIGGRAPH 2001 Course 38, 2001. [Lac95] L ACROUTE , P H . G.: Fast Volume Rendering Using a Shear-Warp Factorization of the Viewing Transformation. Stanford University, CA, Technical Report: CSL-TR-95-678, 1995. [Mea82] M EAGHER , D. J.: Efficient synthetc image generation of arbitrary 3-D objects. Proceeding of the IEEE Conference on Pattern Recognition and Image Processing, Seiten 473–478, 1982. [Rad99] R ADEMACHER , PAUL: View-Dependent Geometry. Computer Graphics Proceedings, Annual Conference Series, 1999. [RK00] R ÖSSEL , C HRISTIAN und L EIF KOBBELT: Line-art Rendering of 3D-Models. Computer Graphics and Applications, Seiten 87 – 96, 2000. [SP94] S ILLION , F RANÇOIS X. und C LAUDE P UECH: Radiosty and Global Illumination. Morgan Kaufmann Publishers, 1994. [SWW+ 04] S CHMITTLER , J ÖRG, S VEN W OOP, DANIEL WAGNER, W OLFGANG J. PAUL und P HILIPP S LUSALLEK: Realtime Ray Tracing of Dynamic Scenes on an FPGA Chip. Proceedings of Graphics Hardware 2004, August 28th-29th, 2004. [ZSD+ 00] Z ORIN , D., P. S CHR ÖDER, T. D E ROSE, L. KOBBELT, A. L EVIN und W. S WELDENS: Subdivision for Modeling and Animation. SIGGRAPH 2000 Course Notes, 2000.