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