11.03.2014 Aufrufe

Vorlesungsskript Computergraphik II - IWR

Vorlesungsskript Computergraphik II - IWR

Vorlesungsskript Computergraphik II - IWR

MEHR ANZEIGEN
WENIGER ANZEIGEN

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.

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!