Skript, entstanden im Rahmen des Pro-Seminars

Transcription

Skript, entstanden im Rahmen des Pro-Seminars
Pro-Seminar Computergrafik
Christopher Keiner, Kai Lawonn, Tobias Pfeiffer, Jacqueline Spexard,
Christoph Sackl, Jonas Fehr, Selimkhan Achmerzaev
Betreuer:
Dr. Ingrid Hotz, Cornelia Auer, Jan Reininghaus, Andrea Kratz
Berlin, 18. Januar 2008
Inhaltsverzeichnis
1
Raster-Algorithmen am Beispiel der digitalen Typografie
6
1.1
Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
1.2
Ausgabegeräte . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
1.2.1
Klassifizierung . . . . . . . . . . . . . . . . . . . . . . .
8
1.2.2
Framebuffer . . . . . . . . . . . . . . . . . . . . . . . . .
9
1.3
Fitting-Algorithmen . . . . . . . . . . . . . . . . . . . . . . . . .
10
1.4
Liniensegment-Rasterung . . . . . . . . . . . . . . . . . . . . . .
10
1.4.1
Bresenham Algorithmus . . . . . . . . . . . . . . . . . .
11
1.4.2
Symmetric Double Step Algorithmus von Wu . . . . . . .
14
Füll-Algorithmen . . . . . . . . . . . . . . . . . . . . . . . . . .
15
1.5.1
Boundary Fill-Algorithmus . . . . . . . . . . . . . . . . .
15
1.5.2
Flood Fill-Algorithmus . . . . . . . . . . . . . . . . . . .
16
Polygon-Rasterung . . . . . . . . . . . . . . . . . . . . . . . . .
16
1.6.1
Charakterisierung von Polygonen . . . . . . . . . . . . .
16
1.6.2
Scan Line-Algorithmus . . . . . . . . . . . . . . . . . . .
17
Transformation eines Bildes . . . . . . . . . . . . . . . . . . . .
18
1.7.1
Skalierung . . . . . . . . . . . . . . . . . . . . . . . . .
19
1.7.2
Rotation . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
Dithering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
1.8.1
Farbrepräsentation . . . . . . . . . . . . . . . . . . . . .
23
1.8.2
Color Look Up Table . . . . . . . . . . . . . . . . . . . .
23
1.8.3
Ordered Dithering mit Fehlerstreuung . . . . . . . . . . .
23
Aliasing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
1.9.1
Objektbasiertes Anti-Aliasing . . . . . . . . . . . . . . .
25
1.9.2
Subpixel Rendering . . . . . . . . . . . . . . . . . . . . .
26
1.5
1.6
1.7
1.8
1.9
1
INHALTSVERZEICHNIS
2
Shading
29
2.1
Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
2.2
Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
2.2.1
Lichtausbreitung . . . . . . . . . . . . . . . . . . . . . .
30
2.2.2
Lichtquellenmodelle . . . . . . . . . . . . . . . . . . . .
33
Lokale Beleuchtungsmodelle . . . . . . . . . . . . . . . . . . . .
34
2.3.1
Lambert-Beleuchtungsmodell . . . . . . . . . . . . . . .
34
2.3.2
Phong-Beleuchtungsmodell . . . . . . . . . . . . . . . .
34
Schattierungsverfahren . . . . . . . . . . . . . . . . . . . . . . .
35
2.4.1
Flat-Shading . . . . . . . . . . . . . . . . . . . . . . . .
35
2.4.2
Gouraud-Shading . . . . . . . . . . . . . . . . . . . . . .
37
2.4.3
Phong-Shading . . . . . . . . . . . . . . . . . . . . . . .
41
2.4.4
Berechnung . . . . . . . . . . . . . . . . . . . . . . . . .
43
2.4.5
Zusammenfassung . . . . . . . . . . . . . . . . . . . . .
44
Cool-to-Warm Shading . . . . . . . . . . . . . . . . . . . . . . .
45
2.5.1
Berechnung . . . . . . . . . . . . . . . . . . . . . . . . .
45
2.5.2
Zusammenfassung . . . . . . . . . . . . . . . . . . . . .
47
Diskussion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
47
2.6.1
Geschichte des Lichtes . . . . . . . . . . . . . . . . . . .
47
2.6.2
Problematik . . . . . . . . . . . . . . . . . . . . . . . . .
48
2.6.3
Warum nicht physikalisch exakt? . . . . . . . . . . . . .
48
2.6.4
Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . .
49
Anhang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
49
2.7.1
Vektoren . . . . . . . . . . . . . . . . . . . . . . . . . .
49
2.7.2
Farbwerte . . . . . . . . . . . . . . . . . . . . . . . . . .
50
2.7.3
Baryzentrische Koordinaten . . . . . . . . . . . . . . . .
51
2.3
2.4
2.5
2.6
2.7
3
2
Raytracing
53
3.1
Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
3.2
Grundlagen des Renderings . . . . . . . . . . . . . . . . . . . . .
53
3.3
Das Raytracing-Verfahren . . . . . . . . . . . . . . . . . . . . .
55
3.3.1
Schnittpunkt- und Normalenbestimmung . . . . . . . . .
56
3.3.2
Farbbestimmung eines Punktes . . . . . . . . . . . . . . .
59
Laufzeitbetrachtungen und Optimierung . . . . . . . . . . . . . .
67
3.4.1
Analyse der Laufzeit . . . . . . . . . . . . . . . . . . . .
67
3.4.2
Verbesserungen der Laufzeit . . . . . . . . . . . . . . . .
67
3.4
2
INHALTSVERZEICHNIS
3.5
4
Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
70
Geometric Modelling: Approximation und Interpolation von Kurven
und Flächen. Von Flächen zu Objekten
72
4.1
Bezierkurven . . . . . . . . . . . . . . . . . . . . . . . . . . . .
72
4.1.1
Renault auf dem Vormarsch . . . . . . . . . . . . . . . .
72
4.1.2
Wie entstehen Bezierkurven? . . . . . . . . . . . . . . . .
73
4.1.3
Nachteile der Bezierkurven . . . . . . . . . . . . . . . . .
78
B-Splines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
79
4.2.1
Mit Schiffen fing alles an . . . . . . . . . . . . . . . . . .
79
4.2.2
Definition von B-Splines . . . . . . . . . . . . . . . . . .
79
4.2.3
Uniform-B-Splines . . . . . . . . . . . . . . . . . . . . .
80
4.2.4
Non-uniform B-Splines . . . . . . . . . . . . . . . . . . .
82
4.2.5
Zusammengefasst . . . . . . . . . . . . . . . . . . . . . .
85
4.3
NURBS (non-uniform rational B-Splines) . . . . . . . . . . . . .
86
4.4
Von Kurven zu Flächen . . . . . . . . . . . . . . . . . . . . . . .
87
4.4.1
Biliniar Patches . . . . . . . . . . . . . . . . . . . . . . .
87
4.4.2
Bilinearly Blended Surfaces . . . . . . . . . . . . . . . .
90
Von Flächen zu Objekten . . . . . . . . . . . . . . . . . . . . . .
91
4.2
4.5
5
3
Grafikkarten und GPU-Programmierung
92
5.1
Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
92
5.2
Die Grafikkarte . . . . . . . . . . . . . . . . . . . . . . . . . . .
93
5.2.1
Entwicklung der Grafikkarte . . . . . . . . . . . . . . . .
93
5.2.2
Eine moderne Highend-Grafikkarte . . . . . . . . . . . .
94
5.3
Grafik-Programmierung . . . . . . . . . . . . . . . . . . . . . . .
96
5.4
Koordinatensysteme . . . . . . . . . . . . . . . . . . . . . . . . .
97
5.4.1
Object Space . . . . . . . . . . . . . . . . . . . . . . . .
97
5.4.2
World Space und Eye Space . . . . . . . . . . . . . . . .
97
5.4.3
Clip Space . . . . . . . . . . . . . . . . . . . . . . . . .
98
5.4.4
Window Space . . . . . . . . . . . . . . . . . . . . . . .
99
Die klassische Grafik-Pipeline . . . . . . . . . . . . . . . . . . .
99
5.5
5.6
5.5.1
Geometrieoperationen . . . . . . . . . . . . . . . . . . . 100
5.5.2
Pixeloperationen . . . . . . . . . . . . . . . . . . . . . . 102
Die Unified-Shader Architektur . . . . . . . . . . . . . . . . . . . 103
5.6.1
Das Shader Model . . . . . . . . . . . . . . . . . . . . . 105
5.6.2
Shader Programmierung . . . . . . . . . . . . . . . . . . 106
3
INHALTSVERZEICHNIS
5.7
5.8
6
4
5.6.3
Vertex- und Fragment-Shader . . . . . . . . . . . . . . . 107
5.6.4
Geometry-Shader . . . . . . . . . . . . . . . . . . . . . . 109
General Purpose Computation on GPUs . . . . . . . . . . . . . . 110
5.7.1
Nutzung des skalaren Prozessor Designs . . . . . . . . . . 111
5.7.2
GPGPU in der Praxis . . . . . . . . . . . . . . . . . . . . 112
5.7.3
Compute Unified Device Architecture . . . . . . . . . . . 113
5.7.4
Diskussion . . . . . . . . . . . . . . . . . . . . . . . . . 114
Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Computer Animation
6.1
6.2
116
Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
6.1.1
Was ist Animation? . . . . . . . . . . . . . . . . . . . . . 116
6.1.2
Klassische Animationstechniken . . . . . . . . . . . . . . 116
Computer Animation - Einleitung zur 3D-Animation . . . . . . . 118
6.2.1
Rigid Body Animation . . . . . . . . . . . . . . . . . . . 119
6.3
Key-Framing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
6.4
Interpolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
6.4.1
Interpolation von parametrischen Kurven . . . . . . . . . 123
6.4.2
Dynamik von Bewegungen . . . . . . . . . . . . . . . . . 125
6.5
Animations-Zyklen . . . . . . . . . . . . . . . . . . . . . . . . . 126
6.6
Hierarchische Modelle und Kinematik . . . . . . . . . . . . . . . 127
6.7
Charakter Animation mit Skelett-Modell . . . . . . . . . . . . . . 131
6.8
Kollisions-Erkennung . . . . . . . . . . . . . . . . . . . . . . . . 132
6.9
Deformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
6.9.1
Globale Deformation . . . . . . . . . . . . . . . . . . . . 134
6.9.2
Free Form Deformation . . . . . . . . . . . . . . . . . . 135
6.9.3
Animierte Deformation . . . . . . . . . . . . . . . . . . . 136
6.10 Gesichts-Animation . . . . . . . . . . . . . . . . . . . . . . . . . 136
7
Image-Based Rendering
138
7.1
Einleitung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
7.2
Light Field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
7.3
7.2.1
Sampling . . . . . . . . . . . . . . . . . . . . . . . . . . 141
7.2.2
Technische Probleme . . . . . . . . . . . . . . . . . . . . 142
7.2.3
Resampling / Erzeugen von neuen Bildern . . . . . . . . . 143
7.2.4
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . 143
View Interpolation . . . . . . . . . . . . . . . . . . . . . . . . . 144
4
INHALTSVERZEICHNIS
7.4
5
7.3.1
Pixel Interpolation . . . . . . . . . . . . . . . . . . . . . 145
7.3.2
Probleme . . . . . . . . . . . . . . . . . . . . . . . . . . 146
7.3.3
Lösung . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
7.3.4
Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . 147
7.3.5
Beipiel aus der Filmindustrie . . . . . . . . . . . . . . . . 148
7.3.6
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . 148
Image Based Lighting mit High Dynamic Range Images . . . . . 149
7.4.1
Light Probes . . . . . . . . . . . . . . . . . . . . . . . . 152
7.4.2
Environment Mapping . . . . . . . . . . . . . . . . . . . 153
7.4.3
Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . 154
7.4.4
Einsatz von IBL in der Industrie . . . . . . . . . . . . . . 155
7.4.5
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . 156
Literaturverzeichnis
156
5
Kapitel 1
Raster-Algorithmen am Beispiel
der digitalen Typografie
Christopher Keiner
1.1
Einleitung
Die Ausarbeitung thematisiert Raster-Algorithmen am Beispiel der digitalen
Typografie. Die Rasterung ist ein Teilgebiet der Computergrafik und betrifft den
Bereich der Grafikausgabe. Viele Ausgabegeräte benutzen als Grundelemente
Pixel, die einen farbigen Bildpunkt repräsentieren. Ein Pixel muss aus technischen
Gegebenheiten eine spezifische Größe besitzen. Die Ausgabefläche besteht aus
einer Menge dieser Pixel und kann wegen der spezifischen Größe der Pixel als
Raster aufgefasst werden. Dies ist das Grundproblem der Rasterung.
Das Gebiet der Rasterung bietet Lösungsansätze für Probleme, die durch das
Arbeiten auf diesem Raster entstehen um eine Grafik auszugeben. Die Ausarbeitung
beschreibt verschiedene Probleme des Rasterns und zeigt mögliche Lösungsansätze
zu den Problemen. Dabei orientiert sich die Ausarbeitung an einem Beispiel aus der
digitalen Typografie.
Typografie umfasst Richtlinien und Regeln, die bei der Gestaltung von Texten
relevant sind. Diese Richtlinien umfassen z.B. die Schrifttypen, die Schriftgröße
oder Zeichenabstände. Die Typografie beinhaltet aber auch die Wahl des Papieres
oder die Gewohnheiten eines Lesers. Um diese Weitläufigkeit einzuschränken,
6
1.1. EINLEITUNG
7
unterteilt sich die Typografie in eine mikro- und eine makrotypografische Sicht.
Die Makrotypografie konzentriert sich auf die Gestaltung des Textes als große
Einheit. Die Mikrotypografie beschränkt sich hingegen auf die Gestaltung einzelner
Zeichen und Worte. Die Richtlinien gelten ebenfalls für digitale Texte. Das Ziel
der Typografie ist dabei eine optimale Lesbarkeit sowie Gestaltung eines Textes zu
erreichen.
Die Mikrotypografie und das Gebiet der Rasterung sind bei digitalen Texten eng
verbunden. Die Lesbarkeit und Gestaltung ist dabei in erster Linie von der Qualität
der Rasterung abhängig. Die Erzeugung von Zeichen wird im Computerbereich
durch einen sog. Font-Rasterizer realisiert. Die zu rasternden Zeichen werden
in diesem Zusammenhang als Glyphen bezeichnet. Die Aufgaben und Abläufe
eines Font-Rasterizers werden nun exemplarisch anhand des TrueType-Rasterizers
[Mic07] kurz vorgestellt. Die Hauptaufgabe besteht darin einen übergebenen String
in ein Bitmap umzuwandeln. Dazu sind die folgenden Schritte notwendig:
1. Die Umrisse des Glyphen werden aus dem TrueType Format ausgelesen.
Die Umrisse werden als Gleichungen von Liniensegmenten und Splines
gespeichert.
2. Im nächsten Schritt werden die Umrisse auf die gewünschte Größe skaliert.
Hierfür werden die Linien und Splines durch die mathematischen Gleichungen transformiert.
3. Die Umrisse müssen als nächstes am Raster ausgerichtet werden um eine optimale Qualität zu erreichen. Um dies zu erreichen kann ein Glyph verschoben
und gestreckt werden.
4. Im letzten Schritt wird der Buchstabe als Bitmap gerastert.
Die Ausarbeitung unterteilt sich in vier Themengebiete und ordnet die Themen
möglichen Aufgaben eines Font-Rasterizers zu. Das erste Themengebiet umfasst
Abschnitt 1.2 und stellt mögliche Ausgabegeräte vor. Es wird der Framebuffer
vorgestellt, der eine Abstraktion dieser Ausgabegeräte darstellt.
Das zweite Themengebiet befasst sich mit dem sogenannten Fitting-Problem, bei
dem eine optimale Ausrichtung eines Objekts an das Raster gefunden werden muss.
Abschnitt 1.3 stellt eine Lösung vor, die das TrueType Format benutzt.
Das dritte Themengebiet beschäftigt sich mit dem Rastern von geometrischen Figuren. Die Abschnitte 1.4, 1.5, 1.6 stellen Algorithmen vor, die zum Rastern von
7
1.2. AUSGABEGERÄTE
8
Objekten benutzt werden können und korrespondiert mit dem vierten Schritt des
TrueType Rasterizers.
Das letzte Themengebiet umfasst die Abschnitte 1.7, 1.8, 1.9 und stellt Optimierungsansätze beim Rastern vor. Abschnitt 1.7 bietet auch Ansätze zur Transformation von Koordinaten, die im zweiten Schritt des TrueType-Rasterizers benötigt
werden.
1.2
Ausgabegeräte
In diesem Abschnitt werden verschiedene Ausgabegeräte vorgestellt. Um das Problem des Rasterns allgemeiner betrachten zu können, werden die Ausgabegeräte
klassifiziert und anschließend durch den sogenannten Framebuffer abstrahiert.
1.2.1
Klassifizierung
Eine Vielzahl von physikalischen/virtuellen Geräten kann als Ausgabegerät dienen:
• Monitor (CRT, LCD)
• Drucker, Pen Plotter
• Beamer, Laser-Projektoren
• Fernsehgeräte
• Ausgabe als digitales Bild
• ...
Die Geräte lassen sich in zwei Klassen unterteilen, um generellere Aussagen
über Ausgabegeräte zu finden.
1. Vektorbasierte Geräte
Die Ausgabedaten dieser Geräteklasse liegen als Befehlsfolge vor. Durch
die Abarbeitung der Befehle entsteht die Ausgabe. In diese Klasse fallen z.B
Oszilloskope, Pen-Plotter oder Laserprojektoren. Der Befehlsvorrat umfasst
meist verschiedene Bewegungsvorgänge, sowie das Aktivieren/Deaktivieren
des Ausgabemechanismus.
8
1.2. AUSGABEGERÄTE
9
2. Pixelorientierte Geräte
Die Ausgabedaten liegen in dieser Geräteklasse als Datenfolge aus Pixeln
vor. Diese Daten beinhalten die Koordinaten und die Farbe an dieser Stelle.
Im Gegensatz zu vektorbasierten Geräten werden die Daten sequentiell in
einer festgelegten Reihenfolge sichtbar gemacht. In diese Klasse fallen z.B.
Monitore, Beamer oder Bilder.
Die Klasse der vektorbasierten Geräte umgeht im Gegensatz zu den pixelorientierten Geräten das Problem des Rasterns. Die Anzahl der vektorbasierten Geräte ist
aber sehr gering. Geräte für den Normalbenutzer fallen in die pixelorientierte Klasse.
Aus diesem Grund wird im Folgenden nur auf die Klasse der pixelorientierten
Geräte eingegangen.
1.2.2
Framebuffer
Es bestehen viele Gemeinsamkeiten der pixelorientierten Geräte.
• Die Ausgabefläche besteht aus einer Menge von angeordneten, adressierbaren
Pixel.
• Die Auflösung (width × height) eines Gerätes spezifiert die Anzahl der
Pixel und die Größe der Ausgabefläche.
• Die Farbtiefe spezifiziert die Bitanzahl, die für die Speicherung einer Farbe
verwendet werden. Die Farbtiefe gibt ebenfalls die Anzahl an Farben an, die
angezeigt oder gespeichert werden können.
Die Abstraktion eines Gerätes ist durch den Framebuffer gegeben. Der
Framebuffer besteht aus einem Speicherbereich für width × height Pixeln.
Diese Pixel lassen sich gezielt manipulieren. Dazu werden Operationen zum
Erfragen und Setzen der Farbe angeboten.
Der Framebuffer dient als Schnittstelle zwischen Algorithmen und Ausgabegerät, welches die Daten aus dem Framebuffer anzeigen kann. Das Raster-Problem
kann nun losgelöst von den Ausgabegeräten betrachtet werden. Abschnitt 1.8 thematisiert später ein Problem, dass durch diese Loslösung entstehen kann. Das Problem
entsteht, wenn eine Reduzierung der Farbanzahl zur Ausgabe auf dem Ausgabegerät
notwendig ist.
9
1.3. FITTING-ALGORITHMEN
1.3
10
Fitting-Algorithmen
Durch einen Fitting-Algorithmus findet eine Optimierung vor dem eigentlichen
Rastern statt. Dabei wird das zu rasternde Objekt am Raster des Framebuffers
ausgerichtet. Ziel des Algorithmus ist es, eine optimale Überdeckung zwischen
den Punkten des Rasters und dem Objekt zu finden. Es ist wichtig, möglichst viele
Punkte des Objekts in das Raster zu übertragen, da ansonsten das gerasterte Objekt
stark von der Vorlage abweicht.
Am Beispiel der Typografie wird durch eine schlechte Überdeckung der Glyph
verzerrt und das Lesen wird dadurch erschwert.
Deshalb versucht die Typografie durch das Setzen von Glyphen die Lesbarkeit eines
Textes zu verbessert. Beispielsweise werden Buchstaben in bestimmten Situationen
enger zusammen oder weiter auseinander gesetzt. Ein Beispiel hier für ist die
Verwendung von Ligaturen oder das Vermeiden von Glyphenkollisionen. Die Ziele
der Typografie und des Rasterns können im Gegensatz zueinander stehen. Es ist ein
Kompromis nötig um eine gute Lesbarkeit zu gewähren.
Eine Ausrichtung am Raster ist durch mathematische Berechnungen mit Hilfe einer
sog. Fehlermatrix möglich. Das richtige Setzen von Glyphen hingegen ist schwierig,
da durch zahlreiche unterschiedliche Situationen eine große Komplexität erreicht
wird. Das TrueType-Format nutzt die Erfahrung und Intelligenz des Typographen.
Der Gestalter einer Schriftart gibt explizit bei der Erstellung der Schrift Abstände
von Glyphen an. Die Abstände können bei der Rasterung genutzt werden, um eine
gute Qualität des Glyphen zu erreichen.
1.4
Liniensegment-Rasterung
Punkte, Liniensegmente und Polygone bilden die Primitive der Computergrafik.
Diese bilden die Grundlage für komplexere Modelle und Anwendungen. Jede
mögliche geometrische Struktur kann in Punkte, Linien und Polygone zerlegt
werden. Daher ist es wichtig diese Elemente möglichst effizient zu rastern. Meistens
wird das Rastern von Primitiven durch Hardware unterstützt, die aber wiederum
auf einem Algorithmus basiert. In diesem Abschnitt werden zwei Algorithmen
zum Rastern von Liniensegmenten vorgestellt. Der Bresenham-Algorithmus ist
ein bekannter Line-Drawing-Algorithmus, der in vielen Bereichen Anwendung
findet. Der Symmetric Double Step Algorithmus soll die effiziente Ausutzung von
Symmetrien zeigen.
10
1.4. LINIENSEGMENT-RASTERUNG
11
In der Einleitung wurde erläutert, dass die Umrisse aus Liniensegmenten und
Splines gespeichert werden. Ein Aufgabenfeld der folgenden Algorithmen ist diese
Umrisse eines Textes darzustellen. Auf die Verarbeitung von Splines wird nicht
weiter eingegangen. Eine Spline-Kurve kann durch Linien approximiert werden.
Somit ist es denkbar, einen Glyphen nur mit den folgenden Algorithmen zu rastern.
1.4.1
Bresenham Algorithmus
Der Bresenham Algorithmus ist 1965 vom gleichnamigen Programmierer entwickelt
worden. Bei der Entwicklung hat die Effizenz eine hohe Priorität eingenommen.
Der Algorithmus arbeitet ausschließlich mit schnellen Integer Berechnungen und
vermeidet hierbei ebenfalls weitgehend die Multiplikation und die Division.
Zu Beginn soll ein allgemeines Verfahren vorgestellt werden, mit dem eine Linie gerastert werden kann. Aufbauend auf diesem Verfahren soll der BresenhamAlgorithmus erläutert werden.
Allgemeine Arbeitsweise und Sampling
Dieser Abschnitt stellt das allgemeine Vorgehen des Linien-Rasterns vor und wird
ein allgemeines Problem aufzeigen, dass in anderen Algorithmen ebenfalls entsteht.
Es wird vorausgesetzt, dass ein Liniensegment durch einen Anfangspunkt (x1 , y1 )
und einen Endpunkt (x2 , y2 ) gegeben ist. In mathematischer Sicht kann jeder Punkt,
der auf der Linie liegt durch die Gleichung
y = m · x + b mit m =
y2 − y1
∆x
=
und b = y1 − m · x1
x2 − x1
∆y
bestimmt werden. Im nächsten Schritt muss die Linie aus dem kartesischen
Koordinatensystem der Mathematik auf die Koordinaten des Pixelbereichs
übertragen werden. Ein Pixel besitzt im Gegensatz zum mathematischen Punkt
eine spezifische Größe. Daraus folgt, dass ein Pixel einem Intervall der Linie
zugeordnet ist. Es muss also für jede Pixelkoordinate stichprobenartig ein Wert
zugeordnet werden. Dieser Prozess wird als Sampling bezeichnet und kann durch
unterschiedliche Verfahren verbessert werden. Zur naiven Lösung genügt es zu
jeder gegebenen x-Koordinate durch die Gleichung einen gerundeten Wert y zu
berechnen. Jede Berechnung erfordert die Auswertung der Geradengleichung. Der
Bresenham-Algorithmus umgeht dies, indem die nachfolgende Koordinate aus der
11
1.4. LINIENSEGMENT-RASTERUNG
12
Vorigen berechnet wird.
Die y-Koordinaten lassen sich durch eine rekursive Gleichung beschreiben, in
der die k+1-Koordinate durch Addieren der Steigung berechnet wird.
0
yk+1
= yk0 + m und y10 = y1
Abbildung 1.1: Line Rastering. Links wurde über x-Koordinate iteriert. Rechts wurde über
die y-Koordinate iteriert.
Eine Lösung des Linienrasterns besteht darin iterativ die Koordinaten (x1 , y10 ),
..., (xn , yn0 ) zu berechnen. Das Resultat (siehe Abb. 1.1) ist aber nicht befriedigend,
da für eine Steigung m > 1 nicht genügend Sampling-Punkte vorhanden sind. Das
Problem lässt sich beheben, indem für eine Steigung m > 1 über die y-Koordinate
iteriert wird. Das Problem entsteht auch in anderen Zusammenhängen und wird im
Folgenden nicht mehr explizit beschrieben. Ein Beispiel ist das später beschriebene
Rastern von Polygonen.
Vorgehen des Bresenham-Algorithmus
Der Bresenham-Algorithmus baut auf dem obigen Konzept auf. Floating-PointWerte z.B. die Steigung m werden aus Effizienzgründen innerhalb der Iteration
elimiert. Eine Fallunterscheidung über den Wert von m ist dazu essentiell.
Exemplarisch wird die Idee des Bresenham-Algorithmus ausgehenden vom
Startpunkt oder einem bereits berechnetem Punkt (xk , yk ) für 0 < m < 1
besprochen.
Durch die Einschränkung der Steigung können für den Folgepunkt nur die Punkte
12
1.4. LINIENSEGMENT-RASTERUNG
13
(xk+1 , yk ) oder (xk+1 , yk + 1) in Frage kommen.
Im Folgenden soll die Frage beantwortet werden, wie effizient entschieden
werden kann, welcher Punkt der Orginal-Linie am nächsten liegt.
d2
?
?
d1
Abbildung 1.2: Bresenham Algorithmus: Für den nächsten Pixel stehen zwei Folgepixel
zur Wahl. Durch den Vergleich der Abstände d1 und d2 wird entschieden, welcher Punkt am
nächsten zur Linie liegt.
Dazu werden die Abstände zwischen Punkt und Linie berechnet und deren
Differenz gebildet. Das Ziel wird sein, am Vorzeichen der Differenz d1 − d2 (siehe
Abb. 1.2) abzulesen, welcher Punkt näher an der Linie liegt.
Dazu wird ein rekursives Prädikat benötigt, dass während der Iteration aktualisiert werden kann. [HB97]
(
pk+1 =
pk + 2∆y
für pk < 0
pk + 2∆y − 2∆x
für pk ≥ 0
und p0 = 2∆y − ∆x
Aus dem Prädikat pk kann die Entscheidung getroffen werden, welcher Pixel
gerastert werden soll. Im Fall pk < 0 wird der untere Pixel gerastert. Der obere
Pixel wird gerastert, wenn die Bedingung pk ≥ 0 erfüllt ist.
Die Steigung 1 < m < ∞ kann nach dem gleichen Prinzip gerastert werden,
indem die Iteration über die y-Koordinate erfolgt. Somit lassen sich alle Linien im
ersten Quadranten des kartesischen Koordinatensystems rastern.
Steigungen außerhalb dieses Bereichs können durch eine Vertauschung der
13
1.4. LINIENSEGMENT-RASTERUNG
14
Endpunkte, sowie durch die Ausnutzung der Symmetrie zur x-Achse auf das obige
Problem zurückgeführt werden.
1.4.2
Symmetric Double Step Algorithmus von Wu
In diesem Abschnitt wird ein weiterer Algorithmus zum Linien-Rastern vorgestellt.
Der Double Step Algorithmus nutzt die gegebene Symmetrie einer Linie aus. Der
Schwerpunkt der Betrachtung liegt auf diesem Vorgehen.
Der Algorithmus basiert auf der Idee, dass ein Liniensegment auf Grund der
Rasterung nur bestimmte Muster annehmen kann. Für eine Steigung 0 ≤ m ≤ 1
und einem Pixelabschnitt, der Länge 3, können nur die 4 Muster aus Abb. 1.3 in
Frage kommen.
Muster 1
Muster 2
Muster 3
Muster 4
Abbildung 1.3: Double Step Algorithmus: 4 mögliche Muster.
Die Steigung einer Linie ist konstant. Somit kann im Vorfeld eine weitere
Unterscheidung vorgenommen werden.
0 ≤ m ≤ 12 : Für diese Steigung kann Muster 4 ausgeschloßen werden.
1
2
≤ m ≤ 1: Für diese Steigung kann Muster 1 ausgeschloßen werden.
Es wird an dieser Stelle ebenfalls ein Prädikat gebraucht, das zwischen den drei
verbleibenden Mustern wählt. Im Vergleich zum Bresenham-Algorithmus werden
durch ein effizientes Prädikat mit einer Prädikatauswertung zwei Pixel gerastert.
Der entscheidende Effizienzunterschied gegenüber dem Bresenham-Algorithmus
wird durch die Ausnutzung der Symmetrie erreicht. Jedes Liniensegment ist
zum Mittelpunkt drehsymmetrisch. Der Double Step Algorithmus rastert aus diesem Grund am gegenüberliegenden Endpunkt jeweils das symmetrische Gegenstück.
14
1.5. FÜLL-ALGORITHMEN
15
Die Ausnutzung der Symmetrie kann in vielen Fällen eine enorme Effizenzsteigerung bringen. In der Typografie sollte besonders auf die Symmetrien geachtet
werden. Neben dem Effizenzgewinn kann das symmetrische Rastern das Schriftbild
verbessern. Glyphen wirken durch das Raster nicht verzerrt und können somit die
Lesbarkeit verbessern.
1.5
Füll-Algorithmen
Im Anschluß an den letzten Abschnitt werden nun zwei Algorithmen vorgestellt,
mit denen Flächen innerhalb der gerasterten Umrisse gefüllt werden können. Eine
naive Lösung des Glyphen-Rastern könnte im Füllen der gezeichneten Umrisse
bestehen.
1.5.1
Boundary Fill-Algorithmus
Voraussetzung für diesen Algorithmus ist ein mit einer bekannten Farbe gerasterter
Umriss. Desweiteren muss ein Startpunkt innerhalb dieser Umrisse gewählt werden. Die gesamte Fläche innerhalb der Grenzen wird neu eingefärbt. Es ist keine
einheitliche Farbe der inneren Fläche vorausgesetzt.
Der Algorithmus boundary fill(x,y) arbeitet nach folgendem rekursiven
Schema:
1. Falls die Farbe des Pixels (x,y) mit der Farbe der Grenze oder mit der neuen
Farbe übereinstimmt, wird an dieser Stelle die Methode verlassen.
2. Der Pixel (x,y) wird neu gefärbt
3. Rekursiv werden die Nachbarpixel gefärbt.
boundary fill(x-1,y)
boundary fill(x+1,y)
boundary fill(x,y-1)
boundary fill(x,y+1)
Der Algorithmus kann durch rekursiven Aufruf der vier Diagonalrichtungen
erweitert werden. (Siehe Abb. 1.4)
15
1.6. POLYGON-RASTERUNG
16
Abbildung 1.4: Boundary-Fill-Algorithmus: Der Algorithmus arbeitet rekursiv auf den
anliegenden Nachbarn. Dabei können entweder vier oder alle acht Nachbarn benutzt
werden.
1.5.2
Flood Fill-Algorithmus
Der Flood-Fill Algorithmus ist eine Abwandlung des Boundary Algorithmus. Der
Vorteil besteht darin, dass die zu füllende Fläche keine Umrisse besitzen muss. Der
Algorithmus färbt stattdessen alle gleichfarbigen Pixel einer zusammenhängenden
Fläche neu ein. Die Arbeitsweise unterscheidet sich nur im Rekursionsanker, der
die Bedingung zum Abbruch der Methode darstellt.
1.6
Polygon-Rasterung
Dieser Abschnitt beschäftigt sich mit dem Rastern von Polygonen und gliedert
sich in zwei Unterabschnitte. Zu Beginn werden verschiedene Arten von Polygone
klassifiziert. Jede Klasse von Polygonen hat bestimmte Eigenschaften. Die Einteilung in Klassen kann bei der Wahl des Algorithmus ausgenutzt werden, indem
der Algorithmus die Eigenschaften des Polygons berücksichtigt und geeignet ausnutzt. Im zweiten Unterabschnitt wird ein Scan Line-Algorithmus vorgestellt, der
es ermöglicht Glyphen und Polygone zu rastern.
Ein Glyph kann ebenfalls als Polygon aufgefasst werden. Somit korresponiert dieser
Abschnitt mit den Aufgaben des vierten Schritt des Font-Rasterizers.
1.6.1
Charakterisierung von Polygonen
Ein Polygon lässt sich am einfachsten durch eine Folge von Eckpunkten beschreiben.
Die Reihenfolge dieser Punkte beschreibt, zwischen welchen Punkten eine Kante
verläuft. Abbildung 1.5 zeigt verschiedene Arten von Polygonen. Die verschiedenen
Polygone lassen sich in Klassen einteilen. Diese sind nicht disjunkt.
Eine mögliche Einteilung in verschiedene Klassen ist:
16
1.6. POLYGON-RASTERUNG
17
4
3
4
1
2
2
3
5
1
1
2
3
Abbildung 1.5: Verschiedene Polygonarten: Dreieck, nicht konvexes Polygon, konvexes
Polygon (es existiert eine Verbindunglinie, die nicht innerhalb des Polygons verläuft),
überlappendes Polygon
Das einfachste Polygon ist das Dreieck. Jede beliebige Figur kann als Menge von
Dreiecken approximiert werden. Dabei können neue Zwischenpunkte in die
Figur eingefügt werden. Die Arbeit mit Dreiecken lässt sich stark optimieren,
denn es gibt nur wenige Sonderfälle die beim Rastern eines Dreiecks auftreten
können. DirectX lässt beispielsweise als Primitive nur Punkte, Linien und
Dreiecke zu.
Zwei weitere Klassen von Polygonen werden durch die Unterteilung in konvexe
Polygone und nicht konvexe Polygone gebildet. Ein Polygon heißt konvex, falls
alle möglichen Liniensegmente, ausgehend und endend auf dem Polygonrand,
innerhalb des Polygons liegen. Ein Polygon wird als nicht-konvex bezeichnet,
falls diese Bedingung nicht erfüllt ist (siehe Abb. 1.5).
Eine weitere Eigenschaft eines Polygon ist die Überlappung und charakterisiert
eine Klasse. Ein Polygon überlappt sich immer dann, wenn der Umriss des
Polygons einen gemeinsamen Schnittpunkt besitzt.
Die Menge aller Glyphen fallen in die Klassen der konvexen und nicht konvexen
Polygone. Buchstaben sind aber nicht selbst überlappende Polygone. Der folgende
Algorithmus ist in der Lage, diese Klasse zu rastern.
1.6.2
Scan Line-Algorithmus
Ein Scan Line-Algorithmus arbeitet die Rasterung eines Polygons zeilenweise ab.
Die aktuelle Zeile wird hierbei Scan Line genannt. Als erstes werden für jede Scan
Line die Schnittpunkte mit dem Polygon berechnet. Die Schnittpunkte werden
nach x-Koordinate sortiert. Es wird an dieser Stelle zwischen dem regulären Fall
und einem Spezialfall entschieden. Im regulären Fall sind die Schnittpunkte keine
17
1.7. TRANSFORMATION EINES BILDES
18
Eckpunkte. Die Anzahl der Schnittpunkte ist gerade. Somit ist im regulären Fall an
dieser Stelle klar, welches ein Eintritts- oder Austrittspunkt aus dem Polygon ist.
Die Pixel zwischen Eintritts- und Austrittspunkt können nun gefärbt werden.
Spezialfälle müssen erkannt und behandelt werden. Ein Spezialfall lässt sich
z.B. durch die ungerade Anzahl an Schnittpunkten identifizieren. Dieser Fall tritt
auf, wenn ein Schnittpunkt ebenfalls ein Eckpunkt des Polygons ist.
Die Behandlung benötigt einen geeigneten Entscheidungsmechanismus.
? Pm ?
Abbildung 1.6: Polygon Rasterung: Im regulären Fall (links) ist klar, welche Schnittpunkte
Eintritts- oder Austrittspunkte sind. Ist ein Schnittpunkt zugleich Eckpunkt (rechts) muss
durch die Monotonie entschieden werden, ob eine Linie gerastert werden soll.
Eine einfache Lösung dieses Problems betrachtet die zwei angrenzenden Kanten
des Punktes Pm . Diese zwei Kanten werden durch Pm und zwei weiteren Eckpunkten beschrieben. Durch einen Vergleich der y-Koordinaten dieser drei Punkte kann
eine Aussage über die Monotonie der Kanten getroffen werden. Monotonie liegt
vor, wenn alle drei y-Koordinaten in abnehmender oder steigender Größe vorliegen.
Beim Vergleich ist die Reihenfolge der Eckpunkte relevant (siehe 1.6.1).
Der Eckpunkt Pm bildet einen Extrempunkt relativ zur Scan Line, genau dann wenn
keine Monotonie vorhanden ist. In diesem Fall ist Pm kein Schnittpunkt und wird
zum Rastern nicht in Betracht gezogen.
1.7
Transformation eines Bildes
In diesem Abschnitt werden zwei grundlegende Funktionen und Algorithmen zur
Transformation eines Bildes vorgestellt. Diese Algorithmen fallen ebenfalls in den
18
1.7. TRANSFORMATION EINES BILDES
19
Bereich der Rasterung, da sie auf Pixelbereichen operieren. Eine Anwendung im
typografischen Rastern liegt im Bereich der Embedded Systems. Kleine Systeme
können wegen Resourcenknappheit Glyphen als vorgerasterte Bitmaps speichern.
Damit entsteht die Notwendigkeit, einen Text aus diesen Bitmaps zusammenzustellen. Diese Schriften werden als Bitmap-Fonts bezeichnet.
In den zwei Unterabschnitten werden die Skalierung und die Rotation vorgestellt.
Die mathematischen Ansätze lassen sich auf die Koordinaten-Transformation übertragen und sind somit für den zweiten Schritt des TrueType-Rasterizers relevant.
1.7.1
Skalierung
Die Skalierung eines Bildes um (sx , sy ) lässt sich durch eine skalare Multiplikation
berechnen.
x0 = s x · x
y 0 = sy · y
Diese Gleichung lässt sich in einer Matrix darstellen, die effizient vom Computer
berechnet werden kann.
sx
0
0
sy
!
x
y
!
=
x0
!
y0
Dieser geometrischer Ansatz setzt voraus, dass jeder Pixel einzeln transformiert
wird. Die Transformation von Koordinaten ist durch die Matrixdarstellung effizient
berechenbar. Die Veränderung der Farbwerte durch die Skalierung wird aber nicht
beachtet. Der skalierte Pixelbereich kann dadurch große Farbflächen oder den
Verlust von Informationen aufweisen (siehe Abb. 1.7). Das gleiche Problem wird
im nächsten Abschnitt thematisiert.
1.7.2
Rotation
Geometrischer Ansatz
Die Rotation eines Bildes um einen Wert Θ lässt sich auf die Geometrie
zurückführen. Eine einfache Lösung besteht darin, das Bild punktweise zu rotieren.
x0 = x · cos(Θ) − y · sin(Θ)
19
1.7. TRANSFORMATION EINES BILDES
20
y 0 = y · sin(Θ) − x · cos(Θ)
Diese Berechnung kann in Matrixdarstellung umgewandelt werden.
cosΘ −sinΘ
sinΘ
!
x
y
cosΘ
!
=
x0
!
y0
Das Hauptproblem der Rotation (und auch der Skalierung) resultiert daraus,
dass die meisten Ergebnisse keine Ganzzahlen sind und nicht direkt gerastert
werden können. Die errechneten Pixel-Koordinaten können durch geeignete
Rundungen den Koordinaten angepasst werden. Es ist jedoch darüber hinaus
erforderlich die Farbwerte der Pixel entsprechend den durchgeführten Rundungen
anzupassen. In Abbildung 1.7 überdeckt der rotierte Pixel vier andere Pixel auf dem
Raster. Der Farbwert muss geeignet verteilt werden. Die Information des Bildes
wird auf jeden Fall verfälscht.
(0,0)
(0,0)
Abbildung 1.7: Beim Skalieren (links) entstehen große Farbflecken oder ein Fläche, die
kleiner als ein Pixel sein kann. Beim Rotieren (rechts) entsteht das Problem, dass eine Farbe
auf mehrere Pixel verteilt werden muss.
Lösungsansätze für dieses Problem bietet die digitale Filterung. Es wird auf
die Lösung nicht näher eingegangen, da dies weit aus dem Bereich der Rasterung
raus führen würde. Im folgenden Algorithmus wird stattdessen exemplarisch eine
Optimierung des Problems anhand der Rotation vorgestellt.
20
1.7. TRANSFORMATION EINES BILDES
21
Rotation durch Scheren
Der Algorithmus basiert auf der Idee, eine Rotation durch Scher-Transformationen
anzunähern. Eine Scher-Transformation kann in x- und y-Richtung geschehen.
Durch die Multiplikation mit einer Streck-Matrix wird jeweils die x- oder y- Koordinate um einen Skalar a vervielfacht.
Mx =
1 a
!
0 1
1 0
und My =
!
a 1
Die Idee des Algorithmus ist es, durch eine gezielte Anwendung des Streckens
eine Rotation anzunähern (Siehe Abb 1.8).
Orginal
x-shearing
y-shearing
x-shearing
Abbildung 1.8: Durch drei Scher-Operationen wird die Rotation um 45 Grad angenähert.
cosΘ −sinΘ
sinΘ
cosΘ
!
Ziel
=
1 a
0 1
!
1 0
!
b 1
1 c
!
0 1
Eine angenäherte Lösung des Gleichungssystems ist a = c = −tan( Θ2 ) und
b = sinΘ. Im Hinblick auf eine bessere Filterung werden die Werte wie folgt
gewählt [Wyv93]:
Θ Def
1
2n
a = c = −tan( ) = : − , b =
2
n
1 + n2
Der Algorithmus arbeitet in drei Stufen. Zu Beginn wird das Bild in x-Richtung
gemäß der Matrix gestreckt. Es folgt danach die Streckung in y-Richtung und
anschließend nochmals eine Streckung in x-Richtung.
Aus dieser Arbeitsweise lassen sich Vorteile ziehen. Eine Streckung erfolgt
jeweils nur in eine Richtung. Die andere Richtung bleibt konstant. Der Vorteil
21
1.8. DITHERING
22
besteht darin, dass auf einer ganzen Reihe von Pixeln gearbeitet werden kann. In
jeder Stufe des Algorithmus wird das Bild zeilenweise gefiltert und gerastert. Die
aktuelle Linie wird als Scan-Line bezeichnet.
Scan Line
Abbildung 1.9: Der urspr̈ungliche Pixel erhält durch das Scheren die Form eines Paralellogramms. In diesem Fall überdecken zwei Parallelogramme einen Pixel. Die Farbe muss
aus diesen zwei Pixeln ermittelt werden.
Im Idealfall wird ein Pixel des Rasters von zwei gestreckten Pixeln überdeckt.
Die Farbe muss in diesem Fall nur aus zwei Pixeln zusammengemischt werden.
1.8
Dithering
In Abschnitt 1.2.2 wurde die Abstraktion des Framebuffers vorgestellt, auf dem
die genannten Algorithmen arbeiten. Die Farbtiefe des Framebuffers muss nicht
zwangsläufig mit der Farbtiefe des Ausgabegerätes identisch sein. Es entsteht das
Problem, dass möglicherweise die Farbtiefe verringert werden muss. Das Problem
betrifft nicht nur das Ausgabegerät. Bei Kopiervorgängen von verschiedenen Pixelbereichen, die relevant bei Bitmap-Fonts sind, muss ebenfalls auf verschiedene
Farbtiefen reagiert werden. Im Folgenden wird ein Verfahren vorgestellt, das dieses
Problem durch das sogenannte Dithering löst.
Dazu betrachten die ersten zwei Unterabschnitte die Repräsentation von Farben.
Unterabschnitt 1.8.3 stellt im Anschluss den Floyd-Steinberg Algorithmus vor, der
ein Ordered Dithering mit Fehlerstreuung realisiert.
22
1.8. DITHERING
1.8.1
23
Farbrepräsentation
Wie in Abschnitt 1.2.2 erwähnt, gibt die Farbetiefe die Anzahl der Bits an, die zur
Speicherung einer Farbe zu Verfügung stehen. Es gibt verschiedene Modelle, die
eine Farbe beschreiben können. Das Bekannteste ist das RGB Modell.
Das RGB Modell unterteilt eine Farbe in die Komponenten Rot, Grün, Blau.
Jede Komponente kann durch einen Wert gewichtet werden. Dieser Wert wird in
unterteilten Bitbereichen gespeichert. Die Gesamtfarbe entsteht aus dem Mischen
der drei Farbkomponenten.
1.8.2
Color Look Up Table
Ein Color Look Up Table (CLUT) kann ein wichtiges und effektives Werkzeug
für Dithering-Algorithmen darstellen. Durch die Reduktion der Farbanzahl muss
eine Wahl der noch zu verwendenden Farben getroffen werden. Ohne Einsatz einer
CLUT werden aus dem ursprünglichen Spektrum gleichmäßig Farbwerte gewählt.
Für ein Bild, das Farben aus einem begrenzten Spektrum benutzt, kann die Auswahl
und somit die Qualität optimiert werden, indem die Auswahl aus dem verwendeten
Spektrum erfolgt. Die Auswahl der verwendeten Farben wird in der CLUT in
geordneter Reihenfolge gespeichert. Mit dieser Ordnung kann nun eine gegebene
Farbe einer Farbe des reduzierten Spektrums zugeordnet werden.
1.8.3
Ordered Dithering mit Fehlerstreuung
Es wird im Folgenden der Floyd-Steinberg-Algorithmus betrachtet. Der Algorithmus arbeitet einen Bereich pixelweise ab. Die Reihenfolge ist bei der Abarbeitung
festgelegt (ordered). Jede Farbe eines Pixel wird während der Abarbeitung mit einer
Farbe der reduzierten Auswahl zugeordnet. Dabei kann eine Farbe durch einen
Vergleich in der CLUT, einer passenden Farbe zugeordnet werden. Die Differenz
zwischen Orginal-Farbe und der reduzierten Farbe wird den noch nicht bearbeiteten Nachbarpixeln aufaddiert. Dabei wird die in Abb. 1.10 gezeigte Gewichtung
vorgenommen.[TB94]
Die Verteilung der Gewichtung setzt dabei voraus, dass die Abarbeitung der
Pixel zeilenweise von links nach rechts geschieht. Dieses feste Abarbeitungsmuster
verhindert, dass bearbeitete Pixel verändert werden oder Pixel zu stark verfälscht
werden.
23
1.9. ALIASING
24
bearbeitet
aktuell
7/16
3/16
5/16
1/16
Abbildung 1.10: Die aktuelle Differenz zum gerundeten Farbwert wird an die benachbarten Pixel weitergegeben. Die Weitergabe unterliegt einer Gewichtung und hängt von der
Abarbeitunsrichtung ab.
Es gibt verschiedene Abwandlungen des Floyd-Steinberg-Algorithmus, die
die Abarbeitung betreffen. Es ist möglich, den Pixelbereich schlangenlinienartig
oder auch diagonal abzuarbeiten. Je nach Anwendung kann das Resultat verbessert
werden. Es ist dabei aber notwendig, eine andere Verteilung der Gewichtung auf die
Nachbarn vorzunehmen.
Abbildung 1.11: Floyd-Steinberg: (links) Orginalbild mit 255 Farben. (mitte) Reduzierung
auf 2 Farben ohne Dithering. (rechts) Reduzierung auf 2 Farben mit Floyd-SteinbergDithering
1.9
Aliasing
Ein Aliasing-Effekt entsteht in der Computergrafik, wenn durch gegebene
Rahmenbedingungen eine Reduzierung der Informationen durchgeführt werden
muss. Dieses Problem betrifft beispielsweise das Sampling einer Geradengleichung
(siehe Abschnitt 1.4.1) oder auch die Reduktion der Farbtiefe (siehe Abschnitt 1.8).
Der visuelle Effekt des Aliasing ist typischer Weise als Treppenstufe (siehe Abb.
1.1, rechts) oder in anderen ungewollten Mustern wahrzunehmen. Diese Muster
beeinträchtigen die Qualität des Glyphen und wirken sich dabei auf die Lesbarkeit
eines Textes aus. Deshalb ist es wichtig, den Aliasing-Effekt zu minimieren.
24
1.9. ALIASING
25
Der Bereich des Anti-Aliasing versucht diesen Erscheinungen entgegen zu wirken. Es werden im Folgenden zwei Ansätze vorgestellt. Abschnitt 1.9.1 beschreibt
das objektbasierte Anti-Aliasing. Anschließend wird der Bresenham-Algorithmus
durch Anti-Aliasing erweitert, um den Treppeneffekt beim Linien-Rastern zu
minimieren. Abschnitt 1.9.2 beschreibt die Subpixel-Rendering-Technik, die beim
ClearType-Format benutzt wird.
1.9.1
Objektbasiertes Anti-Aliasing
Das objektbasierte Anti-Aliasing arbeitet auf der Ebene der Primitive. Punkte,
Linien und Polygone werden durch eine Abstufung der Farbwerte an den Rändern
dem Hintergrund angepasst. Es entsteht eine glatte Kante. Durch die Anwendung
auf der Ebene der Primitive wird das gewünschte Gesamtbild erhalten.
Das objektbasierte Anti-Aliasing kann durch eine Erweiterung der bekannten
Algorithmen erreicht werden. Exemplarisch wird im nächsten Unterabschnitt der
Bresenham-Algorithmus durch Anti-Aliasing erweitert.
Bresenham-Erweiterung
Die oben genannte Abstufung der Farbwerte kann durch die folgende Technik des
Alpha Blending durchgeführt werden. Der Alphawert ist neben Rot, Grün und Blau
eine zusätzliche Farbkomponente und beschreibt die Transparenz einer Farbe. Das
Spektrum reicht von Durchsichtig bis Solid.
Es gibt verschiedene Operationen, den Alpha-Wert zweier Farben zu verrechnen.
Der over-Operator ist zur Berechnung der Überlagerung einer existierenden Farbe
B mit der neuen Farbe A passend. Seien dazu A = (αA , RA , GA , BA ) und B =
(αB , RB , GB , BB ) zwei Farbrepräsentationen (siehe 1.8.1).
Der Farbwert C aus der Berechnung C = AoverB berechnet sich durch die
folgende Formel[Wyv93].

RA


RB





C = αA  GA  + (1 − αA )  GB 
BA
BB
25
1.9. ALIASING
26
Die eigentliche Erweiterung des Bresenham-Algorithmus besteht in der mehrfachen Anwendung des Zeichnens einer Linie. Verschiedene Linien werden mit
jeweils einem kleinen Offset zum Start- und Endpunkt gezeichnet. Die Alpha-Werte
der Linien können beispielweise durch 12 , 13 , 14 , ... gewählt werden.
1.9.2
Subpixel Rendering
Die Microsoft ClearType Technologie benutzt eine andere Möglichkeit des
Anti-Aliasing um Glyphen zu rastern. Das ClearType Format ist speziell für den
Einsatz an einem LCD-Bildschirm entwickelt worden und nutzt die technischen
Gegebenheiten eines LCD-Bildschirms aus. Die Funktionsweise ist frei nach Steve
Gibson[Gib07] wiedergegeben.
Das Raster eines LCD-Bildschirms lässt sich auf Pixelebene weiter unterteilen.
Dabei besteht ein einzelner Pixel weiterhin aus drei weiteren Leuchtelementen,
die sich jeweils separat in der Intensität steuern lassen. Die drei Komponenten
entsprechen der Farbrepräsentation, die in Abschnitt 1.8.1 besprochen wurde. Ein
Pixel unterteilt sich in drei gleich große Spalten für je eine Komponente. Dies
ermöglicht nicht nur einen gesamten Pixel anzusteuern, sondern auch die Intensität
der jeweiligen Subpixel. Diese Unterteilung auf Subpixelebene ermöglicht bei der
Font-Rasterung eine dreifach höhere horizontale Auflösung.
Das Subpixel Rendering ist vom Gerät abhängig. Es muss zum Beispiel auf die
Anordnung der Rot-,Grün- und Blau-Komponenten des Gerätes geachtet werden.
Die Umrisse von Glyphen müssen entsprechend der 3fach höheren horizontalen
Auflösung transformiert werden. Das Rastern des Glyphen geschieht über die Entscheidung, ob ein Subpixel innerhalb dieser Umrisse liegt. Der Subpixel wird im
positiven Fall ausgeschaltet, indem die Intensität auf 0 gesetzt wird. Im anderen Fall
wird dieser Subpixel angeschaltet und der Wert der Intensität ist 1. Diese vereinfachte Beschreibung liefert einen schwarzen Glyphen auf weißem Hintergrund.
Es entsteht aber durch die vorgegebene Farbe der Subpixel ein Problem, das
zusätzlich gelöst werden muss. Es entsteht an den Rändern der Glyphen ein Farbsaum. Dieser resultiert daraus, dass die Subpixel nur in zwei verschiedenen Intensitätsstufen angesteuert wurden. Für einen schwarzen Subpixel wurde keine
Intensität benutzt. Am Rand des Glyphen wird die Farbe des ersten nicht schwarzen
Pixels wegen des Kontrastes vom Auge besonders wahrgenommen. Um dieses
Problem zu lösen, wird die Intensität der Subpixel am Rand abgestuft. Es wird ein
Filter benötigt, der dies leistet.
26
1.9. ALIASING
27
Abbildung 1.12: Subpixel-Rendering: Der linke Umriss des Glyphen soll gerastert werden.
Der Glyph wird mit ganzen Pixel (Mitte) und mit Subpixeln (Rechts) gerastert.
Das Filtern geschieht in zwei Stufen. Die Entscheidung über das schlichte Ein- oder
Ausschalten eines Subpixels bleibt bestehen. Der Filter ändert jedoch die Verteilung
der Intensität.
In der ersten Stufe werden der linke und rechte Nachbar-Subpixel zusätzlich in die
Filterung einbezogen. Der Raster-Algorithmus liefert die Intensität (Wert 0 oder
1) für jeden Subpixel. Der Filter gibt die Intensität zu je einem Drittel den drei
Subpixeln weiter.
In der zweiten Stufe wird die Intensität, die den drei Subpixeln aus der vorigen Stufe
übergeben wurde, ein zweites Mal auf die gleiche Art gefiltert. Linker und rechter
Nachbar sowie der zu bearbeitende Subpixel geben die übergebene Intensität den
Nachbarn ihrer Seits weiter.
Es entsteht daraus die in Abbildung 1.13 zu sehende Verteilung der Intensität
auf die fünf involvierten Subpixel.
Das Verfahren entspricht einem farblichen Anti-Aliasing. Dabei werden durch
die Farben die Positionen der Subpixel angesteuert. Aus diesem Grund werden
bei einer Anwendung des Verfahrens auf einem CRT-Monitor keine optimalen
Ergebnisse geliefert. Ein CRT-Monitor kann die vorausgesetzte Unterteilung in
Subpixeln nicht korrekt wiedergeben.
Die vorgestellten Anti-Aliasing-Verfahren können helfen die Umrisse der Glyphen zu glätten. Jedoch tritt dabei durch die Abstufung der Farbwerte am Rand eine
27
1.9. ALIASING
28
1
1/3 1/3 1/3
1/9 2/9 1/3 2/9 1/9
Abbildung 1.13: Subpixel-Rendering: Die aktuelle Intensität eines Pixels wird auch auf
die vier benachbarten Pixel verteilt..
Unschärfe auf. Es ist daher ein Kompromis zwischen Schärfe und Kantenglättung
zu finden. Dies zeigt, wie auch an anderen Stellen zu sehen, dass die angestrebte
optimale Lesbarkeit äußerst schwer zu erreichen ist.
28
Kapitel 2
Shading
Kai Lawonn
2.1
Einleitung
Das Schattieren von geometrischen Oberflächen ist ein wichtiges Teilgebiet der
Computergraphik. Viele Modelle zur Bestimmung des Aussehens von geometrischen Figuren sowie Formen wurden entwickelt, um solche Objekte realistischer
wirken zu lassen. Hierbei unterscheidet man zunächst globale und lokale Beleuchtungsmodelle. Globale Beleuchtungsmodelle simulieren die Ausbreitung von Licht
Beispiele für globale Beleuchtungsmodelle sind Raytracing oder Radiosity. Lokale
Beleuchtungsmodelle, um die es in dieser Arbeit auch vorrangig gehen soll, simulieren die Wechselwirkung zwischen Licht auf Oberflächen. Bei diesem Beleuchtungsmodellen wird die Farbe beziehungsweise die Helligkeit eines Objekts berechnet.
Für dieses Berechnungen werden lediglich durch die Blickrichtung, den Lichteinfall
sowie einiger Materialkonstanten von Objekten und den Lichtquellen bestimmt.
Hierbei wird die indirekte Beleuchtung völlig ausgeschlossen weiterhin berechnen
globale Beleuchtungsmodelle Schatten, die die Objekte werfen, die auch beim lokalen Beleuchtungsmodellen nicht berechnet werden. In dieser Arbeit werden zwei
Beleuchtungsmodelle: Lambert- und Phong-Beleuchtungsmodell vorgestellt sowie
drei Shading-Verfahren, die sich als die Hauptverfahren der Schattierungsalgorithmen herauskristallisiert haben: Flat-, Gouraud- und das Phong-Shading. Weiterhin
habe ich noch zwei weitere Kapitel verfasst, die das Thema Licht aufgreifen: Das
erste Kapitel behandelt die Frage, was passieren kann, wenn das Licht mit einem
Objekt in Wechselwirkung steht, während das sechste Kapitel Kapitel das Licht aus
29
2.2. GRUNDLAGEN
30
einem geschichtlichen Aspekt behandelt. Hierbei wird beschrieben, wie sich im
Laufe der Zeit immer mehr physikalische Theorien über das Licht entwickelten.
2.2
2.2.1
Grundlagen
Lichtausbreitung
Wenn das Licht in eine Szene eintrifft und mit einem Objekt in Wechselwirkung
steht kann das Licht
1. absorbiert,
2. reflektiert oder
3. transmittiert
werden. Die Bedeutung der einzelnen Begriffe wird im Folgenden erklärt.
1. Der Begriff Absorption (lat.: absorptio = aufsaugen) bedeutet im Allgemeinen
etwas in sich aufnehmen“. Im Zusammenhang mit Licht ist darunter das
”
Aufnehmen von Licht bestimmter Frequenz durch das vorhandene Material
gemeint. Wird also zum Beispiel ein schwarzes Material mit weißem Licht
bestrahlt, so wird das Licht fast vollständig vom Material absorbiert. Die
Folge ist, dass uns das Material schwarz erscheint, wobei man bei solchen
Formulierungen vorsichtig sein muss: Insbesondere heißt es nicht das Licht
wird absorbiert, weil das Material schwarz ist, sondern vielmehr, gerade weil
das Licht absorbiert wird, erscheint uns das Material schwarz.
Abbildung 2.1: Absorption
2. Der Begriff Reflexion (lat. reflectere: zurückbeugen, drehen) bedeutet im Allgemeinen etwas zurückwerfen“. Im Zusammenhang mit Licht versteht man
”
2.2. GRUNDLAGEN
31
darunter, dass Zurückwerfen von Licht mit bestimmter Wellenlänge. Hierbei werden noch zwei weitere Unterscheidungen vorgenommen: spiegelnde
(specular) und ausbreitende (diffuse) Reflexion. Beide Reflexionstypen sind
abhängig von dem Material mit dem sie interagieren. Bei der spiegelnden
Reflexion stelle man sich eine nahezu perfekte Oberfläche vor, die glatt ist
und ohne kleine Unebenheiten. Beispiele hierfür sind ein Spiegel oder ein
stiller Teich. Schauen wir in einen Spiegel, werden die Lichtquanten, die auf
einen Spiegel treffen, nahezu komplett reflektiert, nach dem Gesetz: Einfallswinkel=Ausfallswinkel (siehe Abbildung 2), und wir sehen uns selber wieder.
Dies gilt aber nur bei einem perfektem Spiegel.
Abbildung 2.2: Spiegelnde Reflexion bei einem idealen Spiegel
Abbildung 2.3: Diffuse Reflexion
Im Gegensatz zu der spiegelnden Reflexion findet sich die ausbreitende Reflexion auf einer Oberfläche wieder, die nicht frei von Unebenheiten ist. Beispiel
hierfür ist zum Beispiel Holz. Die Unebenheiten sind auf der Oberfläche so
klein, dass die Reflexion des Strahls in eine nicht vorhersehbare Richtung
reflektiert wird (siehe Abbildung 3).
Das Kosinusgesetz von Lambert erklärt einen einfachen Zusammenhang zwischen der reflektierenden Lichtintensität in Abhängigkeit des Einfallswinkels:
I = A · L · cos θ,
2.2. GRUNDLAGEN
32
wobei
• I die Lichtstärke,
• L eine Konstante,
• A ein Flächenelement und
• θ der Winkel zwischen der Normale und dem einfallenden Licht
bedeutet. Diese Gleichung ist allerdings nur für eine ideale diffuse Fläche
gültig, auf der der Strahl gleichermaßen in alle Richtungen reflektiert wird.
Vereinfacht kann man auch nach dem Lambert-Strahler schreiben:
I = Imax cos θ.
Hierbei nimmt die reflektierende Lichtstärke mit größer werdendem Reflexionswinkel ab. Die Lichtstärke ist direkt proportional zum Eintrittswinkel,
das heißt sie nimmt mit größer werdendendem Reflexionswinkel ab. Für den
Lambert-Strahler gilt, es ist egal aus welcher Richtung man auf die Fläche
schaut, sie erscheint gleich hell.
Abbildung 2.4: Lambert-Strahler
3. Der Begriff Transmission (von lat. trans - hinüber und mittere - schicken)
bedeutet im Allgemeinen etwas übertragen“. Im Bezug auf Licht ist damit
”
die Abnahme der Lichtintensität gemeint, wenn sie durch einen Stoff hindurch strahlt. Ein Beispiel ist zum Beispiel eine Flüssigkeit. Das Licht mit
einer bestimmten Intensität trifft auf eine Flasche, in der sich eine Flüssigkeit
befindet. Vereinfacht denken wir uns die Flasche als nicht vorhanden, bzw.
die Flasche übt keinen Einfluss auf das Licht aus. Dann wird das auftreffende
2.2. GRUNDLAGEN
33
Licht nicht nur reflektiert und absorbiert, sondern es wird auch transmittiert,
das heißt das Licht strahlt noch durch die Flüssigkeit durch. In diesem Zusammenhang darf auch nicht die Brechung unerwähnt bleiben, die auf die
Gesetze von Snell zurückführt. Die Brechungszahl ist der Quotient aus der
spezifischen Brechungszahl n1 des aktuellen Materials (z.B. Luft) und der
spezifischen Brechungszahl n2 des Materials, auf welches das Licht eintrifft
(z.B. Wasser):
n2
sin θ1
=
sin θ2
n1
wobei θ den Winkel des aktuellen Materials bezüglich Einfallswinkel und
Flächennormale beschreibt (siehe Abbildung 5).
Abbildung 2.5: Brechung eines Lichtstrahls, der vom Material 1 mit der Brechungszahl n1
in das zweite Material, mit Brechungstzahl n2 , eindringt.
2.2.2
Lichtquellenmodelle
In der Computergraphik versucht man mit einer Vielzahl von unterschiedlichen
Lichttypen eine Szene realistischer wirken zu lassen. Einige dieser Lichttypen
werden im Folgenden kurz vorgestellt und erklärt.
• Ambientes Licht: Ambientes Licht beleuchtet alle Objekte in der Szene
gleichermaßen. Hierbei werden keine Schatten gesetzt, da das Licht keine
Position und Richtung aufweist. Die Objekte erhalten einfach ihre spezifische
Farbe, hierbei wird kein 3D-Eindruck gewonnen.
2.3. LOKALE BELEUCHTUNGSMODELLE
34
• Direktionales Licht: Direktionales Licht simuliert Licht, welches unendlich
weit entfernt ist. Alle Lichtstrahlen sind dabei parallel (kollinear). Schatten
können bei diesem Lichttypen auftreten.
• Punktlicht: Punktlicht hat einen Ursprung, von dem die Lichtstrahlen radial in
alle Richtungen ausgehen. Punktlicht ist mit einer Glühbirne zu vergleichen.
Dieser Lichtquellentyp erzeugt harte Schatten.
• Spotlicht: Spotlicht geht von einem Ursprung aus und leuchtet in eine vorher
definierte Richtung kegelförmig Licht aus. Dabei sind die Richtung und der
Radius festzulegen. Ein Beispiel hierfür wäre zum Beispiel eine Taschenlampe. Der Unterschied zum Punktlicht ist, dass der Strahl durch einen Kegel
begrenzt wird.
• Flächenlicht: Flächenlicht sind Lichtquellen, die sich gleichmäßig verteilt auf
einer Ebene befinden. Dabei werden weiche Schatten erzeugt. Ein Beispiel
wäre ein gleichmäßig beleuchteter Saal mit Deckenleuchten.
2.3
2.3.1
Lokale Beleuchtungsmodelle
Lambert-Beleuchtungsmodell
Das Lambert-Beleuchtungsmodell berechnet sich nach folgender Gleichung:
I = Imax cos θ.
Diese Gleichung wurde ausführlich im Kapitel 2.1 behandelt. Die maximale
Lichtstärke wird immer senkrecht zur Oberfläche reflektiert. Hierbei ist die maximale Lichtstärke völlig unabhängig vom Ort der Lichtquelle. Dieses Beleuchtungsmodell gilt allerdings nur für nahezu perfekte Oberflächen.
2.3.2
Phong-Beleuchtungsmodell
Das Phong-Beleuchtungsmodell basiert aus drei verschiedenen Komponenten:
• Ambient (umgebend)
• Diffuse (ausbreitend)
• Specular (spiegelnd)
2.4. SCHATTIERUNGSVERFAHREN
35
Nach dem Phong-Beleuchtungsmodell berechnet sich dann die Lichtstärke:
I = Iambient + Idiffuse + Ispecular .
Die Lichtstärke setzt sich aus drei verschiedenen Lichtstärken zusammen. Die drei
verschiedenen Lichtstärken werden im Kapitel 4.3 ausführlich behandelt.
2.4
2.4.1
Schattierungsverfahren
Flat-Shading
Berechnung
Flat-Shading ist das einfachste Schattierungsverfahren in der Computergraphik.
Dieses Schattierungsverfahren basiert auf dem Beleuchtungsmodell von Lambert,
bei dem die Lichtstärke völlig unabhängig von Ort des Beobachters ist. Bei dem FlatShading wird jeder Fläche des Objekts ein Farbwert zugeordnet. Die Zuordnung
des Farbwert basiert dabei auf dem Gesetz von Lambert. Dazu benötigt man:
• ~ne : Die normierte Normale des Flächenelements. Diese lässt sich einfach aus
dem Kreuzprodukt der Vektoren aus dem Vertices-Differenzen berechnen.
• ~l: Der normierte Vektor, der von der Lichtquelle auf den entsprechenden
Vertex zeigt. Dieser muss auch normiert sein.
Nach dem Lambertschen-Kosinus-Gesetz gilt:
I = Imax cos θ.
Zunächst betrachte zur Vereinfachung nur eine Lichtquelle, dann berechnet sich die
neue Farbe des Vertex wie folgt:
colornew = colorcurrent ·κM + colorcurrent · cos(^(~ne , ~l))
 
re  
= ge  · κM + h~ne , ~li .
be
(2.1)
(2.2)
Das letzte Gleichheitszeichen ist deshalb richtig, weil die Vektoren ~nv und ~l normiert
sind. Hierbei ist auch darauf zu achten, dass die R-,G- und B-Werte die Zahl 0 nicht
unterschreiten und die Zahl 1 nicht überschritten werden darf. Sollte dies der Fall
2.4. SCHATTIERUNGSVERFAHREN
36
sein, wird in einer zusätzlichen Abfrage der einzelne Wert auf 0 beziehungsweise
1 gesetzt, dies nennt man auch Clamping. Diese Regel gilt ab sofort immer, wenn
es um Farbwerte im Zusammenhang mit dem Skalarprodukt geht. κM ist eine
Konstante, die das Objekt mit einer bestimmten Farbe sichtbar machen lässt. Wird
beispielsweise κM = 1 gesetzt, so behält das Objekt seine Farbe bei und erscheint
nur an den Stellen heller, an denen die Lichtquelle das Objekt direkt bestrahlt.
Wird hingegen κM = 0 gesetzt, so werden Stellen, die von der Lampe nicht
angeleuchtet werden, schwarz dargestellt. Dies passiert wenn die Vektornormale und
der Lichtquellenvektor senkrecht zueinander stehen, dann wird das Skalarprodukt
0 und die neue Farbe errechnet sich aus dem Produkt von colorcurrent und κM .
Betrachten wir nun den Fall, dass unsere Lichtquelle farbig ist. Dann ändert sich die
Abbildung 2.6: Eine Kugel die mit Flat-Shading schattiert wurde. Elemente, die direkt von
der Lichtquelle angestrahlt werden, sind heller dargestellt, während die hinteren Elemente
komplett schwarz sind. [Bild wurde mit JavaView erstellt]
Gleichung (1) wie folgt:
colornew
   
re
rL    
= ge  ⊗ gL  κM + h~ne , ~li .
be
bL
(2.3)
Über den Operator ⊗“ findet sich mehr im Anhang. Hierbei sind dann rL , gL , bL
”
die entsprechenden R,G,B-Werte der Lichtquelle.
Zum Schluß betrachten wir noch den Fall, dass es in der Szene mehrere Lichtquellen mit unterschiedlicher Farbe gibt, dann erhalten wir folgende allgemeine
Gleichung:
2.4. SCHATTIERUNGSVERFAHREN
colornew
   
r
r
X  e   Li  =
ge  ⊗ gLi  κM + h~ne , ~li .
# lights b
bLi
e
37
(2.4)
rLi , gLi und bLi sind hierbei die Farbwerte der unterschiedlichen Lichtquellen.
Abbildung 2.7: Flat-Shading mit roter und grüner Lichtquelle. [JavaView]
Zusammenfassung
Die einzigen Vorteile, die das Flat-Shading bietet sind, dass es sich sehr einfach
implementieren lässt und sehr schnell ist. Dieses Verfahren kann benutzt werden,
um einen ersten Eindruck von einer Szene zu gewinnen. Diese Verfahren erlaubt
auch Schattierungen in Echtzeit. Nachteile des Flat-Shading sind: Aufgrund der
Berechnung einer einzelnen Farbe für jedes Flächenelement wirkt das Objekt sehr
kantig und eckig. Es ist kein sauberer Übergang von einer Kante zur nächsten
erkennbar. Dieser Nachteil wird durch das nächste Schattierungsverfahren, das
Gouraud-Shading, behoben.
2.4.2
Gouraud-Shading
Berechnung
Das Gouraud-Shading wurde vom französischen Informatiker Henri Gouraud entwickelt und erstmals 1971 vorgestellt. Es ist eines der ersten interpolativen Schattie-
2.4. SCHATTIERUNGSVERFAHREN
38
rungstechniken. Zunächst werden die Farbwerte der Vertices berechnet, doch anstatt
nun wie beim Flat-Shading den Elementen nur einen Farbwert zu zuzuweisen, wird
nun jedem Vertex ein Farbwert zugeordnet, die Farbe innerhalb des Elements wird
durch Interpolation der Vertexfarben berechnet. Die Idee, die dahinter steckt, ist,
den Pixel baryzentrisch durch die anliegenden Vertices (siehe Anhang) zu ermitteln
und dann den Farbwert des Pixels mit den baryzentrischen Koordinaten und den
entsprechenden Farbwerten zu mitteln. Im folgenden gehen wir von Objekten aus,
die trianguliert wurden oder bereits sind. Ein Objekt heißt trianguliert, wenn jedes
Flächenelement aus Dreiecken besteht.
Angenommen die Farbwerte wurden für jeden Vertex berechnet, dann besteht
der nächste Schritt darin, den Farbwert eines beliebigen Pixels durch die lineare
Interpolation zu bestimmen.
Es sei nun m ein Flächendreieck, v1 , v2 , v3 ∈ N2 die angrenzenden Vertices und
v ∈ N2 ein beliebiger Punkt in m. Es werden nun die baryzentrischen Koordinaten
λ1 , λ2 , λ3 ∈ R benötigt, für die gelten muss:
1. λ1 (v), λ2 (v), λ3 (v) ≥ 0,
2. λ1 (v) + λ2 (v) + λ3 (v) = 1 und
3. λ1 (v) · (v1 ) + λ2 (v) · (v2 ) + λ3 (v) · (v3 ) = v.
Man mache sich klar, dass vi , v in N2 sind, da wir nur die Pixelkoordinaten betrachten. Gleichung 2. und 3. führen auf folgendes 3 × 3 Gleichungssystem:

1
1

v1x
v2x
v1y
v2y
 
1
 
  
v3x  · λ2 (v) = vx 
vy
v3y
λ3 (v)
1
 
λ1 (v)

mit folgenden Lösungen:
v2x v3y − v3x v2y − vx v3y + vx v2y + vy v3x − vy v2x
v2x v3y − v3x v2y − v1x v3y + v1x v2y + v1y v3x − v1y v2x
−v1x v3y + v3x v1y + vx v3y − vx v1y − vy v3x + vy v1x
λ2 (v) =
v2x v3y − v3x v2y − v1x v3y + v1x v2y + v1y v3x − v1y v2x
v1x v2y + v2x v1y + vx v1y − vx v2y − vy v2x − vy v1x
λ3 (v) =
v2x v3y − v3x v2y − v1x v3y + v1x v2y + v1y v3x − v1y v2x
λ1 (v) =
(2.5)
(2.6)
(2.7)
Hat man nun die λ’s ausgerechnet so lassen sich die Farbwerte der Pixel aus
den alten Farbwerten α1 , α2 , α3 ∈ [0, 1]3 der zugehörigen anliegenden Vertices,
2.4. SCHATTIERUNGSVERFAHREN
39
errechnen. Der Farbwert für den Pixel v errechnet sich dann durch:
colornew = λ1 (v) · α1 + λ2 (v) · α2 + λ3 (v) · α3 .
Etwas anschaulicher kann man sich folgendes äquivalentes System vorstellen (siehe
Abbildung 8):
v1y − vy
v1y − v2y
v1 − vy
vb = v1 − (v3 − v1 ) · y
v1y − v3y
vb − vx
vp = va − (vb − va ) · x
.
vbx − vax
va = v1 − (v2 − v1 ) ·
(2.8)
(2.9)
(2.10)
Abbildung 2.8: Scanline
Hierbei werden mittels Scanlines zunächst die Vertices va , vb berechnet und
dann schließlich der gesuchte Vertex vp ermittelt. Mit diesen Verfahren stößt man
letztendlich auf die gleichen Formeln. Diese Gleichungen ergeben sich, wenn
man zunächst eine Geradengleichung, durch zum Beispiel ~v1 und ~v2 aufstellt:
g : ~x = ~v1 + t · (~v2 − ~v1 ), t ∈ R und dann jenes t sucht, so dass der y-Wert der
Scanline vy die Gleichung erfüllt: vy = v1y + t · (v2y − v1y ) ⇒ t =
v1y −vy
v1y −v2y
. Die
anderen Formeln werden analog bewiesen. Der Farbwert errechnet sich dann, indem
2.4. SCHATTIERUNGSVERFAHREN
40
man zuerst die Farbwerte für va und vb ermittelt und dann für vp . Die Farbwerte für
va und vb errechnen sich durch Gleichung (9) bzw. (10) indem man für v1 , v2 und
v3 die entsprechenden Farbwerte einsetzt.
Auf dem ersten Blick erscheint nun die zweite Möglichkeit deutlich einfacher
und schneller, allerdings funktioniert diese lineare Interpolation auch nur in Zusammenhang mit triangulierten Objekten. Die Idee der baryzentrischen Koordinaten
lassen sich allerdings auch auf allgemeine Objekten übertragen [siehe 10], die nicht
notwendigerweise trianguliert sind.
Abbildung 2.9: Eine Kugel, die mit dem Gouraud-Shading schattiert wurde. Hier sieht man
deutlich sehr viel weichere Übergänge von einem Element zum anderen. [JavaView]
Zusammenfassung
Das Gouraud-Shading bietet einen optisch besseren Eindruck als das Flat-Shading.
Durch die Interpolation erscheinen die Oberflächen nicht so kantig wie beim
Flat-Shading. Aber wie das Flat-Shading hat auch das Gouraud-Verfahren gewisse Nachteile: Durch die Interpolation der Pixelfarbe von den Eckpunkten des
Flächenelements, bleiben markante Reflexion innerhalb des Flächenelements unberücksichtigt. Strahlt zum Beispiel eine Lichtquelle genau inmitten eines Elements,
so dass man in Wirklichkeit eine starke Reflexion beobachten würde, wird dieser
Effekt beim Gouraud-Shading nicht berücksichtigt. Der Grund dafür ist, dass sich
die Farbwerte der Pixel innerhalb eines Elements nur durch lineare Interpolation der
Farbwerte der anliegenden Vertices berechnen. Alternativ könnte man versuchen,
das zugrunde liegende Objekt durch Subdivisions-Verfahren (feinere Triangulierung) zu verbessern. Je mehr Vertices vorhanden sind, desto weicher die Darstellung.
Hierbei sollte man jedoch berücksichtigen, dass die Dauer des Verfahrens von der
Anzahl der Vertices abhängt. Weiterhin kann man beim Gouraud-Shading die Kan-
2.4. SCHATTIERUNGSVERFAHREN
41
ten der Elemente erkennen. Das nächste Schattierungsverfahren, das Phong-Shading,
behebt nun aber auch diese Lücken.
2.4.3
Phong-Shading
Vorbereitung
Das Phong-Shading geht auf den vietnamesischen Informatiker Bui Tuong
Phong zurück, der dieses Verfahren 1973 in seiner Doktorarbeit entwickelte
und 2 Jahre später veröffentlichte. Das Phong-Shading kann auf dem PhongBeleuchtungsmodell basieren. Das Phong-Beleuchtungsmodell basiert aus drei
verschiedenen Komponenten:
• Ambient (umgebend)
• Diffuse (ausbreitend)
• Specular (spiegelnd)
Nach dem Phong-Beleuchtungsmodell berechnet sich dann der Farbwert:
colornew = colorambient + colordiffuse + colorspecular .
Diese drei Komponenten werden nun ausführlicher erklärt.
Ambiente Reflexion
Die Ambiente-Komponente ist eine Konstante und somit
unabhängig von den Orten der Lichtquellen und des Beobachters. Hierbei wird für
das Objekt eine bestimmte Grundfarbe festgelegt, die abhängig von dem Material
und des Umgebungslichtes ist. Beide können vom Benutzer festgelegt werden. Es
gilt, mit κamb ∈ R+ , Iamb ∈ [0, 1]3 :
colorambient = κamb · Iamb .
Die neue Farbe berechnet sich aus der Grundfarbe der Lichtquelle Iamb und einer
empirisch zu bestimmenden Material-Konstanten κamb . Alternativ könnte man
auch die Farben aller Lichtquellen mitteln und diesen Wert dann Iamb zuweisen.
colorambient ist dann die resultierende Farbe des aktuellen Punktes (siehe Abbildung
10).
2.4. SCHATTIERUNGSVERFAHREN
42
Abbildung 2.10: Ambiente Reflexion: Hier wurde die Grundfarbe des Objektes auf grün
gesetzt. [Bild wurde mit POV-Ray erstellt]
Diffuse Reflexion Die Diffuse-Komponente hängt von dem Ort der Lichtquelle
ab und ist völlig unabhängig vom Ort des Beobachters. Hierbei wird schon die
Schattierung des Objektes berechnet, die abhängig von der diffusen“ Farbe des
”
Lichtes, einer Materialkonstanten und dem Skalarprodukt aus dem Normalenvektor
und Lichtquellenvektor ist. Es gilt, mit κdif f ∈ R+ , Idif f ∈ [0, 1]3 :
colordiffuse = κdif f · Idif f · cos ^(~n, ~l)
= κdif f · Idif f · h~n, ~li.
Spekulare Reflexion
Die Spekulare-Komponente hängt nun vom Ort des Beob-
achters und vom Lichtquellenvektor, der von der Oberfäche reflektiert wird, ab. Der
reflektierte Lichtquellenvektor ~r berechnet sich dabei einfach als Spiegelung an dem
Normalenvektor der Fläche. Zusätzlich wird der Vektor ~o benötigt, der den Vektor
vom Beobachter zum betrachteten Punkt darstellt. Bei diesem Schritt wird der Glanz
an bestimmten Stellen des Objekts berechnet. Die Berechnung ist zusätzlich von der
Farbe des Glanzes Ispec , einer erneuten Materialkonstanten κspec und einer GlanzKonstanten n abhängig. Es gilt dann, mit κspec ∈ R+ , Ispec ∈ [0, 1]3 , n ∈ R+ :
colorspecular = κspec · Ispec · cosn (^(~r, ~o))
= κspec · Ispec · h~r, ~oin
2.4. SCHATTIERUNGSVERFAHREN
43
Abbildung 2.11: Diffuse Reflexion: Hier wurden bereits erste Schattierungen berechnet.
[POV-Ray]
Die Vektoren ~o und ~r sind normiert. Wie schon gesagt, gibt n den Glanz an. Diesen
Exponenten nennt man auch den Phong-Exponenten. Für n < 32 ist die Oberfläche
rau, ab n > 32 wird sie glatter, für einen perfekten Spiegel gilt n = ∞“.
”
2.4.4
Berechnung
Das Ergebnis (siehe Abbildung 13) des Phong-Beleuchtungsmodells berechnet sich
aus der Summe der drei Komponenten.
colornew = colorambient + colordiffuse + colorspecular
= κamb · Iamb + κdif f · Idif f · h~n, ~li + κspec · Ispec · h~r, ~oin .
(2.11)
(2.12)
Zusätzlich gilt:
κamb + κdif f + κspec = 1.
Kommen noch weitere Lichtquellen hinzu, so ändert sich die Gleichung (13) wie
folgt:
colornew = κamb · Iamb +
X κdif f · Idif fi · h~n, ~li + κspec · Ispeci · h~r, ~oin .
# lights
(2.13)
2.4. SCHATTIERUNGSVERFAHREN
44
Abbildung 2.12: Spekulare Reflexion: In diesem Objekt sind nur die spekularen Highlights
dargestellt. [POV-Ray]
Die Farbwerte Idif fi und Ispeci sind abhängig von der Position der Lichtquelle. Der
Unterschied zu dem Gouraud-Verfahren besteht nun nicht nur darin drei verschiedene Komponenten zu berechnen, sondern auch im Umfang. Beim Phong-Shading
werden zunächst die Vertexnormalen berechnet. Anschließend wird für jeden Pixel
des Flächenelements die Normale interpoliert und anschließend das oben beschriebene Beleuchtungsmodell angewendet.
2.4.5
Zusammenfassung
Das Phong-Shading ist sicherlich mit eines der aufwändigsten Shading Verfahren,
dennoch sehen die Bilder im Vergleich zu Flat-Shading und Gouraud-Shading
deutlich besser aus. Im Gegensatz zu dem Gouraud-Shading bekommt man hier
einen noch weicheren Übergang von Flächenelmenten hin, die Kanten sind nicht
mehr erkennbar. Zusätzlich werden auch markante Glanzeffekte berücksichtigt.
Die Glanzeffekte sind nun auch, im Vergleich zum Gouraud-Shading, innerhalb
von Flächenelementen erkennbar. Des weiteren sind nun die Kanten nicht mehr
erkennbar.
2.5. COOL-TO-WARM SHADING
45
Abbildung 2.13: Ambient+Diffuse+Specular: Hier wurden alle drei Komponenten zusammengefügt.[POV-Ray]
2.5
2.5.1
Cool-to-Warm Shading
Berechnung
Cool-to-Warm-Shading ist eine Shading-Methode aus dem Bereich des nicht photorealistischen Renderns (NPR). Hierbei geht es nicht darum, Modelle so realistisch
wie möglich darzustellen, sondern die markanten Stellen der Modelle sichtbar werden zu lassen. Dies zeigt nicht nur Anwendung in der Film- oder Computerspielwelt,
sondern vielmehr auch bei technischen oder medizinischen Anwendungen, um die
Formen oder Strukturen von 3D-Modellen übersichtlicher zu gestalten. Speziell
beim Cool-to-Warm-Shading kommt diese Eigenschaft zum Tragen. Hier werden
anstatt Helligkeitsunterschiede benutzerdefinierte Farbübergänge eingesetzt. Der
Benutzer gibt also zwei verschiedene Farbwerte an und je nachdem, welchen Winkel
die Flächennormale und der Lichtquellenvektor einschließen, desto stärker wird
der Pixel mit einer Farbe gefärbt. Man verwendet häufig, wie der Name schon
andeutet, warme und kalte Farben, wie zum Beispiel: rot/orange und blau. Bei dem
Cool-to-Warm-Shading wird dann die Fläche, die der Lichtquelle zugeneigt, ist mit
der wärmeren Farbe beleuchtet und die entgegengesetzte Seite mit der kalten Farbe.
Für die Formel gilt dann:
2.5. COOL-TO-WARM SHADING
colornew =
1 + h~n, ~li
2
!
46
1 + h~n, ~li
· colorwarm + 1 −
2
!
· colorcool .
Bei diesem Shading-Verfahren kann man entweder, wie beim Gouraud-Verfahren
erklärt, nur jeden Vertex nach der obigen Gleichung einen Farbwert hinzufügen
und dann die anderen Farbwerte des Flächenelements durch bi-lineare Interpolation ermittelt. Eine andere Möglichkeit wäre dies genau wie beim Phong-Shading
pixelweise zu erledigen und für jeden Pixel mit den baryzentrischen Koordinaten
den zugehörigen Normalenvektor ermitteln und dann mit der obigen Formel den
entsprechenden Farbwert zu ermitteln. Es gibt noch eine Möglichkeit, bestimmte
Highlights, also zum Beispiel kleine Reflexionen des Lichtes auf der Oberfläche zu
erzeugen. Hierfür kommt noch eine Reflexions-Komponente hinzu, Gleichung (14)
ändert sich dann wie folgt (siehe Abbildung 14):
colornew =
1 + h~n, ~li
2
!
1 + h~n, ~li
· colorwarm + 1 −
2
!
· colorcool +h~n, ~hin .
(2.14)
Abbildung 2.14: Phong-Shading(links) im Vergleich zu Cool-to-Warm-Shading(mitte und
rechts mit Kanten). Von Stefan Müller [6]
2.6. DISKUSSION
2.5.2
47
Zusammenfassung
Das Cool-to-Warm-Shading ist sicherlich sehr einfach zu implementieren und
erlaubt für verschiedene Farbwerte sehr schöne Resultate. Vom Standpunkt der
Geschwindigkeit ist dieses Verfahren nicht viel aufwändiger als das Phong- oder
Gouraud-Shading, je nachdem welches Verfahren man für das Pixel färben benutzt
hat.
2.6
2.6.1
Diskussion
Geschichte des Lichtes
Beleuchtungsmodelle sind in der Computergraphik lediglich eine Approximation an
die Realität. Es gibt sehr viele physikalische Eigenschaften des Lichtes, die bei der
vereinfachten Darstellung von Licht, völlig unberücksichtigt bleiben. Doch klären
wir zunächst einmal, was Licht im physikalischen Sinne ist. Albert Einstein sagte
1954 einmal: Fünfzig Jahre intensiven Nachdenkens haben mich der Antwort auf
”
die Frage ’Was sind Lichtquanten?’ nicht näher gebracht. Natürlich bildet sich heute
jeder Wicht ein, er wisse die Antwort. Doch da täuscht er sich!“.
Eine der ersten Theorien, wieso Licht sich so verhält, wie es sich verhält, wurde
von Sir Isaac Newton 1672 als Korpuskeltheorie aufgestellt. Bei dieser Theorie
wird dem Licht ein Teilchencharakter zugeordnet. Das Licht besteht also aus kleinen Teilchen, die mit hoher Geschwindigkeit von leuchtenden Körpern geradlinig
ausgeschleudert“ werden. Teilweise können damit die geradlinige Ausbreitung
”
und die Reflexion erklärt werden. Brechung und Beugung bereiten jedoch einige
Schwierigkeiten. Diese Theorie wurde schon bald, 6 Jahre später, von Christiaan
Huygens Wellentheorie abgelöst. Mit seiner Wellentheorie konnte er die Beugung
und Brechung von Licht erklären. 1905 wurde dann von Albert Einstein die Lichtquantenhypothese aufgestellt, die besagt, dass Lichtquanten eine Energie besitzen,
Elektronen die Energie eines Photons absorbieren können und dass bei einem
Quantensprung von Elektronen Energie in Form eines Lichtquants frei wird. Die
Wellentheorie ist deutlich schwieriger nach Einsteins Photoeffekt zu erklären: Werden Photonen, mit hinreichend großer Energie auf eine Metallplatte gestrahlt, lösen
sich Elektronen aus dieser heraus. Nach der Wellentheorie müssten, sich mehr
Elektronen herauslösen, wenn die Intensität des Lichtes größer wird. Dies ist aber
nicht der Fall. Einstein erhielt dafür den Nobelpreis. 1922 machte Arthur Holly
Compton eine Entdeckung, für die er 1927 den Nobelpreis erhielt. Wenn ein Pho-
2.6. DISKUSSION
48
ton auf ein elektron trifft, prallen Elektron und Photon ab und bewegen sich mit
unterschiedlichen Energien voneinander weg. Dieses Phänomen unterstützt wiederum die Teilchen-Theorie, da es sehr stark an den Impuls erinnert. Allgemein
wurde aber nun von einem Welle-Teilchen-Modell im Zusammenhang mit Licht
geredet. Louis-Victor Pierre Raymond de Broglie schrieb 2 Jahre nach Comptons
Entdeckung in seiner Dissertation, dass sich jede Form von Materie den WelleTeilchen-Modell unterwarf. Eine komplette Beschreibung aller Phänomene, die
von Lichtteilchen bzw. geladenen Teilchen aller Art handelt, wurde von Richard P.
Feynman, Shinichiro-Tomonaga und Julian Schwinger aufgestellt. Dies ist heutzutage die Grundlage der Quantenelktrodynamik. Viele dieser Phänomene werden in
den Feynman-Diagrammen sichtbar und sind heutzutage Standard. In seinem Buch
’QED. Die seltsame Theorie des Lichts und der Materie’ berichtet Feynman, dass er
seinen Studenten immer sagte: Keiner versteht die Quantenelektrodynamik, nicht
”
einmal ich. Ich zeige Ihnen nur, wie sie damit umzugehen haben.“
2.6.2
Problematik
Die Beleuchtungsmodelle nutzen bei den Berechnungen lediglich den Teilchencharakter des Lichtes aus. Effekte, die auf das Wellenmodell zurückführen, bleiben
hierbei völlig unbeachtet. Interferenz zum Beispiel, also das Überlagern von zwei
oder mehr Wellen bleibt völlig unberücksichtigt. Hier ist gemeint, falls Licht auf
einen Doppelspalt gestrahlt wird, hinter den Spalten abwechselnd angestrahlte
Stellen und dunkle Stellen zu sehen sind. Hierbei kann sich das Licht einerseits
verstärken“ und anderseits gegenseitig auslöschen. Ein anderer Effekt, dem das
”
Shading unterlegen ist, ist, dass angestrahlte Körper auch Licht emittieren. Weiterhin werden Objekte schattiert, Schatten von diesen Objekten werden allerdings nicht
berechnet, so dass eine Kugel auf einer Ebene so wirkt, als würde sich schweben,
anstatt darauf zu liegen.
2.6.3
Warum nicht physikalisch exakt?
Aus Sicht der Quantenelektrodynamik lassen sich bestimmte Effekte nicht vorhersagen; es lässt sich nur mit einer bestimmten Wahrscheinlichkeit sagen, was
passieren wird. Selbst bei einem einfachen Experiment wie dem Doppelspaltversuch
können wir nicht sagen, welches Photon durch welchen Spalt fliegt“. Aufgrund
”
von Beobachtungen und unter Zuhilfenahme der Wellentheorie können wir sagen,
wie die Szene aussehen wird doch nur mit dem Teilchenmodell ausgestattet, wie
2.7. ANHANG
49
wir es in der Computergraphik benutzen, lassen sich solche Resultate nicht exakt
bestimmen. Kommen nun komplexere Objekte hinzu, die von der Einfachheit des
Doppelspaltes weit entfernt sind, dann wären die Rechnungen viel zu komplex,
um genau zu sagen wie die Szene aussehen wird. Es spielt bei der Berechnung ja
nicht nur eine zentrale Rolle, wohin das Licht strahlt und welche Objekte vom Licht
beeinflusst werden, komplizierter wird es noch, wenn man bedenkt, dass das Licht
ja auch auf sich selbst einen Einfluß ausübt (siehe Interferenz).
Alles in allem sind die lokalen Beleuchtungsmodelle aus physikalischer Sicht
noch weit davon entfernt, realistisch zu sein, allerdings spielen sich sehr viele
Lichteffekte, die sich in der Computergraphik nicht darstellen lassen, auch in einer
makroskopischen Welten ab, die für den Beobachter kaum wahrnehmbar sind.
Deshalb lassen sich aus der Sicht des Betrachters die Ergebnisse wirklich sehen
lassen und sind augenscheinlich nahezu perfekt.
2.6.4
Ausblick
In dem vorherigen Kapitel wurden einige Schwachpunkte des Shadings angesprochen. Allerdings lassen sich einige diese Probleme, zumindestens augenscheinlich, beseitigen. Das Radiosity-Verfahren berechnet zum Beipsiel den Lichteinfluß von Objekten untereinander, so dass Gegenstände, die sich in der Nähe von
sehr auffälligen Gegenständen befinden, auch deren Farbwerte annehmen. Ein
Beispiel ist der rote Apfel auf dem weißen Blatt (siehe oben). Ein anderer Schwachpunkt ist, dass keine Schatten gesetzt werden. Diese Problem wird allgemein durch
das Raytracing-Verfahren gelöst. Hierbei werden durch Schnittpunktberechnungen
zunächst ermittelt welche Flächenelemente von den Strahlen einer Lichtquelle getroffen werden und welche nicht. Die Flächenelemente die nicht getroffen werden
erscheinen dunkler und es kommt zur Schattenbildung.
2.7
Anhang
2.7.1
Vektoren
Definition 1 (Vektorraum Rn ). Der Rn ist als die Menge aller n-Tupel von reellen
Zahlen erklärt, geschrieben: ~x = (x1 , . . . , xn ).
Definition 2 (Addition zweier Vektoren). Es sei ~x
(y1 , . . . , yn ) ∈
Rn
=
(x1 , . . . , xn ), ~y
=
zwei Vektoren, dann ist die Addition komponentenweise erklärt
2.7. ANHANG
50
durch:
~x + ~y := (x1 + y1 , x2 + y2 , . . . , xn + yn ).
Definition 3 (skalare Multiplikation). Es sei ~x = (x1 , . . . , xn ) ∈ Rn ein Vektor
sowie t ∈ R ein skalar, dann ist die skalare Multiplikation erklärt durch:
t · ~x := (t · x1 , t · x2 , . . . , t · xn ).
Definition 4 (Skalarprodukt (euklidisch)). Es sei ~x = (x1 , . . . , xn ), ~y =
(y1 , . . . , yn ) ∈ Rn zwei Vektoren, dann ist das Skalarprodukt erklärt durch:
h~x, ~y i :=
n
X
x i yi .
i=1
Definition 5 (Länge eines Vektors). Es sei ~x = (x1 , . . . , xn ) ∈ Rn ein Vektor, dann
ist die Länge des Vektors erklärt durch:
k~xk :=
p
h~x, ~xi.
Bem. ein Vektor ~x heißt normiert, wenn k~xk = 1.
Definition 6 (Winkel zwischen zwei Vektoren). Es sei ~x = (x1 , . . . , xn ), ~y =
(y1 , . . . , yn ) ∈ Rn zwei Vektoren, dann gilt:
cos(^(~x, ~y )) =
2.7.2
h~x, ~y i
.
k~xk · k~y k
Farbwerte
Definition 7 Es sei α = [rα , gα , bα ] ∈ [0, 1]3 und r ∈ R dann gilt:

r · re



α · r = r · ge  .
r · be
Die skalare Multiplikation ist kommutativ.
Definition 8 Es sei α = [rα , gα , bα ] , β = [rβ , gβ , bβ ] ∈ [0, 1]3 dann gilt:

rα + rβ



α ⊕ β = gα + gβ  .
bα + bβ
2.7. ANHANG
51
Die Addition ist kommutativ.
Definition 9 Es sei α = [rα , gα , bα ] , β = [rβ , gβ , bβ ] ∈ [0, 1]3 dann gilt:

rα · rβ



α ⊗ β = gα · gβ  .
bα · bβ
Die Multiplikation ist kommutativ.
Definition 10 Es sei αi = [rαi , gαi , bαi ] ∈ [0, 1]3 eine endliche Familie von Farbwerten. Dann gilt:
P
i rαi
X
i
2.7.3

P

αi := α1 ⊕ α2 ⊕ α3 ⊕ . . . =  i gαi 
P
i bαi
Baryzentrische Koordinaten
Definition 11 (Polygon). Eine Menge Ω = {{Pi : Pi ∈ Rd , i 6= j ⇒ Pi 6=
Pj , i ∈ {0, 1, 2, . . . , n}, n ≥ 3}, {Pi Pi+1 , i ∈ {0, 1, 2, . . . , n − 1}} ∪ {P0 Pn }}
heißt Polygon. Einfacher: Ein Polygon ist eine Menge aus mindestens drei Ecken,
die paarweise verschieden sein müssen sowie Kanten. Eine Kante verbindet immer
nur zwei verschiedene Ecken, auf einer Kante dürfen nur zwei Ecken liegen.
Satz 1 (Jordanscher Kurvensatz). Jede geschlossene Jordankurve (z.B. Polygon Ω)
in der euklidischen Ebene zerlegt diese in zwei disjunkte Gebiete, deren gemeinsamer
Rand die Jordan-Kurve ist. Dabei wird das von der Kurve eingeschlossenes Gebiet,
◦
Inneres genannt. Im Zeichen: Ω.
Definition 12 Eine Menge Ω heißt ein konvexes Polygon, falls die Verbindungsstrecke von zwei beliebigen Punkten im Inneren von Ω liegt.
◦
Formal: Ω = {V, E} Polygon: Für alle P1 , P2 ∈ V gilt: t·P1 +(1−t)·P2 ∈ Ω
für alle t ∈ [0, 1] .
Definition 13 (Baryzentrische Koordinaten). Es sei Ω = {V, E} ein konvexes Polygon, mit v1 , v2 , . . . , vn ∈ V . Die Zuordnungen λi : V −→ R heißen baryzentrische
◦
Koordinaten, wenn für alle v ∈ Ω folgende Bedingungen erfüllt sind:
1. λi (v) ≥ 0, i = 1, 2, . . . , n,
2.7. ANHANG
52
2.
Pn
= 1 und
3.
Pn
= v.
i=1 λi (v)
i=1 λi (v)vi
Kapitel 3
Raytracing
Tobias Pfeiffer
3.1
Einführung
Ein grundlegendes Problem in der Computergrafik ist es, aus einer dreidimensionalen Szene, deren Geometrien mit Materialien und Texturen versehen sind, eine
Grafik zu berechnen, die demjenigen Bild entspricht, das ein menschlicher Betrachter von einer bestimmten Position in der Szene aus sehen würde; dieser Vorgang
heißt rendern. Raytracing (deutsch: Strahlenverfolgung“) ist ein Verfahren, das
”
dieses Problem löst und dabei durch die Verwendung verschiedener physikalischer
Gesetze der Lichtausbreitung einen hohen Grad an Realismus erreicht.
Der folgende Text gibt einen Überblick über die allgemeine Funktionsweise des
Raytracings und die dort verwendeten Techniken. Zunächst sollen die Grundlagen
des Renderings erläutert werden, anschließend wird erklärt, wie die einzelnen
Schritte des Verfahrens ablaufen. Danach wird die Laufzeit eines allgemeinen
Raytracing-Algorithmus’ analysiert und Formen der Optimierung vorgestellt.
3.2
Grundlagen des Renderings
Ziel des Renderings ist es, ein zweidimensionales Abbild einer dreidimensionalen
Szene zu erzeugen, so wie ein Betrachter in der Szene sie sehen würde. Folgende
Problemparameter sind also gegeben:
• eine Menge an geometrischen Primitiven (z. B. Polygone, Kugeln, implizit
gegebene Flächen), bestimmt durch ihre Koordinaten im Raum, und deren
53
3.2. GRUNDLAGEN DES RENDERINGS
54
assoziierte Materialien bzw. Texturen
• eine Menge an Lichtquellen mit deren Eigenschaften (Position, Farbe, Intensität, Form)1
• eine Betrachterposition ( Kameraposition“) und Blickrichtung
”
Es soll als Ausgabe eine Raster-Grafik berechnet werden, die im Idealfall nicht
mehr von einer Fotografie der gleichen Szene zu unterscheiden ist.
Abbildung 3.1: Einfall von Lichtstrahlen in das Auge
Dafür muss zunächst untersucht werden, wie das menschliche Auge Bilder
wahrnimmt und die gewonnenen Erkenntnisse entsprechend auf das Gebiet der
Computergrafik übertragen werden. Die Funktionsweise des Auges ist in Abbildung
3.1 skizziert: Licht einer gewissen Wellenlängenzusammensetzung (Spektrum) fällt
durch die Pupille ein und trifft auf die Netzhaut, auf der sich Rezeptoren für bestimmte Wellenlängen des Lichtes befinden. Diese unterschiedlichen Wellenlängen
werden vom Menschen als unterschiedliche Farben wahrgenommen, wobei es mehrere Spektren gibt, die die gleiche wahrgenommene Farbe erzeugen. Ein Bild“
”
zu berechnen, ist also äquivalent dazu, für jeden Bereich einer Fläche Intensität
und Spektrum des dort auftreffenden Lichts zu bestimmen. [DSC93] behandelt
umfassend die physikalischen Eigenschaften von Licht, die in der Computergrafik
gebraucht werden, wie beispielsweise Ausbreitung, Brechung und Farbe.
In der Computergrafik wird aus technischen Gründen die Position von Brennpunkt und Netzhaut vertauscht. Wie in Abbildung 3.2 gezeigt, wird dazu eine
Bildebene, die senkrecht auf der Blickrichtung des Blickpunktes steht, definiert. Eine
rechteckige Fläche auf dieser Bildebene wird in der Breite und in der Höhe in kleine
Quadrate unterteilt, die den Pixeln auf dem zu berechnenden Bild entsprechen.
1
Es soll im Folgenden versucht werden, zwischen der Farbe, d. h. der Wellenlängenverteilung, und
der Intensität, d. h. der Lichtstärke, angemessen zu unterscheiden, wo dies möglich ist.
3.3. DAS RAYTRACING-VERFAHREN
55
Abbildung 3.2: Umsetzung der Augenfunktion in der Computergrafik
Die Aufgabe eines Renderverfahrens ist es nun, für jeden dieser Pixel einen
Farbwert zu berechnen, der sich aus den in diesem Bereich sichtbaren Objekten
ergibt. Da das, was der Mensch als Farbe“ wahrnimmt, sich jedoch ausschließlich
”
aus den im Auge ankommenden Lichtwellen verschiedener Wellenlänge ergibt,
bedeutet dies, dass im Wesentlichen die Lichtausbreitung in der modellierten Szene
berechnet werden muss.
3.3
Das Raytracing-Verfahren
Das Raytracing-Verfahren basiert darauf, die Ausbreitung der Lichtstrahlen in der
Szene zu verfolgen; es ist damit ein globales Beleuchtungsmodell. Beim ForwardRaytracing wird von der Lichtquelle ausgehend das ausgesandte Licht verfolgt, auch
über mehrere reflektierende Oberflächen hinweg, bis es entweder auf der Bildebene
ankommt, sich aus der Szene hinaus bewegt oder zu schwach wird, um irgendeinen
Einfluss auf das Bild haben zu können. Da nur ein winziger Bruchteil der anfangs
ausgesandten Lichtstrahlen jemals im Bild ankommt, wird dieses Verfahren in der
Praxis nicht verwendet.
Wenn allgemein vom Raytracing-Verfahren die Rede ist, ist damit in der Regel
das Backward-Raytracing gemeint. Dies bedeutet, dass vom Blickpunkt aus der
eintreffende Lichtstrahl rückwärts verfolgt und dessen Ursprung auf einem Objekt
in der 3D-Szene bestimmt wird. Anschließend kann durch verschiedene Verfahren,
unter anderem durch weitere Aussendung von Strahlen und Einsatz eines lokalen
Beleuchtungsmodells (siehe Kapitel 2.7.3), die Farbe und Intensität des in Richtung
des Blickpunktes ausgesandten Lichtes von diesem Punkt aus berechnet werden,
die dann der Farbe an dem jeweiligen Bildpixel entspricht.
3.3. DAS RAYTRACING-VERFAHREN
3.3.1
56
Schnittpunkt- und Normalenbestimmung
Zunächst muss für jeden Pixel dasjenige Objekt bestimmt werden, das vom Blickpunkt aus in Richtung dieses Pixels gesehen“ wird. Sei dazu der Blickpunkt v ∈ R3 ,
”
die Blickrichtung d ∈ R3 und die Bildebene durch
E := b + λr + µu | λ ∈ [0, wmax ] , µ ∈ [0, hmax ]
gegeben (siehe Abbildung 3.3).
Abbildung 3.3: Bildpunkt und Bildebene: Bezeichnungen
Dabei legt b legt die untere linke Ecke des Bildausschnitts im Raum fest, u ∈ R3
ist der Vektor, der nach oben zeigt, (um verschiedene Rotationen der Kamera zu
erlauben) und r ergibt sich als Kreuzprodukt von u und d. hmax und wmax sind
die gewünschten Pixelanzahlen in der Höhe bzw. der Breite. Dann entspricht ein
Bildpixel (x, y) gerade der Punktmenge {b + λr + µu | λ ∈ [x, x + 1] , µ ∈
[y, y + 1]} mit dem Pixelmittelpunkt m := b + (x + 12 )r + (y + 12 )u.
Der vom Blickpunkt durch diesen Pixelmittelpunkt gehende Blickstrahl“ hat
”
also die Gleichung v + λ(m − v), λ ≥ 0. Nun kann für jedes Primitiv der Szene der
Schnittpunkt mit diesem Strahl berechnet werden, wenn es einen gibt. Im Folgenden
werden für einige Primitivtypen Methoden zur Schnittpunktbestimmung vorgestellt.
Da zur Berechnung der Lichtausbreitung später auch die Normalen am Schnittpunkt
benötigt werden, wird auch gleich die Bestimmung eines Normalenvektors erklärt.
3.3. DAS RAYTRACING-VERFAHREN
57
Kugel
Die Kugel2 ist ein sehr beliebtes Motiv in Raytracing-Szenen, da sich der Schnittpunkt eines Strahls mit einer Kugel sehr schnell feststellen lässt. Eine Kugel mit
Mittelpunkt p ∈ R3 und Radius r ∈ R, r ≥ 0 ist die Punktmenge {x ∈ R3 |
|x − p| = r}. Nun gilt |x − p| = r ⇔ |x − p|2 = r2 ⇔ |x − p|2 − r2 = 0 und
durch Einsetzen der Strahlgleichung v + λd erhält man:
0 = |v + λd − p|2 − r2 = hv + λd − p, v + λd − pi − r2
= hv − p, v − pi + 2λ hv − p, di + λ2 hd, di − r2
= λ2 |d|2 + 2λ hv − p, di + |v − p|2 − r2
⇐⇒ 0 = λ2 + λ
2 hv − p, di |v − p|2 − r2
+
|d|2
|d|2
(Hierbei ist h., .i das euklidische Skalarprodukt.) Dann gilt unter der Voraussetzung
|d| = 1 (d. h. mit normiertem Richtungsvektor):
2
q
v − p, d − |v − p|2 + r2
λ1,2 = − v − p, d ±
Der Einheitsnormalenvektor auf einem Punkt x auf einer Kugel ist gerade der
normierte Richtungsvektor vom Kugelmittelpunkt p zu diesem Punkt auf der Oberfläche:
1
n = (x − p)
r
Dreieck
Ein Dreieck mit den Eckpunkten a, b, c ∈ R3 ist die Menge {αa + βb + γc ∈
R3 | α, β, γ ≥ 0, α + β + γ = 1}, wobei jeder Punkt in diesem Dreieck eindeutig
bestimmte Koeffizienten α, β, γ hat; dies nennt man die baryzentrische Darstellung.
Der Strahl ist gegeben durch den Term v + λd mit λ ≥ 0, dabei soll |d| = 1 sein.
Dann ist eine Lösung für die Gleichung
v + λd = αa + βb + γc
2
Eigentlich geht es hier, mathematisch betrachtet, um eine Sphäre oder Kugelfläche, es soll jedoch
im Folgenden der im allgemeinen Sprachgebrauch eher verbreitete Begriff der Kugel verwendet
werden.
3.3. DAS RAYTRACING-VERFAHREN
58
gesucht. Man kann nun γ = 1 − α − β einsetzen und umformen in α(a − c) +
β(b − c) − λd = v − c. Dies lässt sich als lineares Gleichungssystem schreiben:
 
α
 
a − c b − c −d β  = v − c ,
λ
welches mit den bekannten Verfahren für lineare Gleichungssysteme (z. B. GaußAlgorithmus) gelöst werden kann. Existiert eine Lösung mit α, β, 1 − α − β ≥
0, λ > 0, so schneidet der Strahl das Dreieck, andernfalls geht er außen daran vorbei
oder das Dreieck liegt hinter dem Startpunkt des Strahls. Den Schnittpunkt erhält
man dann mit v + λd, die Normale n, unabhängig von der erhaltenen Lösung, durch
das Kreuzprodukt (a − c) × (b − c). Hierbei muss man jedoch beachten, dass unter
Umständen die Normale auf die Rückseite des Dreiecks zeigt, was in der Regel
nicht erwünscht ist. Dazu prüfe man, ob hv − c, ni > 0; andernfalls sollte man das
Vorzeichen des Normalenvektors ändern.
Der Fall Strahl–Ebene ist eine Verallgemeinerung des Falls Strahl–Dreieck; man
ersetze a−c und b−c durch die beiden die Ebene aufspannenden Richtungsvektoren
(dann ist c Stützvektor) und lasse beliebige Werte für α und β zu.
Achsenparalleler Quader
Ein Quader wird im Raytracing-Verfahren häufig als Container für andere Objekte
verwendet (z. B. als Bounding Box) und man will im Allgemeinen nur wissen, ob
der Strahl diese Box schneidet oder nicht. Ein Quader kann als Schnittmenge von
drei senkrecht aufeinander stehenden Paaren paralleler Ebenen betrachtet werden.
Eine Ebene ist eindeutig bestimmt durch ihre Normale n und den Abstand a zum
Ursprung. Betrachtet man nun nur achsenparallele Ebenen, so reicht die Angabe der
Normalenrichtung d ∈ {x, y, z} (d. h. die Normale zeigt in Richtung der x-, y- oder
z-Achse) und der Abstand zum Ursprung. Ein Ebenenpaar ist dann gegeben durch
(ad1 , ad2 ) (sei o.B.d.A. ad1 ≤ ad2 ), die zwischen den beiden Ebenen enthaltene
Punktmenge ist {p ∈ R3 | ad1 ≤ pd ≤ ad2 } und ein achsenparalleler Quader ist die
Schnittmenge dreier Ebenenpaare in verschiedene Koordinatenrichtungen.
Sei v + λr ein Strahl mit einem Intervall [a, b] der möglichen Parameterwerte,
wobei dieses mit [0, ∞[ initialisiert wird. Nun kann man für jede Koordinatenrichtung das Intervall der Parameterwerte ausrechnen, in dem das von den Ebenen
eingeschlossene Gebiet geschnitten wird und das mit dem Strahl gespeicherte Inter-
3.3. DAS RAYTRACING-VERFAHREN
59
vall entsprechend verkleinern:
λ1 :=
vd − ad1
rd
λmin := min(λ1 , λ2 )
λ2 :=
vd − ad2
rd
(3.1)
λmax := max(λ1 , λ2 )
(3.2)
b := min(b, λmin )
(3.3)
a := max(a, λmin )
Ist das Intervall [a, b] nach Behandlung aller drei Koordinatenrichtungen nicht leer,
so schneidet der Strahl den durch die Ebenen berandeten Quader im Punkt v + a · r.
Auswählen des sichtbaren Objekts
Hat man eine Liste von λi für den Blickstrahl berechnet, wählt man daraus das
kleinste aus, denn Punkte mit größeren Werten für λ sind sicherlich weiter vom
Blickpunkt entfernt als Punkte mit kleineren Werten und werden folglich von
diesen verdeckt (siehe Abbildung 3.4). Im Allgemeinen wird es durch numerische
Rechenungenauigkeiten so sein, dass der berechnete Punkt nicht auf der Oberfläche
eines Objekts liegt, sondern etwas davor oder dahinter. Damit bei der weiteren
Aussendung von Strahlen nicht das Objekt selbst den ersten Schnitt erzeugt, kann
es notwendig werden, das berechnete λ noch ein wenig nach unten zu korrigieren,
damit der Punkt nicht hinter der Oberfläche liegt.
Abbildung 3.4: Das erste geschnittene Primitiv ist das vom Betrachter aus sichtbare Objekt
Damit ist dieser Abschnitt, die Bestimmung des sichtbaren Punktes, dessen
Farbe nun noch ermittelt werden muss, abgeschlossen. Im Abschnitt 3.4 finden sich
Methoden, diesen Teil des Verfahrens deutlich zu beschleunigen.
3.3.2
Farbbestimmung eines Punktes
Aus dem vorherigen Abschnitt kennt man den Punkt p ∈ R3 auf einem Primitiv
P ⊂ R3 , die Normale n ∈ R3 sowie die Richtung r ∈ R3 , in der der Betrachter
3.3. DAS RAYTRACING-VERFAHREN
60
auf p sieht, und muss nun die Farbe bestimmen, die von dort in Richtung des
Blickpunktes v (also in Richtung −r) ausgesandt wird. Dazu überlegt man sich
zunächst, welche Arten von Licht von p ausgehen können:
• Licht, das direkt von platzierten Lichtquellen der Szene auf p fällt und in alle
Richtungen reflektiert wird3
• gerichtet reflektiertes Licht, wie z. B. bei einem Spiegel
• gerichtet transmittiertes Licht, wie z. B. bei einer Glaskugel
• diffus reflektiertes Licht, wie auf matten Oberflächen zu beobachten
• diffus transmittiertes Licht, wie z. B. bei einer Milchglasscheibe
Diese Arten des Lichteinfalls sind unterschiedlich kompliziert zu bestimmen und
müssen für das Berechnen eines realistisch wirkenden Bildes kombiniert werden.
Hat man für p die möglichen Lichtquellen und -einfallsrichtungen berechnet,
kann man mittels eines geeigneten Shading-Verfahrens in Abhängigkeit von Spektrum, Intensität, Entfernung, Einfallswinkel und gegebenenfalls weiteren Parametern
das ausgesandte Licht berechnen; dies ist jedoch nicht das Thema dieser Arbeit (siehe stattdessen z. B. Kapitel 2.7.3). Im Folgenden soll daher nur gezeigt werden, was
die genannten Kategorien des Lichteinfalls auszeichnet und wie man sie berechnen
kann.
Direkter Lichteinfall
In der einfachsten Form des Raytracing muss bestimmt werden, von welcher der
Lichtquellen Licht am Punkt p ankommt. Sicherlich macht es für die Erscheinung eines Objekts einen massiven Unterschied, ob es direkt von einer Lichtquelle
beschienen wird oder bezüglich dieser Lichtquelle im Schatten eines anderen,
lichtundurchlässigen (opaken) Objekts liegt.
Zu prüfen ist folglich, ob und in welchem Maße Licht von der Menge L ⊂ R3
der gegebenen Lichtquellen auf p fällt. Dazu erstellt man für jede Lichtquelle l ∈ L
einen Strahl p + λ(l − p) (einen sog. Schattenstrahl) und berechnet, ob es ein
Objekt gibt, das diesen Strahl für λ ∈ [0, 1] schneidet. Wenn dies so ist, bekommt p
3
Genau genommen ist die Reflexion von Licht, das direkt von Lichtquellen kommt, nur ein
Sonderfall der diffusen Reflexion. Dort ist der Fall gegeben, dass man zufällig weiß, aus welcher
Richtung sehr starkes Licht kommt; dies wird aber nach den gleichen physikalischen Gesetzen
behandelt wie die diffuse Reflexion im Allgemeinen.
3.3. DAS RAYTRACING-VERFAHREN
61
kein direktes Licht von l, denn der Weg der Lichtstrahlen von l zu p ist durch ein
Objekt versperrt. Andernfalls erhält p direktes Licht von l, das dann teilweise zum
Blickpunkt reflektiert wird.
Die Intensität des in Richtung des Blickpunktes ausgesanten Lichts verhält sich
dabei nach [Gla89] proportional zum Cosinus des Winkels zwischen Lichteinfall
und Oberflächennormale. Hier gilt das Lambertsche Gesetz I = L · A · cos α, wobei
I die Lichtstärke, L die Leuchtdichte und A die leuchtende Fläche ist. Dies bedeutet,
dass die Intensität des ausgesandten Lichts am stärksten ist, wenn die Lichtquelle
senkrecht über der Oberfläche steht; wenn sie sehr stark von der Seite strahlt, ist die
Intensität geringer (vergl. Abbildung 3.5).
Abbildung 3.5: Auswirkung des Einfallswinkels auf die ausgesandte Lichtstärke
Gerichtete Reflexion und Transmission
Abbildung 3.6: Zu verfolgende Lichtstrahlen bei idealer gerichteter Reflexion
Aus der Erfahrung weiß man, dass auf spiegelnden Oberflächen der direkte
3.3. DAS RAYTRACING-VERFAHREN
62
Lichteinfall die Aussendung von Licht in Richtung des Blickpunktes nur bedingt
beeinflusst. Steht man in einem bestimmten Winkel vor einem Spiegel, so sieht
man nur noch das Licht, das in einem bestimmten anderen Winkel eingefallen ist.
Dabei gilt für perfekte Spiegel das bekannte Gesetz Einfallswinkel = Ausfalls”
winkel“; dies bedeutet, dass der Winkel α zwischen Betrachtungsrichtung r und
Oberflächennormalen n der gleiche ist wie der Winkel β zwischen der Richtung l,
aus der das gespiegelte Licht kommen muss, und der Oberflächennormalen, siehe
Abbildung 3.6. Des weiteren liegen die Betrachtungsrichtung, Normalenvektor und
Lichtursprungsrichtung in einer Ebene.
Es kann (unter der Prämisse |r| = |n| = 1) mittels der beiden angegebenen
Nebenbedingungen h−r, ni = hn, li und ∃ α, β : l = αr + βn für den ausgehenden
Vektor mit Länge 1 folgende Formel bestimmt werden:
l = r − 2 hn, ri · n
(Die Gültigkeit der Forderungen ist leicht nachzuprüfen, die Herleitung findet
sich in [Gla89].)
Abbildung 3.7: Zu verfolgende Lichtstrahlen bei idealer gerichteter Transmission
Ähnlich geht man bei Objekten vor, die aus einem Material bestehen, das zu
einem Teil lichtdurchlässig ist. Auch hier kann das Licht, das von einem Punkt in
eine gewisse Richtung ausgesandt wird, bei einem ideal transmittierenden Material
aus genau einer Richtung kommen, man nennt das Material dann transparent.
Dabei tritt das Phänomen der Lichtbrechung auf, d. h. der Winkel α zwischen
Betrachtungsrichtung r und der Oberflächennormalen n ist abhängig vom Winkel γ
zwischen der Richtung t, aus der das transmittierte Licht kommen muss, und der
Oberflächennormalen, siehe Abbildung 3.7. Wieder liegen die Betrachtungsrichtung,
Normalenvektor und Lichtursprungsrichtung in einer Ebene.
3.3. DAS RAYTRACING-VERFAHREN
63
Der Grad der Brechung hängt dabei immer von den beiden Materialien ab, an
deren Grenze der Lichtstrahl gebrochen wird. Jedes Material hat einen Brechungsindex η, der das Verhältnis der Lichtgeschwindigkeit in diesem Material im Vergleich
zur Lichtgeschwindigkeit im Vakuum angibt. Dann gilt nach Snells Gesetz
sin α
ηr
=
sin γ
ηt
Es kann passieren, dass beim Übergang von einem dichteren in ein weniger dichtes
Material Totalreflexion auftritt, d. h. der Winkel zwischen einfallendem Licht und
der Normalen ist so groß, dass keine Brechung mehr statt findet, sondern das Licht
an der Innenseite der Fläche komplett reflektiert wird.
Unter der Vorraussetzung |r| = |n| = 1 erhält man für den ausgehenden Vektor
t in das zweite Material hinein die Formel:
r
ηr
η r 2
ηr
·r+
cos α − 1 +
· (cos α − 1) · n
t=
ηt
ηt
ηt
(Die Herleitung findet sich, mit anderen Bezeichnungen, ebenfalls in [Gla89].)
Ist der Term unter der Wurzel negativ, so ist dies gerade das Zeichen dafür, dass
Totalreflexion auftritt; es ist dann stattdessen die Formel für die ideale Reflexion zu
verwenden.
In die jeweils berechnete Richtung l bzw. t kann man nun einen Strahl von p aus
schicken und das Objekt finden, das diesen Strahl als erstes schneidet. Anschließend
muss das von diesem Objekt am Schnittpunkt in Richtung −l (bzw. −t) ausgesandte Licht berechnet werden. Dies ist offenbar genau das gleiche Problem, wie das
Ursprungsproblem, das an p in Richtung −r ausgesandte Licht zu bestimmen, daher
kann man hier einen rekursiven Ansatz wählen; dies nennt man dann rekursives Raytracing, vergl. Abbildung 3.8. Der Rekursionsanker kann dann beispielsweise das
Verlassen der Szene, eine bestimmte Rekursionstiefe oder ein zu gering werdender
Anteil an der Gesamtintensität des von p ausgehenden Lichts sein. Ein Beispiel, bei
dem intensiv von der Möglichkeit des rekursiven Raytracings Gebrauch gemacht
wurde, ist in Abbildung 3.9 zu sehen.
Diffuse Reflexion und Transmission
Die im vorigen Abschnitt beschriebene gerichtete Reflexion findet so nur auf glatten,
spiegelnden Oberflächen statt. Auf rauen, matten Oberflächen findet stattdessen
diffuse Reflexion statt; dies bedeutet, dass einfallendes Licht aus einer Richtung in
3.3. DAS RAYTRACING-VERFAHREN
64
Abbildung 3.8: Beispiel für rekursives Raytracing und dazugehöriger Strahlenbaum
Abbildung 3.9: Reflexion und Transmission an einem lebensnahen Beispiel (aus [PR])
alle Richtungen gleichmäßig ausgesandt wird. Daraus ergibt sich umgekehrt sofort
das Problem, dass nicht eindeutig bestimmbar ist, aus welcher Richtung das Licht
kommt, das in Richtung des Betrachters ausgesandt wird.
Ein ähnliches Problem tritt auf, wenn ein Material zwar lichtdurchlässig ist,
aber nicht die Möglichkeit einer gerichteten Transmission bietet, weil es im Innern
viele Partikel gibt, die das Licht umlenken, wie z. B. bei Milchglas; man nennt
das Material dann transluzent. Auch hier ist das Problem, dass Licht aus vielen
3.3. DAS RAYTRACING-VERFAHREN
65
Richtungen zum Farbwert am betrachteten Punkt beitragen könnte.
Eine mögliche Herangehensweise an dieses Problem ist, den Einfluss der diffusen Reflexion bzw. Transmission zu vernachlässigen oder durch ein globales
Umgebungslicht zu simulieren. Eine Alternative dazu bietet das stochastische bzw.
verteilte Raytracing, das in [Coo89] umfassend beschrieben wird. Die Idee bei
diesem Verfahren ist, statt nur eines Strahls in eine feste Richtung mehrere, mehr
oder weniger zufällig verteilte Strahlen in ungefähr diese Richtung auszusenden
und die erhaltenen Werte zu mitteln.
Vergleich der Beleuchtungsarten
Im Folgenden soll veranschaulicht werden, welche Konsequenzen die Berechnung
der oben vorgestellten Arten des Lichteinfalls hat. Die verwendeten Bilder wurden
aus [Wik] entnommen.
Abbildung 3.10: Raytracing nur mit Verdeckungsberechnung (Raycasting)
Abbildung 3.11: Raytracing mit jeweils einem Schattenstrahl pro Punkt
In Abbildung 3.10 sieht man eine Szene, bei der nur Primärstrahlen ausgesandt
wurden und die Farbe der Textur als einzige Größe für die Berechnung der Lichtaussendung in Richtung des Blickpunktes herangezogen wurde. Als Folge davon kann
man sehen, dass korrekt festgestellt wurde, welches Objekt ein anderes Objekt
verdeckt. Jede weitere Tiefeninformation geht jedoch verloren, da es keine Schatten
und keine Auswirkungen von Lichtquellen gibt.
In Abbildung 3.11 wurde zusätzlich von jedem Punkt auf einem getroffenen
Objekt ein Schattenstrahl in Richtung der Lichtquelle (bzw. einem Punkt im Zentrum
der Lichtquelle) ausgesandt. Man erkennt nun bereits die dreidimensionale Gestalt
3.3. DAS RAYTRACING-VERFAHREN
66
der Körper und deren Lage relativ zur Lichtquelle. Die Körper werfen Schatten mit
harten Kanten, da im Schatten sein“ hier eine binäre Eigenschaft ist, es gibt keinen
”
Halbschatten. An Wänden und Decke des Szene sowie an der Grenze von Licht und
Schatten auf den Kugeln erkennt man den Einfluss des Einfallswinkels des Lichts
(siehe Abschnitt 3.3.2).
Abbildung 3.12: Raytracing mit jeweils einem Schattenstrahl pro Punkt und rekursiver
Reflexions-/Transmissionsbestimmung
Abbildung 3.13: Raytracing mit rekursiver
Reflexions-/Transmissionsbestimmung und
teilweise diffuser Reflexion
In Abbildung 3.12 wurde die hintere Kugel als spiegelnd und die vordere als
teils transparent, teils spiegelnd modelliert. Von dem jeweils getroffenen Punkt
der Kugel wurden also rekursiv weitere Strahlen im jeweiligen Ausfalls- bzw.
Brechungswinkel ausgesandt. In der vorderen Kugel erkennt man die Spiegelung
der orangen Wand und der Lichtquelle und die durch Lichtbrechung im Inneren der
Kugel umgedrehte blaue Wand, die sich hinter der Kugel befindet. Wände, Decke
und Schatten sehen genauso aus wie im vorherigen Bild, da diese nicht perfekt
spiegeln und daher keine veränderte Behandlung erfahren.
In Abbildung 3.13 wurden zusätzlich zu den bisher eingesetzten Techniken
zur Berechnung der diffusen Reflexion einige Strahlen in zufällige Richtungen
ausgesandt. Dies kann man insbesondere an den Schatten mit weichen Rändern
erkennen, die dadurch entstehen, dass von Punkten im Randbereich des Schattens
einige Lichtstrahlen die Lichtquelle treffen, andere nicht, und die Mittelung der so
erhaltenen Farbwerte zu einem Ergebnis zwischen vollständig im Schatten“ und
”
nicht im Schatten“ führt. Auch der Bereich an der Decke um die Lichtquelle herum
”
ist nun deutlich weicher berandet.
3.4. LAUFZEITBETRACHTUNGEN UND OPTIMIERUNG
3.4
3.4.1
67
Laufzeitbetrachtungen und Optimierung
Analyse der Laufzeit
Raytracing ist ein Verfahren, das hochqualitative Ergebnisse liefern kann, jedoch oft
zum Preis einer langen Laufzeit. Zunächst einmal ist (von einer konstanten Anzahl
von Strahlen pro Pixel ausgehend) die Anzahl der ausgesandten Primärstrahlen
proportional zur Anzahl der Pixel des zu erzeugenden Bildes. Dies bedeutet, dass
die Renderzeit direkt von der Auflösung des zu erzeugenden Bildes abhängt.
Ohne weitere Optimierungen muss jeder Strahl gegen alle n in der Szene vorhandenen Objekte getestet werden. Dies gilt nicht nur für die O(xy) Primärstrahlen,
sondern auch für alle Sekundärstrahlen, wie zum Beispiel die bei der Reflexionsoder Transparenzbestimmung ausgesandten Strahlen. Es soll daher zunächst die
Anzahl s der Sekundärstrahlen bestimmt werden. In jeder Ebene des Strahlenbaums (vergl. Abbildung 3.8) wird zu jeder Lichtquelle ein Strahl gesandt und
ein Reflexionsstrahl und ein Transmissionsstrahl erzeugt. Die letzten beiden erzeugen wieder Schnittpunkte, von denen das Gleiche aus geschieht. Die Anzahl der
Sekundärstrahlen im Strahlenbaum mit Tiefe d ist also:
sd = (|L| + 2) + 2(|L| + 2) + 4(|L| + 2) + . . . = (2d − 1)(|L| + 2) ∈ O(2d ),
wobei |L| die Anzahl der Lichtquellen ist. Wenn für jeden Strahl n Objekte auf
Schnitt getestet werden müssen und d als Obergrenze für die Tiefe des Strahlenbaums festgelegt wird, ergibt sich als Gesamtanzahl der Schnittoperationen:
O xy · (1 + sd )n = O(n · xy · 2d )
3.4.2
Verbesserungen der Laufzeit
Die im vorherigen Abschnitt bestimmte Anzahl der Schnittpunktbestimmungen ist
linear in der Anzahl der Pixel, der Objekte und exponentiell in der Tiefe des Strahlenbaums. Nach [AK89] werden 95% der Laufzeit eines Raytracing-Rendervorgangs
auf Schnittpunkttests verwendet; es besteht also – gerade in Bildern mit großem d,
d. h. vielen Spiegelungen (vergl. Abbildung 3.9) – durchaus Optimierungsbedarf.
In [AK89] werden die Techniken zur Beschleunigung in folgende Kategorien
eingeteilt:
• schnellere Schnittpunktbestimmung (schnellere bzw. weniger Strahl-ObjektSchnittoperationen)
3.4. LAUFZEITBETRACHTUNGEN UND OPTIMIERUNG
68
• weniger Strahlen, z. B. durch adaptive Tiefenkontrolle des Strahlenbaums
• verallgemeinerte Strahlen, d. h. verfolge ein Volumen (z. B. Kegel) statt eines
Strahls
Die Geschwindigkeit der Strahl-Objekt-Schnittoperationen kann man verbessern,
indem man Algorithmen zur Schnittpunktbestimmung entwickelt, die mit möglichst
wenig Elementaroperationen (Multiplikation, Addition etc.) auskommen, wie sie
beispielsweise bei [Han89] und [Hai89] vorgestellt werden. Da diese Optimierungen
häufig wenig anschaulich sind, sollen im Folgenden nur Methoden zur Reduktion
der Anzahl der Strahl-Objekt-Schnittoperationen erläutert werden.
Wie oben beschrieben, muss prinzipiell jeder Strahl gegen jedes Objekt getestet
werden. Dies ist jedoch, gerade bei zunehmend komplexer werdenden Szenen, ein
Problem; insbesondere, weil nur der erste Schnittpunkt für den Strahl interessant ist.
Eine Idee, die die Laufzeit eines Raytracing-Algorithmus’ beschleunigen kann, ist
es daher, effiziente Indexstrukturen einzuführen; zwei Möglichkeiten dafür werden
im Folgenden erläutert.
Objekthierarchien Eine Möglichkeit, die Anzahl der Schnittpunkttests zu reduzieren, ist das Verschachteln von mehreren Objekten in ein gemeinsames Elternobjekt, das einfacher auf Schnitt mit einem Strahl zu prüfen ist. Es können
beispielsweise mehrere Primitive in einer Kugel zusammengefasst werden, diese
dann wieder in einem größeren Objekt, usw., bis zum Schluss alle Objekte in einem
großen Container-Objekt zusammengefasst sind. Ein Beispiel für diese Situation ist
in Abbildung 3.14 gezeigt.
Wird nun ein Strahl in den Raum geschossen, wird zunächst das Wurzelobjekt
auf Schnitt geprüft. Gibt es einen Schnittpunkt, werden alle Kindobjekte geprüft,
dann ggf. deren Kinder usw., bis es entweder kein Objekt mehr gibt, das den
Strahl schneidet, oder so weit in der Objekthierarchie hinabgestiegen wurde, bis ein
Strahl-Primitiv-Test durchgeführt werden muss.
Bei der Auswahl der Art der Container-Objekte (z. B. Kugel, Quader, Zylinder)
muss man zwischen Geschwindigkeit des Schnittpunkttests und Genauigkeit der
Unterobjektapproximation abwägen. Sicherlich ist es besser, wenn das ContainerObjekt so genau wie möglich das enthaltene Objekt annähert, denn dann ist die
Wahrscheinlichkeit geringer, dass man den Container trifft, obwohl das eigentliche
Objekt nicht getroffen wird. Andererseits wird der Aufwand des Strahl-ContainerSchnittpunkttests höher, je komplizierter der Container ist und unter Umständen
3.4. LAUFZEITBETRACHTUNGEN UND OPTIMIERUNG
69
Abbildung 3.14: Objekthierarchie mit Kreisen als Container-Objekten (7 Kreisschnitt- und
1 Primitivschnitt- statt 11 Primitivschnitttests)
gewinnt man dann keinen Geschwindigkeitsvorteil mehr. Eine Erweiterung dieses
Verfahrens ist beispielsweise die Verwendung mehrerer Container-Objekte unterschiedlichen Typs, die alle geschnitten werden müssen, bevor ein Test mit dem
enthaltenen Primitiv durchgeführt wird.
Zur weiteren Optimierung kann man zu einem Strahl v + λr außer Startpunkt v
und Richtung r auch noch ein Intervall [a, b] ⊂ R speichern, aus dem der Parameter
λ sein darf. Davon kann man profitieren, wenn man eine Tiefensuche im ContainerBaum durchführt und nach jedem erfolgreichen Strahl-Primitiv-Test das obere Ende
des Intervalls so setzt, dass es gerade noch den berechneten Schnittpunkt enthält,
aber keine Punkte, die weiter vom Startpunkt des Strahls entfernt sind. Dann braucht
ein Container-Objekt, dessen nächster Punkt erst bei einem λ > b geschnitten
wird, nicht weiter untersucht zu werden, denn es kann sicher keine Objekte mehr
enthalten, die näher an v sind als eines der bisher gefundenen.
Raumaufteilung Eine Alternative zur Gruppierung von Objekten ist die Partition
des Raumes in Bereiche, die dann nur noch eine Teilmenge der Objekte enthalten.
Ein Beispiel dafür ist das Binary Space Partitioning (BSP)4 , bei dem durch Ebenen
eine Aufteilung des Raums in Halbräume vorgenommen wird, bis jeder Bereich nur
noch eine festgelegte Anzahl an Primitiven enthält, vergl. Abbildung 3.15. Zu jedem
Blatt des BSP-Baums wird dann eine Liste der Objekte, die im entsprechenden
4
Sowohl BSP-Bäume als auch ähnliche Strukturen wie Octrees oder k-d-Bäume sind in jedem
Standardwerk über Algorithmen ausführlich beschrieben. [dB93] beschäftigt sich zu großen Teilen
mit speziellen Techniken zur Reduktion von Schnittpunkttests.
3.5. AUSBLICK
70
Bereich liegen, gespeichert.
Abbildung 3.15: BSP-aufgeteilter Bereich und entsprechender BSP-Baum
Wenn nun der erste Schnittpunkt eines Strahls mit einem Objekt aus der Szene
bestimmt werden soll, wird, beginnend bei der Wurzel des BSP-Baums, immer
dasjenige Kind des Knotens zuerst betrachtet, das den Bereich repräsentiert, der
näher am Startpunkt des Strahls liegt. Mit dieser Methode erreicht man zuerst das
Blatt des Baums, dessen assoziierter Bereich am nächsten am Startpunkt liegt. Gibt
es einen Strahl-Primitiv-Schnittpunkt in diesem Bereich, kann abgebrochen werden,
denn es gibt sicherlich kein Primitiv, das noch näher am Startpunkt des Strahls
ist. Andernfalls muss man den zum jeweiligen Elternknoten gehörenden anderen
Bereich prüfen und ggf. wieder eine Ebene nach oben gehen. Durch Anpassung der
Grenzen des Intervalls, aus dem die Parameterwerte λ des Strahls kommen können,
kann man bestimmte Unterbäume gleich vollständig von der Suche ausschließen.
Mit Hilfe der in diesem Abschnitt vorgestellten Techniken ist es möglich, die
Anzahl der Schnittpunkttests pro Strahl in eine Größenordnung von O(log n) zu
bringen.
3.5
Ausblick
In der vorliegenden Arbeit wurden die Grundlagen des Renderings im Allgemeinen
und des Raytracings im Speziellen erläutert. Es wurde ausgeführt, welche Arten des
ausgesandten Lichts es gibt und wie man für einen gewissen Punkt in der Szene
die beeinflussenden Lichtquellen bestimmt. Die durch die verschiedenen Techniken
erzeugten Effekte wurden demonstriert, eine Laufzeitanalyse durchgeführt und
Techniken der Geschwindigkeitsoptimierung vorgestellt.
3.5. AUSBLICK
71
Ein Thema, das in dieser Arbeit nicht ausführlich behandelt wurde, sich aber
für den interessierten Leser zur Vertiefung anbietet, ist das stochastische Raytracing.
Damit lassen sich mit vergleichsweise einfachen Methoden Effekte wie weiche
Schatten, Tiefenunschärfe, verschwommene Reflexionen, Kantenglättung und Bewegungsunschärfe simulieren.
Kapitel 4
Geometric Modelling:
Approximation und Interpolation
von Kurven und Flächen. Von
Flächen zu Objekten
Jacqueline Spexard
4.1
4.1.1
Bezierkurven
Renault auf dem Vormarsch
Die 60er Jahre waren eine Zeit des Aufschwungs und des allgemeinen Wohlstands.
Eine Zeit in der Luxusgüter, wie zum Beispiel Autos, für Normalbürger erschwinglich wurden. Da zu dieser Zeit Viele Arbeitsschritte von Maschinen übernommen
wurden,wurde die Produktion einzelner Güter billiger. Es handelte sich nicht
mehr um mühsame Handarbeit. Man entwickelte Maschinen und Methoden, um
effizienter zu arbeiten und zu produzieren. So hatte auch der französische Ingenieur
der Firma Renault, Bezier, zu dieser Zeit eine Methode entwickelt Kurven zu
modellieren, ohne dabei von Schablonen, Modellen und Skizzen abängig zu sein.
Durch Beziers neue Methode sind viele Arbeitschritte bei der Modellierung
weggefallen. Früher wurden zunächst Skizzen und kleine Modelle aus Ton
angefertigt .Diese wurden dann von Designern korrgiert. Erst dann wurde ein
72
4.1. BEZIERKURVEN
73
originalgroßes Modell aus Sperrholz und Ton hergestellt.
Dieses Modell wurde dann erstmals den Managern präsentiert, die noch Ideen
und Korrekturen einbringen konnten. Nachdem diese Änderungen durchgeführt
wurde, konnte man mit Hilfe des Rohmodells ein serienreifes Modell produzieren.
Allerdings verging vom Entwurf bis zur Produktion meistens mehr als ein Jahr.
Dieser lange Arbeitsverlauf, der auf Erfahrung, Experementieren und handwerklichem Geschick basierte, konnte durch Beziers leichte mathematische Berechnungen
enorm verkürzt werden.
4.1.2
Wie entstehen Bezierkurven?
Definition
Bezierkurven werden mit Hilfe polynomieller Basisfunktionen (genannt Bersteinpolynome) und n Kontrollpunkten erstellt.Dabei wird jede Basisfunktion durch jeweils
einen Kontrollpunkt skaliert.
B(t) =
n
X
Un,i (t)Pi
0≤t≤1, 0≤i≤n
i=0
Dazu das Bersteinpolynom(Basisfunktion).
n
Un,k (t) =
(1 − t)n−k tk
k
Eigenschaften
Die dadurch entstandene Bezierkurve liegt immer in der konvexen Hülle der KonP
trollpunkte, da die Summe der Basisfunktionen immer 1 ergibt. ni=0 Un,i (t) = 1
Die Kontrollpunkte definieren demnach auch den ungefähren Verlauf der Kurve.
Aufsteigend miteinander verbunden, bilden die Kontrollpunkte das so genannte
Stützpolygon. Aus der Definition der Bezierkurve und insbesondere der Bernsteinpolynome gilt, dass der Grad der Kurve bestimmt wird durch die Anzahl der
Kontrollpunkte minus eins. Des Weiteren gilt, dass der Anfangs- und Endpunkt des
4.1. BEZIERKURVEN
74
Abbildung 4.1: Basisfunktionen
Bezier immer interpoliert wird.
P0 = B(0) und Pn = B(1)
Die Gerade zwischen P0 und P1 bildet die Tangente zum Anfangspunkt. Gleiches
gilt für den Endpunkt mit der Geraden Pn−1 und Pn
Abbildung 4.2: Beispielkurve mit 4 Kontrollpunkten
Ferner gilt für Bezierkurven die variation diminishing property, die besagt,
dass eine beliebig durch die Kurve gesetzte Gerade die Kurve nicht öfter als das
Stützpolygon schneidet. Bezierkurven lassen sich zwar generell für jeden beliebigen
Grad bauen, jedoch steigt der Rechenaufwand ab Grad drei enorm. In der Praxis
4.1. BEZIERKURVEN
75
arbeitet man normalerweise mit kubischen Bezierkurven (Grad 3), da diese keinen
so hohen Berechnungsaufwand haben und trotzdem zu akzeptierenden Ergebnissen
führen.
Kubische Bezierkurven
Eine kubische Bezierkurve ist eine von 4 Kontrollpunkten(P0 ,P1 ,P2 ,P3 ) umschlossene Kurve. Um den genauen Verlauf der Kurve zu berechnen, braucht man das
Bernsteinpolynom, welches folgendermaßen definiert ist:
n
Un,k (t) =
(1 − t)n−k tk
k
Für kubische Beziers entstehen demnach folgende 4 Polynome:
U3,0 (t) = (1 − t)3
U3,1 (t) = 3(1 − t)2 t
U3,2 (t) = 3(1 − t)t2
U3,3 (t) = t3
Abbildung 4.3: Bernstein-Basisfunktionen für Kurven vom Grad 3
Um jetzt die gewünschte Kurve zu erhalten multipliziert man diese 4 Polynome
4.1. BEZIERKURVEN
76
jeweils mit den 4 Kontrollpunkten (P0 ,P1 ,P2 ,P3 ) und addiert diese dann zusammen:
B(t) =
n
X
Un,i (t)Pi
i=0
also
B(t) = U3,0 (t)P0 + U3,1 (t)P1 + U3,2 (t)P2 + U3,3 (t)P3
..
.
B(t) = (Qx (t), Qy (t))
Man erhält in vektorschreibweise ein Polynom Qx (t) für die x-Achse und Qy (t) für
die y-Achse, wobei t zwischen 0 und 1 liegt(0≤t≤1). Wenn man jetzt t zwischen
0 und 1 laufen lässt, zeichnet ein imaginärer Stift unsere Kurve. Man sieht, dass
alle Basisfunktionen über das ganze Intervall ]0, 1[ immer größer als null sind. Das
hat den Effekt, dass sobald sich ein Kontrollpunkt verändert, sich der Verlauf der
gesamten (global) Kurve ändert. Da die Beziers Summe der Kontrollpunkte multipliziert mit den Basisfunktionen sind, folgt daraus, dass man mit der Beziermethode
keinen lokalen Einfluss auf die Kurve nehmen kann.
Kleines Beispiel
Um sich das Vorgehen genauer vorstellen zu können, hier ein kleines Beispiel: Wir
nehmen folgende Kontrollpunkte und die Formel:
P0 (0, 0), P1 (1, 2), P2 (2, 3), P3 (3, 1)
B(t) = U3,0 (t)P0 + U3,1 (t)P1 + U3,2 (t)P2 + U3,3 (t)P3
Wenn man nun die 4 Kontrollpunkte einsetzt entsteht folgende Gleichung:
B(t) = (1 − t)3 (0, 0) + 3t(1 − t)2 (1, 2) + 3t2 (1 − t)(2, 3) + t3 (3, 1)
Daraus berechnet sich folgender Polynomvektor P (t) = (Qx (t), Qy (t)):
B(t) = ((3t), (6t − 3t2 − 2t3 ))
Wenn man nun t in 0,01 Schritten von 0 bis 1 laufen lässt, erhält man folgenden
Graphen:
4.1. BEZIERKURVEN
77
Abbildung 4.4: Bezierkurve mit den 4 Kontrollpunkten:
P0 (0, 0), P1 (1, 2), P2 (2, 3), P3 (3, 1)
Komplexere Beziers
Wie schon vorher erwähnt, verwendet man Beziers eigentlich nur bis Grad 3, da
sonst der Rechenaufwand zu hoch wird. Man versucht dieses Problem des hohen
Rechenaufwands zu umgehen, indem man Kurven niederen Grades(meist dritten
Grades) zu einer komplexeren Kurve zusammensetzt.
Um einen schönen glatten Übergang zu gewährleisten, müssen bestimmte
Stetigkeitsbedingungen beim Zusammensetzen erfüllt sein.
Es gibt zwei verschiedene Arten von Stetigkeit die C-Stetigkeit und die GStetigkeit(geometrische Stetigkeit). Sobald eine Kurve C-stetig ist,ist sie auch
G-stetig. Jedoch folgt nicht aus der G-Stetigkeit die C-Stetigkeit. Die geometrische
Stetigkeit ist eine abgeschwächte Form der C-Stetigkeit. Da sich die C-Stetigkeit
in der Praxis oft nicht realisieren lässt, verwendet man die abgeschwächte Form.
Wir betrachten nur die G-Stetigkeit.
G0 -Stetigkeit(positionelle Stetigkeit)
Für die positionelle Stetigkeit muss gelten,
dass zwei Kurven sich in einem Punkt berühren.Kann aber zu Knicken führen.
Werden zwei Bezierkurven am gleichen Kontrollpunkt zusammengestzt, ist die
positionelle Stetigkeit gewährleistet. Da unsere Kurve aber einen möglichst glatten
Übergang haben soll, reicht diese Bedingung nicht aus.
4.1. BEZIERKURVEN
78
Abbildung 4.5: positionelle Stetigkeit = G0 − Stetigkeit
G1 -Stetigkeit(tangentielle Stetigkeit)
Die Tangente, die durch den Verbindungspunkte läuft muss bei beiden
Verbindungsstücken die gleiche Steigung haben.
Sobald der vorletzte Punkt der ersten Kurve, der Verbindungspunkt und der zweite
Punkt der zweiten Kurve kollinear sind, wird die Kurve G1 -stetig. Demnach können
wir auch die tangentielle Stetigkeit bei Bezierkurven erreichen.
Abbildung 4.6: tangentielle Stetigkeit = G1 − Stetigkeit
4.1.3
Nachteile der Bezierkurven
Die Bezierkurven können noch nicht die optimale Lösung sein, da sie mehrere
Probleme aufweisen:
1. Der Grad der Kurve ist abhängig von der Anzahl der Kontrollpunkte.
2. Der Verlauf der Kurve lässt sich nur global ändern.
Die Bezierkurve ist demnach nicht die ideale Lösung in der Computergrafik, hat
diese aber sicherlich enorm beeinflusst. Der Vorteil der Bezierkurven liegt in der
4.2. B-SPLINES
79
Einfachheit.Nach wie vor sind sie ein beliebter Modellierungsapperat und werden
auch heute noch für beispielsweise Schriftdesign eingesetzt. Jedoch lassen die oberen Probleme bestimmte Modellierungen nicht zu. Diese verlangten einen anderen
Lösungsansatz.
Die B-Splines.
4.2
B-Splines
4.2.1
Mit Schiffen fing alles an
Der Ursprung der B-Splines liegt im Schiffsbau.Um einen Schiffsrumpf zu bauen,
wurden große Metallstreifen (Splines) in die gewünschte Form gebracht und mit
Gewichten (Knots) fixiert. Durch die Gewichte konnte man die Metallstreifen auch
lokal beeinflussen. Eine Eigenschaft, die man bei den B-Splines ebenfalls erreichen
wollte.
4.2.2
Definition von B-Splines
Ähnlich wie bei Bezierkurven, entstehen B-Splines mit Hilfe von Basisfunktionen
und Kontrollpunkten.Auch hier werden die Basisfunktionen durch n Kontrollpunkte
skaliert.
C(u) =
n
X
Ni,k (u)Pi
a≤u≤b
i=0
Dabei entstehen die Basisfunktionen folgendermaßen

 1 falls t < t
i
i+1 und ti ≤u≤ti+1
Ni,1 (u) =
 0 sonst
und
Ni,k (u) =
(u − ti )Ni,k−1 (u) (ti+k − u)Ni+1,k−1 (u)
+
ti+k−1 − ti
ti+k − ti+1
Achtung:
Eine Division durch Null ist hier erlaubt, das heißt 0/0 wird gleich 0 gesetzt.
Die Basisfunktionen entstehen mit Hilfe des Knotenvektors T = (t0 ...tj ).
Ein Knotenvektor definiert Teilintervalle eines großen Intervalls [a, b]. Es gibt zwei
4.2. B-SPLINES
80
Arten von Knotenvektoren,mit deren Hilfe man zwei verschiedene B-Spline-Typen
erstellen kann.
1. Zum einen die uniformen (einheitliche) B-Splines (Abstand der Knotenwerte
im Knotenvektor ist immer gleich groß.Knotenwerte sind aufsteigend sortiert)
2. Zum anderen die nicht-uniformen B-Splines (non-uniform-B-Splines genannt)
(Abstände der Knotenwerte im Knotenvektor variieren.Werte können sich
wiederholen. Auch hier sind die Knotenwerte aufsteigend sortiert.)
Des Weiteren gilt für B-Splines, dass der Grad der Kurve nicht mehr von der Anzahl
der Kontrollpunkte abhängt.
Man kann beliebig viele Kontrollpunkte wählen, nämlich Pi ,wobei 0≤i≤n. Also
hat man n + 1 Kontrollpunkte.
Auch den Grad der Kurve kann man vorher selber definieren. Dieser ist definiert
durch k = Grad + 1. Grundsätzlich gilt, je höher der Grad umso glatter wird die
Kurve und entfernt sich immer mehr den Kontrollpunkten.
4.2.3
Uniform-B-Splines
Ähnlich wie bei den Beziers, werden die uniformen B-Splines durch kontrollpunktskalierte Basisfunktionen erstellt.
Abbildung 4.7: Basisfunktionen eines uniformen B-Splines
Der Unterschied hierbei ist, dass der B-Spline mit Hilfe des Knotenvektors in
4.2. B-SPLINES
81
Kurvensegmente unterteilt wird. Diese Kurvensegmente sind über aufeinanderfolgenden Intervallen gleicher Länge definiert. Jedes Kurvensegment besteht dabei
aus vier Kontrollpunkten (für kubische B-Splines). und liegt in der konvexen
Hülle dieser vier Punkte. Benachbarte Kurvensegmente teilen sich jeweils drei
Kontrollpunkte.Demnach hat man bei den B-Splines n − 1 Kurvensegmente.
Die Aufteilung in Kurvensegmente hat zur Folge, dass wir unseren B-Spline auch
lokal beeinflussen können.
Abbildung 4.8: Beispiel für lokale Manipultion eines B-Spline
Für uniforme B-Splines gelten die im vorherigen Kapitel beschriebenen Bedingungen. Der Knotenvektor ist für uniforme B-Splines folgendermaßen definiert. Der
Abstand der Knotenwerte im Knotenvektor ist immer gleich groß. Die Knotenwerte
sind aufsteigend sortiert.
tj+1 − tj = konstant, ∀j
Hierzu sei gesagt, dass im Allgemeinen bei uniformen B-Splines der Anfangs- und
Endpunkt nicht interpoliert wird.
Unsere Basisfunktionen für uniforme B-Splines mit sechs Kontrollpunkten sehen
folgendermaßen aus.(Siehe Abb.:1.7) Da sich jedes Kurvensegment drei Punkte
teilt, fangen wir erst ab u = 3 bis u = 6 an die Kurve zu zeichnen. Also besteht
demnach unser erstes Kurvensegment S3 aus den Punkten P0 , P1 , P2 und P3 . S4
aus den Punkten P1 , P2 , P3 und P4 . S5 aus den Punkten P2 , P3 , P4 und P5 . Der
Knotenvektor sieht folgendermaßen aus: T = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
Wobei wieder jeweils ein Polynomvektor für die Kurvensegmente entsteht. Lässt
man also u von 3 bis 6 laufen, entsteht folgende Kurve.
4.2. B-SPLINES
82
Abbildung 4.9: Entstandener B-Spline
Möglichkeit der Interpolation
Man kann auch bei uniformen B-Splines sich an Kontrollpunkte annähern
beziehungsweise interpolieren. um das zu erreichen, definiert man Kontrollpunkte
einfach mehrfach. Wenn man einen Kontrollpunkt mehrfach definiert nähert
sich das Kurvensegment diesem Kontrollpunkt an. Wenn aber die Anzahl der
hinzugefügten gleichen Kontrollpunkte genauso groß ist wie der Grad der Kurve,
dann wird dieser Punkt interpoliert.
Allerdings auf Kosten der Stetigkeit.
Abbildung 4.10: Mehrfache Definition eines Kontrollpunktes; das rechte Bild zeigt nur
noch einen G0 -stetigen Übergang
4.2.4
Non-uniform B-Splines
Der non-uniforme B-Spline unterscheidet sich von uniformen B-Splines nur im
Knotenvektor. Hierbei gilt nur, dass tj ≤tj+1 ∀j.Das heißt bei diesem Knotenvektor
sind alle Eingaben erlaubt, sie müssen nur aufsteigend sortiert sein. Ansonsten
unterscheidet sich die Berechnung nicht von uniformen B-Splines. Es gibt noch
einen Spezialfall des Knotenvektors. Es handelt sich dabei um eine Unterart des
4.2. B-SPLINES
83
non-uniform Knotenvektortypen. Den open-uniform knot-vector:



0
falls j < k


tj = j − k + 1 falls k≤j≤n



 n − k + 2 falls j > n
Dieser definiert die Anfangs- und Endwerte des Knotenvektors mehrfach. Dadurch
wird der Anfangs- und Endpunkt des B-Spline interpoliert.
Abbildung 4.11: Beispiel für eine open-uniform (bzw.non-uniform) Basisfunktion
Bezierkurven sind ein Spezialfall der open uniform B-Splines. Dieser Fall ensteht,wenn die Anzahl der Kontrollpunkte um eins höher ist wie der Grad der Kurve.
Wenn also folgender Knotenvektor ensteht, berechnet man wieder eine Bezierkurve.
Durch die Mehrfachdefinition von 0 und 1 wird der Anfangs- und Endkontrollpunkt
interpoliert.
T = ( 0...0
|{z} 1...1
|{z} )
k−mal k−mal
Man hat bei den non-uniformen B-Splines auch die möglichkeit die Kurve näher an
einen bestimmten Punkt heranzuführen oder gar zu interpolieren. Allerdings nicht
über die Kontrollpunkte, sondern mit Hilfe des Knotenvektors. Wie man auch schon
bei dem open-uniform B-Spline gesehen hat, muss man einfach Knotenwerte mehrfach im Knotenvektor definieren (genannt: multiplizieren). Dadurch verschieben
verschmelzen die einzelnen Teilintervalle. Sobald die Basisfunktionen in einem
Punkt eine Spitze bilden, wurde ein Kontrollpunkt interpoliert. Wir haben hier also
eine weitaus elegantere Möglichkeit komplexe Kurven zu modellieren, die nicht
mehr die gleichen Probleme haben wie die Bezierkurven. Selbst die G2 −Stetigkeit
ist auf der gesamten Kurve definiert.
4.2. B-SPLINES
84
Beispiel für eine Interpolation bei non-uniformen B-Splines
Genauer gesagt bei open-uniformen B-Splines. Zunächst betrachten wir uns unsere
Kurve.Die Basisfunktionen haben vier Teilintervalle (Kästchen oben rechts). Das
heißt außer dem Anfangs- und Endpunkt, übt jeder Punkt einen gleichmäßigen
Einfluss auf die Kurve aus. Die blauen Punkte kennzeichnen die einzelnen
Teilintervalle.
Abbildung 4.12: B-Spline ohne Manipulation
Hier sieht man nun, wie sich die Basisfunktionen verschieben und die vier
Teilintervalle zu drei Teilintervallen verschmelzen. Die Basisfunktionen addieren
sich in dem verkleinerten Intervall auf und dadurch erhöht sich der Einfluss des
einen Kontrollpunktes auf die Kurve. Der Punkt P3 zieht hier also stärker die Kurve
an sich heran.
Abbildung 4.13: Annäherung an Punkt P3
Hier werden die drei Teilintervalle der Basisfunktionen zu zwei Teilintervallen
verschmolzen. Da die Basisfunktionen sich zu eins aufaddieren, wird der
Kontrollpunkt P3 interpoliert. Damit entfällt auch die G1 − Stetigkeit.
4.2. B-SPLINES
85
Abbildung 4.14: P3 wurde interpoliert
4.2.5
Zusammengefasst
Mit den B-Splines haben wir nun eine Methode gefunden komplexe Kurven zu
beschreiben, ohne dass sie von der Anzahl der Kontrollpunkte abhängen. Des
Weiteren können wir nun auch lokal Einfluss auf die Kurve nehmen. Das war bei
den Beziers nicht möglich. Also haben wir mit den B-Splines die Probleme der
Bezierkurven umgangen. Ein weiterer Vorteil zu den Bezierkurven ist, dass die
B-Splines auch G2 -Stetig sind.
G2 -Stetigkeit(Krümmungstetigkeit)
Bei der Krümmungsstetigkeit muss gelten, dass an jedem beliebigen
Punkt einer beliebigen Kurve, ein Kreis sich an die Kurve
anschmiegen kann.
Wird Krümmungskreis genannnt.
In jedem Krümmungskreis gibt es einen Krümmungsvektor.
Die Krümmungsvektoren unterscheiden sich nur im Betrag.
Da aber die B-Splines mit Polynomen arbeiten, können wir Kreise und Ellipsen
(Kegelschnitte) nur annähern, aber nicht exakt beschreiben. Also muss auch hier
eine bessere Lösung gefunden werden. Die NURBS.
4.3. NURBS (NON-UNIFORM RATIONAL B-SPLINES)
4.3
86
NURBS (non-uniform rational B-Splines)
Die NURBS-Kurven gehören zu der Klasse der rationalen Splines.(B-Splines waren non-rational) Diese haben den Vorteil, dass sie Kreise und Ellipsen genau
beschreiben. Ähnlich wie bei B-Splines berechnen sich die NURBS mit Hilfe von
Kontrollpunkten und Basisfunktionen. Die NURBS sind rational, da wir nochmal
durch die Summe teilen allerdings ohne die Kontrollpunkte.
Pn
Ni,k (u)wi Pi
Cn,k (u) = Pi=0
n
i=0 Ni,k (u)wi
Die Basisfunktionen werden wieder durch die Kontrollpunkte skaliert. Allerdings
taucht hier noch ein weiterer Parameter wi auf, der als Gewicht bezeichnet wird.
Der Gewichtsparameter beeinflusst die Kurve nur in seinem Kurvensegment, also
wieder lokal. Das Gewicht zieht die Kurve näher an den Kontrollpunkt heran. Es
gilt für NURBS, dass der Anfangs- und Endpunkt interpliert wird.
C(0) = P0 und C(1) = Pn
Rationale NURBS können auch wieder nicht-rational werden, wenn der Gewichtsparameter folgendermaßen aussieht:
wi = 1 ∀i, dann Rn,k (u) = Nn,k (u)
Abbildung 4.15: Durch Gewichte beeinflusster NURB
Non-rationale B-Splines und Bezierkurven sind Spezialfälle der NURBS. (Außerdem auch rationale Bezierkurven, wurden in dieser Arbeit aber nicht aufgeführt.)
4.4. VON KURVEN ZU FLÄCHEN
87
Ansonsten haben wir die gleichen Parameter wie bei den B-Splines.Die NURBS
werden durch die folgenden Eigenschaften definiert:
1. Kontrollpunkte
2. Knotenvektor/Knoten
3. Grad
4. Gewicht
Der NURB liegt (auch schon wie bei den B-Splines) in der konvexen Hülle eines kontrollpunkt-definierten Kurvensegments. Des Weiteren erfüllen NURBS die
variation diminishing property. Außerdem sind NURBs Gn -stetig, was uns die
optimale Glattheit der Kurve sichert. Bei den NURBS kann man also nicht nur
die Kontrollpunkte verschieben, die Knotenwerte ändern, sondern zusätzlich auch
Gewichte definieren. Das ermöglicht uns eine weitaus genauere und differenziertere
Manipulation der Kurve. Entscheidenden Vorteile der NURBS:
1. interaktives Platzieren und Bewegen von Kontrollpunkten
2. interaktives Platzieren von Knotenpunkten
3. interaktives Steuern der Kontrollpunkt-Gewichte
4. lokale Kontrolle
Durch die Genauigkeit und die Manipulationsmöglichkeiten sind die NURBS ein
sehr beliebter Modellierungapperat. Berühmte Entwicklungsumgebungen wie Maya,
3dsMax und Rhinoceros verwenden NURBS.
4.4
4.4.1
Von Kurven zu Flächen
Biliniar Patches
Patches sind auch Flächen. Ein biliniar Patch ensteht, wenn zwei Linien L0 (u) und
L1 (u) über das selbe Intervall definiert sind. Wenn jetzt zum Beispiel die Endpunkte
von L0 (u) P00 und P01 sind, dann wäre L0 (u) = (1 − u)P00 + uP01 und für L1 (u)
würde gelten L1 (u) = (1 − u)P10 + uP11 , wäre der biliniare Patch durch folgende
Formel definiert:
B(u.v) = (1 − u)(1 − v)P00 + u(1 − v)P01 + v(1 − u)P10 + uvP11
4.4. VON KURVEN ZU FLÄCHEN
88
Biliniare Patches sind planar, wenn ihre Linien L0 (u) und L1 (u) in der selben
Ebene liegen.
Bezier-Patches
Bezier-Patches entstehen, wenn man das kartesische Produkt zweier Bezierkurven
nimmt.
F (u, v) =
n
n X
X
Bi (u)Bj (v)Pij
i=0 i=0
Die Kontrollpunkte bilden ein Polyeder an den sich dann die Bezierfläche annähert.
Die gesamte Fläche liegt unterhalb ihrer Kontrollpunkte. Die Eckpunkte werden
interpoliert und somit liegt die Fläche innerhalb ihres konvexen Polyeders.
Hierbei beeinflusst die Manipulation eines Kontrollpunktes wieder die gesamte
Abbildung 4.16: Bezierfläche im konvexen Polyeder
Bezierfläche. Wir haben bei Bezier-Patches wieder die gleichen Vor- und Nachteile,
wie bei Bezierkurven.
Vorteile:
- Leichte und effiziente Berechnung.
Nachteile:
- Nur globaler Einfluss
- Grad hängt wieder von Kontrollpunkten ab.
Komplexere Flächen
Man kann Bezier-Patches zusammensetzen, um eine größere und konplexere
Kurve zu erhalten. Dabei ist wieder darauf zu achten, dass die Kurve mindestens
G1 -stetig ist. Man erhält G0 -Stetigkeit, indem man die Kontrollpunkte eines Randes
gleichsetzt mit den Konttrollpunkten des Randes der zweiten Fläche.
4.4. VON KURVEN ZU FLÄCHEN
89
Abbildung 4.17: G0 -stetige Fläche
Um jetz G1 -Stetigkeit zu erhalten, müssen die beiden Flächen kollinear verbunden
werden.
Abbildung 4.18: G1 -stetige Fläche
B-Spline Patches
Um einen B-Spline Patch zu erhalten bilden wir wieder das kartesische Produkt der
Kontrollpunkte und der B-Splinekurven.
Q(u, v) =
n X
m
X
Bi (u)Bj (v)Pij
i=0 i=0
Analog zu B-Splinekurven entstehen bei B-Spline Patches auch Flächensegmente,
die eine Gesamtfläche bilden. Die Flächensegmente liegen in der konvexen Hülle
der Teilpolyeder. Hierbei haben wir wieder die lokale Kontrolle der einzelnen
Flächensegmente. Der Verlauf der Fläche hängt wieder von den beiden Knotenvektoren ab.
4.4. VON KURVEN ZU FLÄCHEN
90
NURBS Patches
Ahnliches Prinzip, wie bei den B-Spline Patches. Zusätzlich hat man wieder den
Gewichtsparameter wi .
Pn Pm
S(u, v) =
i=0
j=0
P
n Pm
i=0
Ni,p (u)Nj,q (v)wi,j Pij
j=0 Ni,p (u)Nj,q (v)wi,j
Man kann bei den NURBS-Flächen mit Hilfe des Gewichtsparameters die Fläche
viel genauer manipulieren.
4.4.2
Bilinearly Blended Surfaces
Coons Patches
Leider gibt es zu diesem Thema auch sehr wenig Informationen. Es wird meistens
nur ein allgemeiner Überblick gegeben. So auch hier. Eine andere Möglichkeit
Flächen zu bauen, ist der Coons Patch. Die Idee ist eine Fläche mit Hilfe von
vier Randkurven zu definieren. Die Fläche wird also durch die vier Randkurven
P (0, v),P (1, v) P (u, 0) und P (u, 1) begrenzt, u = [0, 1] und v = [0, 1]. Diese
Kurven schneiden sich in den Eckpunkten P (0, 0),P (0, 1), P (1, 0) und P (1, 1).
Außerdem brauchen die Coons Patches noch so genannte Bindefunktionen, mit
denen man die Stetigkeit benachbarter Kurvensegmente gewährleisten kann. Da die
Berechnung für Coons Patches sehr langwierig ist, hier eine erläuternde Skizze:
Abbildung 4.19: Berechnung eines Coons Patch
Man subtrahiert zum Schluss nochmal die Eckpunkte, da diese sonst doppelt definiert wären. Coons Patches werden selten in der Computergrafik verwendet.
4.5. VON FLÄCHEN ZU OBJEKTEN
4.5
91
Von Flächen zu Objekten
Um Objekte zu erstellen, werden Flächen mit Hilfe der Manipulationswerkzeuge
so verändert, dass man eine Objekt erhält. Angenommen wir wollen einen Kopf
modellieren: Wir erstellen zunächst eine Kugel und bilden dann an den Stellen, wo
die Augen sich befinden Dellen. Also wir verschieben die Kontrollpunkte nach innen
oder definieren Gewichte dementsprechend. Bei der Nase analog. Die Teilfläche
wird nach außen gezogen.
Kapitel 5
Grafikkarten und
GPU-Programmierung
Christoph Sackl
5.1
Einleitung
Eine Grafikkarte, brauche ich die wirklich? Im Lexikon ist die Grafikkarte definiert
als das Steuergerät für die Bildschirmanzeige in einem Personal Computer [Wik07b].
Das ist heute aber nur mehr die halbe Wahrheit und verrät nur einen Teil von dem,
was eine Grafikkarte tatsächlich kann. Grafikkarten werden immer schneller und
können so immer realistischere 3D-Spiele am Computer oder Render-Sequenzen
fürs Kino erzeugen. Sie können mittlerweile aber auch komplexe Algorithmen auf
ganz anderen Gebieten, wie etwa dem Entschlüsseln von Passwörtern, sehr viel
schneller bearbeiten als der Hauptprozessor (CPU, engl.: Central Processing Unit).
In dieser Arbeit findet man eine kurze geschichtliche Einführung, wie rasant sich
die Grafikkarte bis heute entwickelt hat und sieht einen Überblick der alten GrafikPipeline und der nun aktuellen Unified-Shader Architektur, die nVidia mit dem G80
Chip eingeführt hat. Darüber hinaus sollen auf einfache Weise die Grundlagen der
Shader- und GPU-Programmierung und womit hier eigentlich programmiert wird,
gezeigt werden.
92
5.2. DIE GRAFIKKARTE
5.2
5.2.1
93
Die Grafikkarte
Entwicklung der Grafikkarte
Die erste Grafikkarte, aus dem Jahre 1977, wurde im Apple II Computer verbaut.
Dieser Monochrome-Display-Adapter ist im heutigen Sinne eigentlich keine Grafikkarte, da sie keine einzelnen Pixel ansteuern konnte. Die Darstellung auf dem Bildschirm erfolgte in nur zwei Farben (monochrom) und es wurde eine Textauflösung
von 80 Spalten (Zeichen) und 25 Zeilen geboten. Deshalb bezeichnete man diese
Karte auch als 80-Zeichen-Karte“ [Kom07]. Die erste Grafikkarte im heute immer
”
noch so bezeichneten IBM-PC, wurde von IBM im Jahre 1983 als CGA-Karte
(Color-Graphic-Adapter mit 320x200 und vier Farben) verbaut. Die ersten Modelle
liefen auf einem sehr einfachen 8-Bit Bus (XT-Bus) und waren im Vergleich zu
heutigen Grafikkarten sehr klein (siehe Abb. 5.1).
Abbildung 5.1: Eine der ersten Grafikkarten für den XT Bus. (Quelle: Wikipedia)
Bis 1989 waren die von IBM eingeführten Grafiktypen (1983 die CGA-Karte,
1984 die EGA-Karte und 1989 die VGA-Karte) bei dem am meisten verbreiteten
IBM-PC Standard. Heute wird bei IBM kompatiblen PCs immer noch der VGAModus (640x480 Bildpunkte in 16 Farben) als Notfall-Modus“ unterstützt. Die zur
”
Zeit gängigsten Standards sind PAL (768x576), SVGA (800x600), XGA (1024x768)
und SXGA (1280x1024). Der Trend zu Widescreen-Bildschirmen spiegelt sich in
neueren Standards wie dem WUXGA-Standard mit einer Auflösung von 1920x1200
Bildpunkten oder HD1080 mit 1920x1080 Bildpunkten, bei 16,7 Millionen Farben
auf einem 16:10 bzw. 16:9 Monitor, wieder.
Auch die verwendeten Steckplätze haben sich bis heute in starkem Umfang weiterentwickelt. Hier ein kurzer Überblick über deren technische Daten:
5.2. DIE GRAFIKKARTE
94
• ISA (Industry Standard Architecture)-Bus: Heute technisch überholt (Taktfrequenz 8,33 MHz; erreichbare Übertragungsrate: 4 MB/s; Datenbreite 16
Bit).
• PCI (Peripheral Component Interconnect)-Bus: Nur noch in Servern im
Einsatz (Taktfrequenz 33-66 MHz; 2x-Pipelining-Modus Übertragungsrate:
150 MB/s; Datenbreite 32 Bit).
• AGP (Accelerated Graphics Port)-Bus: Zunehmend durch PCI-Express vom
Markt verdrängt (Taktfrequenz 66-533 (Effektiv) MHz; bis zu 8x-PipeliningModus Übertragungsrate: 2133 MB/s; Datenbreite 32 Bit).
Bei aktuellen Grafikkarten wird der moderne PCI-Express-Bus benutzt. Durch die
erhöhten Taktfrequenzen und Speicherbandbreiten können immer mehr Daten in
gleicher Zeit verarbeitet werden, was mit ein Hauptgrund für die höhere Grafikqualität bei Computerspielen und gerenderten Bildern ist oder auch computeranimierten
Szenen in Filmen. Die hohe Speicherbandbreite kann dabei zum Beispiel für größere
Texturen (höhere Auflösung) genutzt werden. Vergleicht man zum Beispiel eine
Grafik mit VGA-Auflösung und vergrößert sie dann auf XGA-Auflösung wächst
der Speicherbedarf der Grafik an. Das bedeutet mit mehr Speicherbandbreite kann
man größere Mengen an Grafikdaten in gleicher Zeit verarbeiten, so dass wir heute
zum Beispiel nicht mehr im älteren PAL-Format Filme sehen sondern in einer
hohen HD-Auflösung. Anhand der Taktfrequenz lässt sich ablesen, wie lange eine
Taktperiode dauert. Eine Taktfrequenz von 1 GHz entspricht zum Beispiel einer
Taktperiode von 1 ns. Erhöht sich der Takt finden mehr Taktperioden in der gleichen
Zeit statt. Da pro Taktperiode eine gewisse Zahl an Grafik-Operationen stattfinden
kann, steigert die Takterhöhung die Zahl der ausführbaren Operationen.
Im Folgenden soll anhand eines kurzen Überblicks der Aufbau einer modernen
Grafikkarte erläutert werden.
5.2.2
Eine moderne Highend-Grafikkarte
Die nVidia GeForce 8800 GTX ist eine moderne Highend-Grafikkarte und verwendet den nunmehr aktuellen PCI-Express-Bus zur Datenübertragung zwischen
CPU und Grafikkarte. Er läuft mit einer effektiven Taktfrequenz von 1-12 GHz
und unterstützt bis zu 16-Pipelines mit einer theoretischen Übertragungsrate von 4
GB/s je Richtung (Näheres in der Spezifikation [Ins07]). Die Datenbreite beträgt 32
5.2. DIE GRAFIKKARTE
95
Bit. Im folgenden die wichtigsten Bestandteile einer Grafikkarte am Beispiel der
GeForce 8800 GTX (siehe Abb. 5.2).
Abbildung 5.2: Eine nVidia 8800 GTX mit abmontiertem Kühler. (Quelle: Techreport)
Den Kern der Grafikkarte bildet der Grafikprozessor (GPU, engl.: Graphics
Processing Unit). Die GPU beherbergt auch die Grafik-Pipeline und führt Shader
Operationen aus, worauf später im Detail eingegangen wird. Auf dieser Grafikkarte
ist ein G80-Chip, welcher mit 575 MHz getaktet ist, verbaut. Er erlaubt eine Füllrate
von 13,8 Milliarden Pixel/s und 36,8 Milliarden Texel/s. Ein Pixel ist ein Bildpunkt
auf dem Bildschirm. Ein Texel (Texturelement) ist in der Computergrafik die fundamentale Grundeinheit eines Texturraumes. Texturen werden durch Arrays von
Texeln repräsentiert, so wie Bilder aus Arrays von Pixeln bestehen. Die theoretisch
erreichbare, maximale Füllrate an Texeln pro Sekunde gilt heute als Hauptleistungsindikator einer GPU. Sie gibt an, wieviele texturierte Pixel die Grafikkarte pro
Sekunde auf den Bildschirm rendern kann. Den Kern umgibt der Grafikspeicher. In
Abbildung 5.2 sehen wir um die GPU 768 MB GDDR3-Speicher mit einer Taktrate
von 1800 MHz und einer Datenbreite von 384-Bit. Die maximale Bandbreite dieses
Speichers beträgt 86,4 GB/s und liegt damit weit über der Geschwindigkeit früherer
Modelle. Ebenfalls beachtlich ist die große Anzahl an Transistoren in GPUs. Eine
GeForce 8800 GT (G92 Chip) besitzt 754 Millionen Transistoren. Im Vergleich
dazu hat eine aktuelle Core 2 Duo CPU nur 291 Millionen Transistoren. Ein Transistor ist ein Halbleiterbauelemt, welches aus einem Halbleiter (meist Silizium) als
Grundmaterial besteht und zum Schalten und Verstärken von elektrischen Strömen
und Spannungen dient. Ein Nachteil der hohen Geschwindigkeit bei modernen
Grafikkarten ist allerdings der hohe Stromverbrauch, der unter anderem auf die stark
gestiegene Transistoranzahl zurückzuführen ist. Das Spitzenmodell von AMD/ATI
die Radeon HD 2900XT benötigt maximal 245 Watt und damit doppelt so viel
Strom wie ein durchschnittlicher PC. AMD führt zur Zeit das neue Modell HD
3870 ein, das durch ein spezielles Power Management mit einem Verbrauch knapp
über 100 Watt auskommen soll und trotzdem die gleiche Leistung wie eine GeForce
5.3. GRAFIK-PROGRAMMIERUNG
96
8800 GTX bietet.
Vergleicht man diese moderne Karte mit einer GeForce-Karte der ersten Generation
sieht man schnell, wie stark sich die Performance in diesem Bereich entwickelt
hat. So waren im Jahr 2000 bei der GeForce 256 noch ein NV10 Chip mit 120
MHz, der über eine Füllrate von nur 480 Millionen Texel/s verfügt hat, verbaut.
Eine Pixel Füllrate wird für diesen Chip überhaupt nicht angegeben, da zu dieser
Zeit viele Operationen, die heute von der GPU übernommen wurden, noch die
CPU ausgeführt hat. Als Speicher wurden 16-64 MB SDRam mit 166-300 MHz
eingesetzt, die über eine Bandbreite von 2,7-4,8 GB/s verfügten. Die Anbindung
erfolgte damals noch über eine Busbreite von nur 128-Bit. Eine Übersicht über alle
nVidia Chips findet man bei Wikipedia [Wik07a].
5.3
Grafik-Programmierung
Bevor man die klassische Grafik-Pipeline und die neue Shader-Architektur genauer
betrachtet, sollte man wissen, womit diese eigentlich programmiert werden. Da
die Ausführungen der bekannten Architekturen bei den verschiedenen HardwareHerstellern oft unterschiedlich sind, ist es wichtig auf standardisierte Schnittstellen
für Programmierer zurückzugreifen. Diese Schnittstellen nennt man APIs (engl.:
Application Programming Interface). Mit ihnen kann man einfach Computergrafiken
programmieren ohne genauere Kenntnisse über die Hardware zu besitzen. Sie dienen
als Schnittstelle zwischen Anwendung und Hardware, um so möglichst plattformund hardwareunabhängig mit standardisierten Befehlen die Grafik-Pipeline bzw.
Shader programmieren zu können. Die beiden wichtigsten Beispiele für solche APIs
sind OpenGL (vor allem im professionellen Bereich genutzt, engl.: Open Graphics
Library) sowie Direct3D (Dieser Teil des DirectX-Entwicklungspakets wird von vielen Windows Spielen und Anwendungen genutzt). Weniger bekannte Grafik-APIs
sind GDI (engl.: Beginning Game Programming) und SDL (engl.: Simple Direct
Media Layer). Da GDI relativ langsam und umständlich ist [Pyg07], wird es für
größere Objekte nicht verwendet. SDL ist wie OpenGL eine freie Grafik-Bibliothek
und betriebssystemunabhängig, im Gegensatz zu Direct3D welches mit DirectX nur
unter Windows zur Verfügung steht.
Die Motivation solche speziellen Grafik-APIs anzubieten liegt darin, dass die klassischen Programmiersprachen wie beispielsweise C/C++ oder Python in ihrem
Standardumfang keine Grafikfunktionen anbieten. Damit Programmierer für die
Grafik-APIs keine neue Programmiersprache lernen müssen, haben die oben ge-
5.4. KOORDINATENSYSTEME
97
nannten APIs die Gemeinsamkeit, dass sie auf C basieren und auch mit C++ genutzt
werden können. 3D-Anwendungen können daher mit C/C++ programmiert werden,
deren Befehlsumfang dann durch die gewählte Grafik-API lediglich erweitert wird
um so mit standardisierten API-Befehlen die Grafik-Pipeline oder Shader zu parametisieren. Da OpenGL und Direct3D auf C-Befehlen basieren, können diese nicht
mit der sonst oft genutzten Programmiersprache Java zur Spieleprogrammierung
oder für andere 3D-Anwendungen verwendet werden. Es gibt einen sogenannten
Java-Wrapper mit der Bezeichnung Jogl um OpenGL nutzen zu können.
Da nun gezeigt wurde, womit man etwas für die Grafikkarte programmiert, soll als
nächstes veranschaulicht werden, was man eigentlich für die Grafikkarte programmiert.
5.4
Koordinatensysteme
Bevor es am Bildschirm zur Bildausgabe kommt, müssen am Computer 3D-Objekte
in einem typischerweise 3-dimensionalen Raum erzeugt werden. Aus diesen Geometriedaten wird die Grafik-Pipeline später das 2-dimensionale Bild auf dem Monitor
erzeugen. Die Vertex-Einheiten der GPU transformieren die Vertizes der Objekte
jeweils in ein oder mehrere verschiedene Koordinatensysteme [FK03]. Diese Koordinatensystem werden durch unterschiedliche Räume beschrieben, welche im
Folgenden erläutert werden sollen.
5.4.1
Object Space
Hier liegen alle Objekte in ihrem eigenen x-y-z-Koordinatensystem mit einem festgelegten Ursprung. Zur Bearbeitung eines solchen Raums lässt sich beispielsweise
3D Studio Max nutzen, in dem das Zentrum des Objekts für gewöhnlich den Koordinaten (0,0,0) entspricht. Bei einem Auto könnte dieser Punkt etwa dem linken
Vorderreifen entsprechen. Über diesen Kontrollpunkt kann der 3D-Renderer das
Modell bewegen und rotieren, weil alle Koordinaten im Object Space relativ zu
diesem Ursprung liegen.
5.4.2
World Space und Eye Space
Im World Sapce werden die Objekte über ein homogenes x-y-z-wKoordinatensystem in eine virtuelle 3D-Welt transformiert. Das w entspricht
hier dem Wert, durch den man x, y, und z teilen würde, um die 3D-Position
5.4. KOORDINATENSYSTEME
98
im nichthomogenen Koordinatensystem zu erhalten. Auf diese Weise kann
man 3D-Transformationen später effektiv als 4x4 Matrizen ausdrücken. Diese
haben in den gängigsten APIs Direct3D (World- und View-Matrix) und OpenGL
(Modelview-Matrix) unterschiedliche Bezeichnungen.
Da die 3D-Welt nie vollständig sichtbar ist, muss ein Objekt vom World Space in
den Eye Space transformiert werden oder wird eben direkt vom Object Space in
den Eye Space (siehe Abb. 5.3) transformiert. Dies resultiert aus der Tatsache,
dass wir immer nur von einer bestimmten Position aus den 3D-Raum betrachten.
Um vom World Space in den Eye Space zu transformieren, nutzt man in Direct3D
wieder eine Matrix mit der Bezeichnung View Matrix. In diesem Raum wird die
tatsächliche Position der Kamera (bzw. des Betrachterauges) über die Grafik-API
gesteuert und man schaut nun quasi die negative z-Achse entlang in den Raum auf
die Objekte. Man muss sich das ganze wie eine Blickpyramide vorstellen, deren
oberes Ende abgeschnitten ist (der Anfang des sichtbaren Bereichs) und deren
Boden das Ende des sichtbaren Bereichs darstellt (siehe Abb. 5.3). Dieser Vorgang
wird auch als Clipping bezeichnet.
Abbildung 5.3: Die Blickpyramide in den Eye Space. (Quelle: Extreme Tech)
5.4.3
Clip Space
Als weiteres wichtiges Koordinatensystem gibt es den Clip Space, in dem festgestellt wird, welche Stellen eines Objektes eigentlich sichtbar sind. Ein wichtiger
Unterschied zwischen OpenGL und Direct3D im Clip Space ist die unterschiedliche
Behandlung der Koordinaten. Die x-y-Koordinaten werden zwar gleich behandelt,
die z-Koordinate aber nicht. In OpenGL muss alles an einer Achse ausgerichtet
sein, so dass die x-y-z-Koordinaten immer kleiner oder gleich des w Wertes sind. In
Direct3D dagegen gilt dies nur für die x-y-Koordinaten, während die z-Koordinate
kleiner als der w Wert bis hin zur Null entspricht. Beide Vorgehensweisen setzen
voraus, dass die Clip Space Positionen in homogenen Koordinaten vorliegen, da sie
von w abhängig sind. In diesem Koordinatensystem wird wieder eine 4x4 Matrix
5.5. DIE KLASSISCHE GRAFIK-PIPELINE
99
mit der Bezeichnung Projektions-Matrix genutzt.
5.4.4
Window Space
Während die Clip Space Koordinaten in homogenen Koordinaten vorliegen, müssen
diese im Window Space in normalisierte x-y-Koordinaten transformiert werden, da
unser Bildschirm nur eine 2D-Oberfläche besitzt. Erreichen kann man das durch
das Dividieren von x, y, und z durch w, was man als Perspektivische Zerlegung“
”
(engl.: Perspective Division) bezeichnet [FK03], mit der wir dann die normalisierten
Gerätekoordinaten erhalten. Die Posititionen in OpenGL liegen hier zwischen (-1,1,-1) und (1,1,1), während sie in Direct3D zwischen (-1,-1,0) und (1,1,1) liegen.
Nach der Erläuterung in welchen Koordinatensystemen 3D-Objekte dargestellt
werden, folgt nun eine Betrachtung wie diese in der klassischen Grafik-Pipeline
verarbeitet werden.
5.5
Die klassische Grafik-Pipeline
Ähnlich wie die CPU eine Pipeline mit mehreren Stages besitzt (Vergleich DLXPipeline, bekannt aus der Technischen Informatik), von der jede eine einfache
Aufgabe schnell erfüllt, besitzt auch die GPU auf der Grafikkarte eine Pipeline.
Diese sogenannte Pipelined“-Architekur dient der Aufteilung größerer Aufgaben
”
in kleinere Schritte, um somit eine quasi-parallele Ausführung mehrerer Aufgaben gleichzeitig zu ermöglichen. Bei der GPU bestehen die Aufgaben aus dem
Übernehmen der Daten eines Programms in Form von geometrischen Primitiven
(Punkten, Linien und Polygonen), welche die 3D-Geometrie beschreiben. Diese
Formen werden dann auf einer per-Vertex Basis bearbeitet und vom virtuellen 3DRaum auf den 2D-Bildschirm transformiert.
Der Weg geht dabei vom ersten Polygon (in der Computergrafik werden in der
Regel Dreiecke verwendet) einer Szene bis zum letzten Pixel, den man letztendlich
auf dem Bildschirm sieht. Die Grafik-Pipeline besteht dabei aus mehreren Stufen
( Stages“), die 3D-Objekte in 2D-Bildschirm Objekte transformieren um so am
”
Ende ein gerastertes Bild auf dem Bildschirm auszugeben [Shi05] (siehe Abb. 5.4.
Die Geometrie-Daten der 3D-Objekte, die in die Grafik-Pipeline hinein gehen
lassen sich grob in folgende geometrische Primitive unterteilen [Shi05]:
• Punkte: Einzelne Vertizes um Punkte oder Partikelsysteme zu beschreiben.
5.5. DIE KLASSISCHE GRAFIK-PIPELINE
100
Abbildung 5.4: Grobes Modell der Grafik-Pipeline. (Quelle: Fundamentals of Computer
Graphics Second Edition, Page 380)
• Linien: Paare von Vertizes um Linien oder Silhouetten zu erzeugen oder
Kanten hervorzuheben.
• Polygone: Üblicherweise Dreiecke um über ein Netz aus vielen Dreiecken
geometrische Strukturen zu beschreiben.
Zu beachten ist hier, dass dies die einzigen Geometrie-Daten sind, die in der Pipeline verarbeitet werden. Auch wenn man beispielsweise Splines oder Nurbs 4.5
verwendet, werden die Oberflächen von der Hardware als Polygone behandelt. Die
Kontrollpunkte der Splines oder Nurbs sind in der Pipeline betrachtet primitive
Punkte, die Verbindung zwischen zwei Kontrollpunkten eine Linie und die resultierende Fläche aus drei oder mehr Kontrollpunkten stellen dann ein Polygon dar.
Daraus folgt auch, dass man nur einen endlichen Grad an Rundung erreichen kann.
Die Anwendung selbst (zum Beispiel ein 3D-Spiel oder 3D-Renderer) kann man
als den Anfang der Grafik-Pipeline ansehen. Sie ist zwar rein technisch gesehen
kein elektronischer Bestandteil der Pipeline, von hier gehen jedoch alle Befehle an
die Pipeline aus. An dieser Stelle beginnt das Vertex Processing (Ein Vertex ist der
Eckpunkt eines Polygons) wobei die Geometrie-Daten einigen Transformationen
unterzogen werden, bevor man ein 2D-Bild auf dem Bildschirm rastern kann.
5.5.1
Geometrieoperationen
Der wahrscheinlich wichtigste Teil der Pipeline sind die Geometrieoperationen.
Hier finden verschiedene Transformationen der 3D-Objekte, sowie Operationen, die
den Lichteinfall auf den einzelnen Vertizes bestimmen statt 2.7.3.
Die Eingangsdaten (3D-Objekte) werden zuerst aus dem Object Space in eine einheitliche Form überführt, also in den World Space transformiert. Einige APIs wie
zum Beispiel OpenGL, überspringen diesen Schritt und transformieren über die
Modelview-Matrix direkt in den Eye Space. Mit Direct3D dagegen wird zunächst
über die World-Matrix vom Object Space in den World Space transformiert und erst
dann legt die View-Matrix den Standort und Blickrichtung für den Eye Space fest.
Nachdem man nun den Blickwinkel in die virtuelle Welt berechnet hat, besteht die
5.5. DIE KLASSISCHE GRAFIK-PIPELINE
101
nächste Aufgabe darin, überflüssige Arbeit zu minimieren. Eine Mögichkeit stellt
das Occlusion Culling“ dar, bei dem es darum geht die nicht sichtbaren Objekte
”
zu entfernen. Ein Objekt hinter einer Wand muss man zum Beispiel nicht rendern.
Weitere Methoden sind die Verwendung von Bounding Boxes und dem Objekt-LoD
(engl.: Level of Detail). Dieser Transformation findet über die Projektions-Matrix
im Clip Space statt.
Um die homogenisierten Gerätekoordinaten zu erhalten, sind einige Schritte notwendig. Aus dem homogenen Koordinatensystem müssen die Koordinaten jedes Vertex
normalisiert werden, damit ins endgültige x-y-Koordinatensystem im Windows
Space transformiert werden kann. Es gibt dabei im wesentlichen vier Operationen,
die alle mit Hilfe von Transformations-Matrizen arbeiten.
• Translation: 3D-Objekte können auf einer der drei Achsen verschoben werden.
Mathematisch würde es sich hierbei eigentlich um Addition beziehungsweise
Subtraktion handeln, aus Effizienzgründen nutzt man diese Transformationen
jedoch so, dass sie über Matrizenmultiplikation funktionieren.
• Rotation: 3D-Objekte können um eine der drei Achsen gedreht werden. Einfachste mathematische Operation, wenn das Objekt bereits im Ursprung des
Koordinatensystems liegt, ist hier die Multiplikation jeder Koordinate mit
dem Sinus oder Cosinus von Theta. Theta ist die Gradzahl, um die das Objekt
gedreht werden soll. Sollte eine Drehung um mehrere Achsen erforderlich
sein, ist auch die Reihenfolge der Rotationen zu beachten, da es dabei zu
unterschiedlichen visuellen Ergebnissen kommen kann.
• Skalierung: 3D-Objekte müssen auch skaliert werden um deren Größe in
der Nähe und Entfernung zu unterscheiden. Mathematisch gesehen wird die
Veränderunggröße in den Diagonalelementen der Skalierungs-Matrix angegeben. Verwendet man zum Beispiel den Wert 0,5 in der Diagonalen einer 2x2
Matrix wird das Objekt in seiner Größe halbiert. Nutzt man unterschiedliche
Werte spricht man von der nicht-uniformen Skalierung.
• Skewing: Skewing (Shearing) ist wichtig, da es ja auch elastische Objekte
in einer 3D-Welt geben kann, wie etwa einen Ball der beim aufprallen auf
eine Wand zusammengequetscht wird. Mathematisch realisiert man dies zum
Beispiel durch das addieren des x-Achsenwerts zum y-Achsenwert während
man den x-Achsenwert unverändert belässt.
5.5. DIE KLASSISCHE GRAFIK-PIPELINE
102
Abbildung 5.5 zeigt ein Grundmodell wie diese Transformations-Matrizen aussehen.
Abbildung 5.5: Typische Transformations-Matrizen für ein 3D-Objekt. (Quelle: Extreme
Tech)
5.5.2
Pixeloperationen
Der weitere Verlauf der Grafik-Pipeline ist nicht eindeutig, da manche Quellen das
sogenannte Polygon-Setup zur Rasterisierung zählen und andere es als eigenständige
Stufe in der Pipeline ansehen [Inc07]. Hier wird das Polygon-Setup als Vorstufe zur
Rasterisierung betrachtet. Es wird zunächst die Neigung der einzelnen Polygone anhand der Vertex-Information am Ende der Kanten berechnet. Dies ist nötig, um die
x-y-Werte für jedes Polygon zu berechnen. Durch diese Berechnung kann man das
linke und rechte Ende jedes Polygons erfassen. Diesen Bereich der Scan-Line“ (es
”
wird Zeilenweise gearbeitet) nennt man auch Span [Wat93]. Das daraus resultierende Scan-Line Diagramm, welches die Spans enthält, wird für die Pixeloperationen
benötigt.
In diesem Bereich der Grafik-Pipeline liegt der Übergang vom Vertex-Processing
(Verarbeitung) zum Pixel-Processing. Auch hier wird wieder unnötige Arbeit eingespart, indem durch den sogenannten Depth-Test festgestellt wird, ob ein Pixel
überhaupt sichtbar ist. Hier findet beispielsweise auch das Texture Mapping statt,
bei dem jeder Pixel mit einem Texel in Verbindung gebracht wird. Nachdem die
Rasterisierung abgeschlossen ist, werden die endgültigen Pixel in den Framebuffer
geschrieben.
Einen völlig neuen Ansatz des Grafikkartenaufbaus, der auf das klassische GrafikPipeline Modell verzichtet, finden wir erstmals in der G80-Grafik-Architektur von
nVidia.
5.6. DIE UNIFIED-SHADER ARCHITEKTUR
5.6
103
Die Unified-Shader Architektur
Die große Neuerung, die erstmals mit der G80-Architektur eingeführt wurde, ist
das sogenannte Unified“ Design. Der Entwickler nVidia spricht vom Unified,
”
”
Massively Parallel Shader Design“ [nVi06a]. Die 8800 GTX war die erste Grafikkarte, die auf dieser Architektur aufgebaut hat. Einen Überblick gibt das Diagramm
in Abbildung 5.6. Die neueren Modelle der für den Desktop-Einsatz gedachten
Grafikkarten von nVidia und auch AMD (ATI) bauen nur noch auf diese Architektur
auf.
Abbildung 5.6: GeForce 8800 GTX Block Diagramm. (Quelle: nVidia [nVi06b])
Das besondere an diesem Unified-Design ist der Ersatz der bekannten und relativ
restriktiven Pipeline-Architektur durch eine Vielzahl von Stream-Prozessoren (SPs).
Aus technischer Sicht ist ein SP ein Koprozessor, der Datenströme verarbeiten kann.
Die Spezialisierung auf hohe Parallelisierung dieser Koprozessoren spiegelt sich
auf einer Grafikkarte in der großen Anzahl wider (8800 GTX 128 SPs bis HD
3870 mit 320 SPs). Ein einzelner SP kann als skalare Recheneinheit angesehen
werden, die einzelne skalare Rechenoperationen an einem Datenstrom (welcher
vorher die Pipeline passieren musste) durchführt. Schaltet man mehrere dieser skalaren Recheneinheiten zusammen, so sind auch die für Grafikkarten interessanten
Vektorverarbeitungen möglich. Der Begriff der Unified-Shader“ kommt nun da”
her, dass die Grafikkarte nicht mehr einzelne Vertex- und Pixel-Pipelines besitzt,
sondern jeder SP Aufgaben für Vertex-, Fragment- und auch die neu eingeführten
Geometry-Operationen durchführen kann, wodurch sich die GPU dynamisch an die
aktuellen Anforderungen der Anwendung anpassen kann. Was diese Begriffe im
einzelnen bedeuten, folgt nach einem weiteren Überblick über die neue Architektur.
Durch die Veränderung der Architektur ändert sich auch der sequentielle Datenfluss
auf der GPU. So werden nicht mehr wie beispielsweise bei der GeForce 7 über 200
sequentielle Pipeline-Stages allein für den Pixel-Shader benötigt, sondern stattdessen die Anzahl der einzelnen Schritte stark reduziert um die effiziente Nutzung von
5.6. DIE UNIFIED-SHADER ARCHITEKTUR
104
Loops“ zu ermöglichen. In der Programmierung spricht man von Loops wenn eine
”
Befehlssequenz die einmal spezifiziert wurde, mehrmals hintereinander ausgeführt
wird. Durch die Nutzung der Loops kann so ein durch eine Befehlssequenz verarbeitetes Datum viel schneller wieder verwendet werden, als wenn es erst die gesamte
Grafik-Pipeline durchlaufen müsste. Wie man sich das bildlich vorstellen kann, ist
in Abbildung 5.7 zu sehen.
Abbildung 5.7: Vergleich einer gewöhnlichen Pipeline mit Loops in einer UnifiedArchitektur. (Quelle: nVidia [nVi06b])
Die Vereinheitlichung“ der Shader, also dass jede Shader-Einheit für alle
”
Shader Operationen genutzt werden kann, bringt noch weitere Vorteile mit sich. Die
aktuell anfallenden Anfragen einer Anwendung können in ihrer Anforderung an
Vertex- und Fragment-Shader variieren. In der Regel ist die Zahl der Pixel zwar
größer als die der Vertizes - was der Grund ist, warum auf den alten Grafikkarten
mehr Pixel-Shader als Vertex-Shader verbaut waren - es gibt aber genauso Szenen,
bei denen dies nicht der Fall ist. So kann auch im untypischen Fall das die Zahl
der Vertizes überwiegt, die Rechenleistung maximal dafür genutzt werden und
so die Gesamt-Effizienz erhöht werden. Will man zum Beispiel ein großes MeshModell, das mehr Vertizes besitzt, als Pixel auf dem Monitor angezeigt werden
(hohe Vertex-Shader Last) und ein hochauflösendes Bild (hohe Fragment-Shader
Last), dann wird der Unterschied in den Anforderungen deutlich wenn man bedenkt,
dass nun nicht mehr im einen Fall beispielsweise nur 4 Vertex- und im anderen
Fall 8 Pixel-Shader zur Verfügung stehen, sondern 12 Unified-Shader für beide
Operationen. Die Shader-Einheiten können nun auch mit verkürzten Leerlauf-Zeiten
arbeiten, da die GPU theoretisch für jede Aufgabe voll genutzt werden kann und
nicht immer nur für jeweils eine Teilaufgabe wie in Abbildung 5.8 gezeigt wird.
Auch das Branching wurde bei der neuen Architektur verbessert. Ein Branch ist
5.6. DIE UNIFIED-SHADER ARCHITEKTUR
105
Abbildung 5.8: 3D-Transformationen (Mathematische Operationen) und TexturOperationen können gleichzeitig ausgeführt werden. (Quelle: nVidia [nVi06b])
ein Punkt in einem Computer Programm, wo der Programmfluß abhängig von einer
Bedingung geändert wird (zum Beispiel if-then-else). Wurde bei alten Grafikkarten
mit DirectX 9 Shadern eine Grafik mit 10000 Pixeln geladen und dann aufgrund
eines if-then-else Statement festgelegt, an welchen Stellen eine bestimmte Operation
stattfinden sollte und an welchen nicht, so wurden die gesamten 10000 Pixel auf
einmal abgearbeitet. Dabei wird anhand der gesamten Pixel zweimal geprüft ob
die Bedingung zutrifft. Einmal für die Frage nach dem Zutreffen und einmal für
die Frage nach dem nicht Zutreffen. Es handelt sich also eigentlich um doppelte
Arbeit. Die neue Architektur nutzt dagegen eine Granularität von 16-32 Pixeln (bei
AMD X1950 XTX 48 Pixeln was nVidia als zu ungenau bezeichnet). So kann die
Abarbeitung einer Grafik mit 10000 Pixeln auf die SPs verteilt werden, was zu
einem deutlichen Performance-Schub führt.
Mit der Einführung dieser Architektur wurde von nVidia vor allem auch darauf
Rücksicht genommen, dass moderne 3D-Anwendungen performante Shader unter verschiedensten Voraussetzungen benötigen, daher nun eine etwas genauere
Betrachtung wie sich das Shader Model bis heute entwickelt hat.
5.6.1
Das Shader Model
Ein Shader ist ein Programm, das von den Grafikquellen hauptsächlich für das
Rendering benutzt wird, um die endgültige Oberfläche eines Objektes oder Bildes zu erzeugen. Programmierer können mit den Shadern also die Grafikausgabe
programmieren, die man später auf seinem Bildschirm sieht. Die veraltete Form
der Grafik-Pipeline hat man hier als fixed-function-pipeline“ bezeichnet, da alle
”
Bauteile auf eine bestimmte Funktion ausgelegt und somit nicht individuell programmierbar waren. Eine moderne Grafik-Pipeline bezeichnet man dagegen als
programmable-pipeline“, die durch die Programmierbarkeit mehr Flexibilität mit
”
sich bringt. Da nichts ohne Spezifikationen plattformübergreifend funktionieren
kann, gibt es das Shader Model (Aktuell in der Version 4.0). Das Shader Model ist
5.6. DIE UNIFIED-SHADER ARCHITEKTUR
106
eine Zusammenfassung von Instruktionen unter Verwendung einer ISA (Instruction
Set Architecture). Es werden dabei Befehle für alle Shader-Typen, also Vertex- und
Fragment-Shader und seit der Version 4.0 auch Geometry-Shader zusammengefasst.
Aufgrund der neuen Architektur seit den G80-GPUs redet man hier auch von der
Unified ISA. Dieser Befehlssatz erleichtert Programmierern ihre Arbeit ganz erheblich.
Das Shader Model existiert bereits seit einigen Jahren (Vertex- und FragmentShader wurden 2001 eingeführt) und hat seit seiner Einführung an Komplexität
zugenommen. Zu Beginn erlaubte das Shader Model nur einfache arithmetische
und boolesche Operationen. Die Verwendung von Loops war zwar auch in älteren
Versionen möglich, aber sehr aufwändig und nicht effizient. Es waren meistens nur
eine begrenzte Anzahl an Iterationen möglich und für je eine bestimmte Anzahl
Iterationen musste ein separater Shader programmiert werden. Auch die Verwendung von Branches unterlag zu dieser Zeit noch größeren Problemen wie zum
Beispiel Hazards (Hazards werden in diesem Foliensatz erklärt [uotad99]). Der
Hauptunterschied der aktuellen Version 4.0 gegenüber dem Vorgänger 3.0 ist die
Vereinheitlichung ( Unification“ - deswegen Unified-Architektur) der Shader, so
”
dass es keine Unterschiede mehr zwischen Pixel- und Vertex-Shadern gibt. Neu
eingeführt wurden die Geometry-Shader, die es erlauben Vertizes auf der GPU zu
erzeugen. Diese Berechnungen musste bisher die CPU übernehmen, was zu einer
höheren Belastung des Gesamtsystems geführt hat und zudem ist die CPU nicht
für Grafik-Operationen optimiert. Darüber hinaus ist es nun möglich Ressourcen
zu virtualisieren, was man sich in etwa wie den virtuellen Speicher auf der GPU
vorstellen kann. Insgesamt soll das Shader Model 4.0 also mehr Freiheiten beim
Programmieren schaffen und noch flexiblere Möglichkeiten für Programmierer
bieten, als die programmable-pipeline“ dies bisher tut.
”
5.6.2
Shader Programmierung
Zu Beginn wurden Shader nur über die Assembler-Sprache (Maschinencode) der
GPU programmiert. Das ermöglichte zwar die volle Kontrolle über die GPU, war
aber sehr schwerfällig und kompliziert in der Verwendung. Deswegen wurde von
nVidia Cg (C for Graphics) entwickelt. Eine Hochsprache, die es einfacher macht
ein Programm zu programmieren und später zu lesen. Cg Code ist auch portabel auf
unterschiedliche Plattformen, während Assembler für gewöhnlich von der Hardware,
für die es geschrieben wurde, abhängig ist. Darüber hinaus übernimmt der Cg Compiler einige Optimierungen selbst und führt einige Operationen auf unterster Ebene
5.6. DIE UNIFIED-SHADER ARCHITEKTUR
107
von selbst durch, die mit Assembler noch kompliziert von Hand gemacht werden
mussten. Cg wurde in enger Zusammenarbeit mit Microsoft entwickelt und wurde
unter anderem bei den aktuellen Spielen Far Cry und Quake Wars genutzt. Die
zwei bedeutendsten APIs bieten zudem eigene Hochsprachen, um auf Instruktionen
die im Shader Model 4.0 spezifiziert sind, zuzugreifen. Von Microsoft stammt die
High Level Shader Language“ (HLSL) zur Verwendung mit der Direct3D API die
”
im ersten echten DirectX 10 Spiel Crysis Anwendung findet. OpenGL spezifiziert
eine eigene OpenGL Shading Language“ [Fou06a]. DirectX (Bestandteil unter
”
anderem Direct3D) führt das Shader Model 4.0 in der aktuellen Version 10 ein, die
nur unter Windows Vista zur Verfügung steht. OpenGL dagegen ist beispielsweise
auch auf UNIX- und Apple-Plattformen nutzbar.
Ein Shader besteht aus einem Array an Strings mit dem Quellcode für die jeweiligen Operationen, die angewendet werden sollen (zum Beispiel Operationen
auf Vertex Basis mit dem Vertex-Shader). Um diesen Code zu nutzen, wird etwa
nach der OpenGL Shading Language Spezifikation der Quellcode zunächst in ein
Shader-Objekt“ geladen und dann kompiliert. Es können dann ein oder mehrere
”
Vertex-Shader-Objekte“ mit einem Programm-Objekt verknüpft werden, welches
”
dann einen ausführbaren Code aus allen mit dem Programm verknüpften ShaderObjekten generiert.
Die Vertex- und Fragment-Shader sind dabei aus der alten Grafik-Pipeline Architektur vom Grundprinzip her übernommen worden. Neu eingeführt wurden die
Geometry-Shader. Was diese Shader machen wird im folgenden erklärt.
5.6.3
Vertex- und Fragment-Shader
Was als Datenstrom (Eingabe) in den Vertex-Shader kommt, sind die 3DObjektdaten mit der Position jedes Vertex mit Farben und Texturkoordinate. Der
Vertex-Shader ist dabei zuständig für Transformationen mit den bereits beschriebenen 4x4 Matrizen. In OpenGL sind Vertizes immer mit zwei, drei oder vier
Dimensionen deklariert. Die x- und y-Achse bilden die erste und zweite und die
z-Achse die dritte Dimension. Eine vierte Koordinaten-Dimension wird dazu genutzt, um die Entfernung eines Objekts zur Kamera zu steuern. Zusätzlich werden
Farbe (Color) und eventuell auch eine Sekundäre Farbe (SecondaryColor) definiert.
Die homogenisierten Werte der Texturkoordinaten werden über TexCoord oder bei
mehreren Texturen über MultiTexCoord spezifiziert. Für die Tiefenwerte (etwa für
Gegenstände im Nebel) kann man dann noch die FogCoord definieren. Es gibt in
OpenGL noch eine Reihe weiterer Attribute für Vertizes, die hier genutzt werden
5.6. DIE UNIFIED-SHADER ARCHITEKTUR
108
können. Die Daten für jeden einzelnen Vertex können dann in einem Vertex-Array
abgelegt werden, der im Adressraum des Computers liegt. Verschiedene Blöcke
aus diesem Array können dann über einen einzigen OpenGL Befehl als primitive,
geometrische Figur ausgegeben werden womit man wieder über die Position, Farbe
und Texturkoordinaten eines Vertex (Ausgabe) zur weiteren Verarbeitung verfügt.
Ein Vertex-Shader steuert Informationen über Lichtquellen, Materialien und Matrizen. Die Operationen, die im Vertex-Shader stattfinden, sind zum Beispiel die
Beleuchtung der Eckpunkte oder die Animation von verschiedenen Oberflächen. Im
Ablauf des Bildaufbaus befinden wir uns nun beim Rastern, wo die Koordinaten aus
der 3D-Welt auf den 2D-Bildschirm interpoliert werden. Wichtig ist auch, das ein
einzelnes Objekt sowohl Vertex- und Fragment-Shader enthalten kann.
Der Fragment-Shader (auch als Pixel-Shader bezeichnet) erhält als Eingabe pro
Pixel die interpolierte Farbe und Texturkoordinaten. Fragment-Shader werden vor
allem dazu genutzt, einzelne Fragmente zu manipulieren und mit bestimmten Effekten zu versehen. Das wäre etwa das Bump Mapping (wie zum Beispiel in Abbildung
5.9), Schatten (Shadow Maps) oder Nebeleffekte (Alpha Compositing).
Abbildung 5.9: Eine durch Bump Mapping erzeugte Oberfläche, um eine Kugel als Orange
darzustellen. (Quelle: Wikipedia)
Das Texturieren ist der wichtigste Teil dieses Shaders. Für die Textur wird ein
Bild an die Stelle der Texturkoordinaten gerendert, wobei jedes Fragment mehrere
solcher Texturkoordinaten enthalten kann. Diese werden genutzt um ein oder mehrere Texturbilder einzusetzten um die endgültige Farbe zu modifizieren um so als
Ausgabe dann einen Pixel mit dieser Farbe zu erhalten.
Der Fragment-Shader arbeitet im Gegensatz zum Vertex-Shader auf einer per Pixel
5.6. DIE UNIFIED-SHADER ARCHITEKTUR
109
Basis und kann deshalb sehr viel aufwändiger sein. Bei einer Full HD Auflösung
(1920x1080 Pixel) kommt man bereits auf 2 Millionen Pixel. OpenGL greift
beim Rastern auf Fragment-Shader für verschiedenste Effekte zurück (Antialiasing, Points, Line Segments, Polygons, Pixel Rectangles, Bitmaps, Texturing, Color
Sum, Fog [Fou06b]).
Zusammenfassend kann man also sagen, dass die statischen Funktionen der GrafikPipeline mit Hilfe von Shader-Programmen an die eigenen Bedürfnisse angepasst
werden können. Eine Übersicht über den Zusammenhang zwischen dem klassischen
Vertex- und Fragment-Shader gibt Abbildung 5.10.
Abbildung 5.10: Zusammenhang von Vertex- und Fragment-Shader. (Quelle: Stevens Institute of Technology)
5.6.4
Geometry-Shader
Neu eingeführt im Shader Model 4.0 wurden die Geometry-Shader. GeometryShader sind auch ein neues Feature von DirectX 10 und steht daher unter Windows
erst seit Vista zur Verfügung. Somit ist dies auch eine der besonderen Neuerungen
der G80-Architektur. Die Geometry-Shader werden nach dem Transformieren der
Vertizes durch den Vertex-Shader ausgeführt (siehe Abb. 5.11), aber vor dem
Pixel-Processing.
Abbildung 5.11: Die Reihenfolge in der die Shader ausgeführt werden. (Quelle: nVidia)
5.7. GENERAL PURPOSE COMPUTATION ON GPUS
110
Ein Geometry-Shader hat einen festen, primitiven Ausgabetyp (Punkt-, Linienoder Dreiecksfolge) und verzichtet auf Vertizes, um neue Objekte zu definieren. Ein
Geometry-Shader kann dabei mehrere nicht verbundene Objekte ausgeben, die dann
wie gewöhnliche von der Anwendung definierte Objekte weiter behandelt werden.
Zum Beispiel wird mit diesem neuen Objekt auch ein Clipping-Test gemacht. Was
durch die neuen Geometry-Shader ermöglicht wird, sind etwa sehr realistische
menschliche Charaktere mit ausgeprägten Gesichtszügen, natürlichen Schatten und
physikalisch korrekten Bewegungen. So kann man über diese Shader ganze Objekte
einfacher kontrollieren oder auch zerstören (etwa bei einer Explosion). Ein hoher
Performance-Gewinn ist vor allem deshalb gegeben, weil aufwändige physikalische
Berechnungen, wie beispielsweise die Bewegung einer Wasseroberfläche nicht mehr
von der CPU berechnet werden müssen, sondern von der GPU berechnet werden
können. Mit Hilfe dieses Shader-Typs lassen sich auch nicht feste Objekte wie
Rauch oder der Feuerball einer Explosion sehr viel einfacher und detaillreicher
darstellen.
5.7
General Purpose Computation on GPUs
Wie bereits in der Einleitung angekündigt, kann eine moderne GPU nicht mehr nur
zu Grafikdarstellung auf dem Bildschirm genutzt werden. Im Allgemeinen spricht
man hier von General Purpose Computation on Graphics Processing Units“ (GPG”
PU). Durch die gestiegene Flexibilität bei der Programmierbarkeit von GPUs und
der höheren Präzision in der Arithmetik, sind nun auch nicht grafische komplexe
Algorithmen auf der GPU denkbar [Fou07]. Heute hat man mehr Möglichkeiten aufgrund der erweiterterten Funktionalität der GPUs. Die auf modernen Grafikkarten
verbauten SPs sind sehr effizient bei Berechnungen eines konstanten Eingabeda”
tenstroms“ (input stream), während sie gleichzeitg die Rückgabewerte in einem
Ausgabedatenstrom“ (output stream) liefern, welcher wieder von anderen SPs
”
genutzt werden kann. Besonders bei komplexen Aufgaben, die aufwändige Berechnungen erfordern, ist diese Art der Abarbeitung des Datenstroms von Vorteil. Die
neuesten Modelle bieten sogar 320 SPs (AMD HD 3870 Grafikkarte), die eine spezialisierte und sehr schnelle instruction decode“ und execution logic“ eingebaut
”
”
haben. Mathematisch gesehen handelt es sich bei disen SPs um sogenannte skalare
Prozessoren, die ein Datum auf einmal enthalten und mit Floating Point Einheiten
arbeiten. Ein Speicher direkt auf den Chips wird gewöhnlich genutzt, um die Ausgabe zu speichern und kann so extrem schnell von anderen SPs genutzt werden.
5.7. GENERAL PURPOSE COMPUTATION ON GPUS
111
Die hohe Anzahl an vorhanden SPs und die daraus resultierende hohe Parallelität
bringt große Vorteile bei der Verarbeitung von Vektoren wie sie bei Grafik-Streams
vorkommen, aber eben auch bei anderen Anwendungen.
5.7.1
Nutzung des skalaren Prozessor Designs
Frühere GPUs haben keine skalaren Prozessoren benutzt, sondern vektorbasierte
Prozessoren, da bei grafischen Operationen sehr viele Matrizen genutzt werden.
Jedoch treten auch sehr viele skalare Operationen auf, zum Beispiel wenn man
zum Aufhellen eines Bildes einen Wert zum Alpha-Wert hinzu addiert. Warum es
bei einem Umstieg auf skalare Prozessoren bei grafischen Anwendungen nicht zu
einem Verlust an Leistung kommt liegt daran, dass man viel mehr davon auf einen
Chip bekommt, da sie viel kleiner sind. Vektorbasierte Prozessoren sind sogenannte 4-Komponenten Prozessoren und benötigen mehr Platz. Dieses Umdenken im
Architektur-Design hat nun maßgeblich dazu geführt, dass eine GPU auch insbesondere für andere mathematische Operationen effizient genutzt werden kann, da nun
auf Basis von Floating Point Werten gearbeitet wird. Einen Vergleich des möglichen
Leistungsunterschieds bei solchen Berechnungen zeigt Abbildung 5.12
Abbildung 5.12: Vergleich der theoretischen Rechenperformance von GPU und CPU.
(Quelle: CUDA Documentation)
Ein Problem besteht jedoch darin, dass wissenschaftliche Anwendungen oft
64-Bit Floating Point Werte benötigen (Double Precision Float) die auf CPUs in
der Regel auch verfügbar sind. Bisherige GPUs können aber nur 32-Bit Float Werte
darstellen. Es gibt allerdings Anstrengungen Double Precision Float auf GPUs zu
emulieren [DG05] und AMD ist auch gerade dabei einen SP der über diese Fähigkeit
verfügt, unter dem Namen FireStream zu entwickeln.
Die dabei verwendeten Instruktionen nennt man auch SIMD (single instruction/multiple data). Der Vorteil dieser Programmierweise zeigt sich dann, wenn
5.7. GENERAL PURPOSE COMPUTATION ON GPUS
112
man beispielsweise einen festen Wert mit einer mathematischen Operation auf eine
lange Reihe beliebiger Werte anwenden möchte. Der Vorteil von SIMD ist hier das
die Daten als Block betrachtet werden und so mehrere Werte gleichzeitig bearbeitet
werden können, anstatt einen Pixel nach dem anderen abzuarbeiten. Da das Anwendungsgebiet in der Computergrafik bereits bekannt ist, nun eine Betrachtung der
Anwendung im wissenschaftlichen Bereich. So kann man sich beispielsweise in
der Medizin einen Genstrang als Array vorstellen, der wieder in mehrere kleine
MicroArrays unterteilt werden kann und so schnell von der GPU Genomanalysen
ausgeführt werden können.
Ein praktisches Anwendungsbeispiel und womit man solche Anwendungen eigentlich programmiert wird im folgenden gezeigt.
5.7.2
GPGPU in der Praxis
Anwendung findet GPGPU zum Beispiel in der Kryptographie für
RSA-Algorithmen [MPS07]. RSA ist ein sogenanntes Public-Key Verschlüsselungsverfahren. Es war der erste Algorithmus, der sowohl zum Signieren,
als auch Verschlüsseln geeignet war. Die Verschlüsselung ist sicherer wenn man
längere Schlüssel verwendet. Steigert man die Ausführungsgeschwindigkeit des
Algorithmus, kann man in gleicher Zeit höhere Sicherheit gewähren, weshalb hier
das Portieren auf die GPU auch besonders interessant ist. Ohne näher auf die
angewandten Formeln einzugehen, kann mann sagen, das RSA unter anderem mit
vielen modulo Operationen und großen Primzahlen arbeitet. Für solche modulo
Operationen mit Primzahlen gibt es verschiedene mathematische Verfahren. Hier
kommt nun besonders das SIMD Instruction Set zu tragen, da eine Operation
auf viele Datenelemente angewendet wird, wofür die GPU wie bereits mehrfach
erwähnt, sehr gut geeignet ist.
Ein weiteres Anwendungsbeispiel ist das Projekt Folding@home der Stanford
University [Uni07]. In diesem Projekt geht es darum sehr aufwändige Berechnungen zur Faltung und Entfaltung von Proteinen durchzuführen, um so deren
Zusammenhang mit der Entstehung von Krankheiten zu erforschen. Dabei wird
ein Client Programm auf möglichst vielen PCs installiert, um so einen virtuellen
Computer Cluster zu erhalten. Im Gegensatz zum ebenfalls bekannten SETI@home
Projekt wird hier für die Berechnungen die GPU genutzt. Datenelemente, die dabei
benutzt werden sind zum Beispiel Ketten von Aminosäuren die als Array dargestellt
werden können. Da bei diesen Berechnungen auch wieder konstante Operationen
auf eine Vielzahl von Datenelementen angewendet wird, kommt hier wieder der
5.7. GENERAL PURPOSE COMPUTATION ON GPUS
113
Vorteil der GPU gegenüber der CPU zu Tage.
5.7.3
Compute Unified Device Architecture
Der Grafikchiphersteller nVidia, der auch die Unified-Architektur für GPUs als
erster eingeführt hat, hat im November 2006 eine eigene API entworfen die Programmierern im GPGPU Bereich eine einfache Schnittstelle bieten soll. Das Problem
war bisher, das die gängigen Grafik-APIs wie Direct3D und OpenGL auf die klassischen in der Computergrafik angewandten Operationen ausgelegt sind und nicht
zur GPU-Programmierung geeignet sind. Diese neue API von nVidia die für die
Programmierung unter C/C++ entwickelt wurde, bietet Programmierern nun eine
Schnittstelle um auch andere Algorithmen besser auf die GPU zu portieren. Die API
nenn sicht kurz CUDA (Compute Unified Device Architecture) und funktioniert derzeit nur mit der 8000er Serie von nVidia Grafikkarten. AMD bietet für seine GPUs
die API CTM (Close to Metal) an. Als Beispiele für die Hauptanwendungsgebiete
der API führt nVidia hier Forschung und Sprachentwicklung an.
Die vier Hauptmerkmale der CUDA API sind:
• Die hohe Performance bei rechenintensiven Anwendungen.
• Der Hersteller garantiert die Kompatibiltät mit zukünftigen GPUs von Anwendungen, die mit dem CUDA C-Compiler erzeugt wurden.
• Die Anwendbarkeit der etablierten C-Programmiersprache soll für hohe Produktivität sorgen.
• CUDA Anwendungen sind frei skalierbar und funktionieren sowohl mit
einfach Budget-Versionen von CUDA GPUs, wie auch in speziellen Clustern
mit vielen verbundenen GPUs.
CUDA beinhaltet auch eine Assembler-Sprache (Maschinencode Sprache) und ein
Treiber Interface [nVi07] (CTM beinhaltet diese Erweiterungen ebenfalls). Der Hersteller bietet zu diesem Zweck auf seiner Webseite auch ein SDK-Paket (Software
Development Kit) an, das Entwicklern hilft, auf CUDA-fähigen GPUs Anwendungen zu entwickeln.
Aufgrund der Art und Weise wie eine Grafikkarte funktioniert, ist sie besonders Effektiv beim lösen von Problemen, die über einen einheitlichen Datenstrom realisiert
werden können. So können GPUs nur Vertizes und Fragmente verarbeiten, davon
jedoch sehr viele gleichzeitig. Eine optimale GPGPU Anwendung verwendet daher
5.7. GENERAL PURPOSE COMPUTATION ON GPUS
114
große Datensätze (zum Beispiel einen Genstrang als Array), nutzt die Parallelität
von vielen SPs und sorgt dafür, dass eine möglichst geringe Abhängigkeit zwischen
Elementen herrscht, da sonst zuviele Speicherzugriffe benötigt werden bei denen
die GPU gegenüber der CPU zur Zeit keine Vorteile mit sich bringt.
5.7.4
Diskussion
Was bei allem Enthusiasmus über diese neue Technologie jedoch auch bedacht werden muss, sind ökologische und ökonomische Bedenken. Auch wenn durch den mit
CUDA mitgelieferten C-Compiler theoretisch sehr viele existierende Programme
auf die GPU portiert werden könnten, muss ganz klar gesagt werden, dass dies
nicht sinnvoll ist. Zum Beispiel ist Programmcode der mit vielen Strings und viele
voneinander abhängige Datenelemente einsetzt auf der CPU sehr viel schneller
auszuführen. Ist eine große Datenabhängigkeit gegeben ist mit vielen Speicherzugriffen zu rechnen, wobei eine moderne CPU durch einen größeren L2-Cache
(Ein Cache-Speicher direkt auf dem Prozessor) der GPU gegenüber im Vorteil ist.
Zudem sind die SPs nicht für die Verarbeitung von Strings ausgelegt sondern zum
Rechnen mit Floating Point Werten und Matrizen. Wichtig ist auch, dass eine moderne Highend-GPU sehr viel mehr Strom benötigt als eine CPU. Ein Core 2 Duo
beispielsweise kommt mit weniger als 60 Watt aus, während eine 8800 GTX knapp
150 Watt benötigt und auch die neuen HD 3870 Modelle mit speziellem Power
Management benötigen unter Last immer noch knapp über 100 Watt. Es sollte
also gut überlegt werden, ob ein Algorithmus auf der GPU genutzt werden sollte
wenn dieser nur minimal schneller ist. Einen Kostenvorteil, den GPUs gegenüber
CPUs haben, ist wiederum die leichtere Einsetzbarkeit von mehreren Grafikkarten. Jedes moderne Mainstream-Mainboard (die Hauptplatine im PC) unterstützt
mindestens zwei Grafikkarten, die einfach zusammengeschaltet werden können.
nVidia bezeichnet diese Technologie als SLI (Scalable Link Interface) und bei
AMD heißt das ganze Crossfire. nVidia bietet auch spezielle für CUDA optimierte
Rechen-PCs“ (Tesla GPU Computing Processor) die mehrere Grafikkarten in einem
”
kompakten System vereinigen und im wesentlichen nicht für Grafik sondern für
wissenschaftliche Berechnungen gedacht sind. Im Filmbereich finden diese Maschinen dennoch Einsatz, da hier teils sehr hoher Renderaufwand, der nicht mit Spielen
oder einfachen 3D-Grafiken auf Desktop PCs vergleichbar ist, anfällt.
5.8. FAZIT
5.8
115
Fazit
Nun kennt man den Ursprung der ersten Grafikkarten in PCs und hat grob den
Aufbau einer modernen Grafikkarte gesehen. Die bisher existierende Grafik-Pipeline
Architektur wurde gezeigt und wie man dort in den verschiedenen Pipeline Stages
3D-Objekte und Welten transformieren kann. Zudem haben wir auch Einblicke in
die mit der G80-Architektur eingeführte Unified-Shader Architektur gewonnen und
das Thema der General Purpose Computation on GPUs kennengelernt, welches in
Zukunft sicher ein stark wachsendes Segment im Entwicklungsbereich darstellt.
Kapitel 6
Computer Animation
Jonas Fehr
6.1
6.1.1
Einleitung
Was ist Animation?
Das Wort Animation stammt vom lateinschen animare (zum Leben erwecken) ab.
Hier geht es darum, “lebendige” Bilder zu schaffen. Unterschiedlichsten AnimationsMethoden ist eins gemeinsam: nämlich, dass sie Folgen von Momentaufnahmen
aneinanderreihen, um den Eindruck einer flüssigen Bewegung zu erzeugen.
Bekanntlich können wir zwischen flüssigen Bewegungen und Sequenzen von
Momentaufnahmen eines Ablaufs ab einer bestimmten Bildrate nicht mehr unterscheiden. Ab welcher Bildrate diese Illusion eintritt hängt auch davon ab, wie groß
die Änderungen zwischen den Bildern sind und wie (un-)scharf die einzelnen Bilder
sind, aber rund dreißig Bilder pro Sekunde ist eine gute Größenordnung.
Reduzieren wir im folgenden Animation darauf, Sequenzen von Einzelbildern
zu erzeugen, die jeweils eine Momentaufnahme eines zeitlichen Ablaufs darstellen. Dann besteht das Problem darin, zu bestimmen, was in einem Einzelbild zu
gegebenem Zeitpunkt dargestellt wird, und dieses Bild zu erzeugen.
6.1.2
Klassische Animationstechniken
Während es beim Filmen reicht, in Intervallen eine arrangierte Szene zu belichten,
muss beim Animieren i.d.R. die Szene für jedes Bild gestellt werden.
Im Schwerpunkt soll es in dieser Ausarbeitung um computergestützte Animation
116
6.1. EINLEITUNG
117
Abbildung 6.1: Frames eines Bewegungsablaufs
gehen, aber es lohnt sich ein Blick auf ältere Animationstechniken, da einige
Parallelen existieren und sich mit ihnen manche Problemstellung für die RechnerGestützte 3D-Animation veranschaulichen lässt.
Beim Puppentrickfilm oder Knetfigurenfilm entsteht Bewegung dadurch, dass
Akteure und Gegenstände von Hand in Pose gesetzt werden und eine Aufnahme
gemacht wird. Das ganze wiederholt sich ständig, wobei der Folgezustand die Szene
zeitlich versetzt um einen Bruchteil einer Sekunde darstellt. Das ist intuitiv aber
es ist offensichtlich sehr zeitaufwändig, längere Szenen zu erzeugen. Immerhin
müssen die Modelle nicht für jedes Bild neu erzeugt werden.
Beim Zeichentrickfilm werden einzelne Bilder gezeichnet. Mit einigen Tricks
lässt sich die Effizienz der Animatoren steigern. Etwa indem man mit mehreren
Lagen transparenter Folien arbeitet und Bild-Sequenzen von einzelnen Teilen wiederverwendet: so kann man gezeichnete Figuren vor diversen Hintergründen bewegen, usw.. Zeichentrick-Animation wurde immer ausgefeilter und fließbandmäßig
organisiert: um die Ressource ’talentierte Zeichner’ effektiver zu nutzen, ließ man
sie nur die Schlüßel-Posen zeichnen (Key-Framing), eine größere Anzahl Zeichner
zeichneten die In-Between-Frames (Tweening) und wiederum andere kümmerten
sich ausschließlich um das farbige Ausfüllen der Zeichnungen (Inking).
Dieses Streben nach höherer Effizienz setzt sich bei der Computer-Grafik fort:
man versucht, den Animateuren die nicht-kreativen Aufgaben abzunehmen und
sie an den Computer zu deligieren. Dazu werden Werkzeuge geschaffen, die es
ermöglichen, Abläufe relativ abstrakt zu beschreiben und aus den Beschreibungen
viele monotone Computer-Aufgaben zu erzeugen. Für diesen Gewinn an Effizienz
nahm man auch in Kauf, dass der Animateur weniger Kontrolle im Detail über die
erzeugten Szenen hat. Das sah man frühen CG-Filmen auch an - sie wirkten im
Vergleich zu Zeichentrick-Filmen etwas unnatürlich und hölzern. Aber mit besseren
Werkzeugen wurden bessere Animationen möglich.
Bevor es mit Computergrafik weitergeht will ich noch kurz auf ein paar Parallelen hinweisen, man hat vielleicht ein plastischeres Bild einer Methode, wenn man
ihre klassische Entsprechung kennt.
6.2. COMPUTER ANIMATION - EINLEITUNG ZUR 3D-ANIMATION
118
• Das erwähnte Tweening taucht in der Computer-Grafik als Key-FrameInterpolation wieder auf, bei der zwischen zwei Posen interpoliert wird,
um Zwischen-Bilder zu finden.
• Das noch unerwähnte Rotoscoping des Zeichentrickfilms, bei dem Bewegungen eines Films in Einzelbildern als Silhouette auf eine Mattscheibe
projeziert werden, damit der Animator davon leicht variiert abpausen kann,
hat in der Computer-Grafik als Entsprechung das Motion-Capturing. Der
Zweck der Sache ist, dass natürliche Bewegungen von Tieren oder Menschen einfach schwer zu animieren ist. Speziell für CG Sequenzen lassen sich
natürliche Bewegungen auf 3D-Modelle effektiv übertragen, was eine Menge Animations-Arbeit spart. Hierzu bekommen Schauspieler an relevanten
Stellen Markierungen oder Sensoren, deren Positionen protokolliert werden,
während sie schauspielern.
• Wenn später Kinematik und Inverse Kinematik erwähnt werden, kann man
sich Gliederpuppen vorstellen, wie sie in sog. Stop Motion Animationen
genutzt werden. Was gelenkige Puppen von sich aus können, wird auf dem
Rechner nachempfunden.
• Deformation: Die Free-Form-Deformation, die später vorgestellt wird, hat
eine gewisse Ähnlichkeit zur Verformung von Knete-Figuren.
6.2
Computer Animation - Einleitung zur 3D-Animation
Ich will nicht gesondert auf 2D-Animation eingehen. Die 3D Animations-Methoden
lassen sich aber weitgehend auf 2D übertragen.
Dieser Abschnitt soll elementare Operationen vorstellen, die zum Animieren
verwendet werden und auf die spätere Abschnitte aufbauen. Mit diesen Operationen lässt sich eine Anordnung von Objekten im 3D-Raum manipulieren. Die Momentaufnahmen, die für eine Bilder-Serie benötigt werden, werden durch ständige
Neu-Anordnung der Szene erreicht.
Translationen, Rotationen, globale und lokale Koordinatensysteme und die
“Kamera” sollten bekannt sein (siehe auch Themen der Vorträge 1 und 3).
Grundlegende Manipulationen einer 3D-Szene:
Sei die Ausgangslage, dass wir 3D Modelle im Koordinatensystem positioniert
haben und damit eine Szene abdrehen wollen. Wir haben eine Idee, wie sich welche Objekte bewegen sollen und stehen vor dem Problem, dass wir für gegebene
6.2. COMPUTER ANIMATION - EINLEITUNG ZUR 3D-ANIMATION
119
Zeitpunkte die Szene so arrangieren müssen, wie es das Drehbuch vorsieht. Vom
Rendering der Szene brauchen wir nichts zu wissen.
• Bewegung der Kamera
Schon mit der Bewegung der Kamera relativ zu einer statischen Anordnung
von Objekten lassen sich interessante Aufnahmen machen: Man kann einzelne
Gegenstände aus sich wandelnder Perspektive betrachten oder sich durch
komplexe virtuelle Welten bewegen.
In einem ganz einfachem Szenario könnte man von einem 3,6 SekundenFilm ausgehen, der unsere Objekte leblos auf einem Präsentationsteller zeigt,
wärend die Kamera einmal einen Kreis um die Szene fährt. Zuerst positionieren wir die Kamera weit genug vom Koordinatenursprung, dass sie die
komplette Szene zeigt und lassen sie auf den Nullpunkt blicken. Pro Sekunde
Film-Laufzeit sollten also 100◦ zurückgelegt werden und wir wollen 25 Bilder/s produzieren: also rotieren wir die Kamera um 4◦ um die Y-Achse, lassen
das Bild rendern und wiederholen den Vorgang noch 89 mal und “that’s a
wrap!”.
• Bewegung von Gegenständen
Das nächste simple Beispiel soll nur mit Translationen arbeiten. Ausgangslage sind unsere Objekte, die im Raum verstreut sind und wir wollen, dass
ein Raumschiff über die Sachen fliegt. Wie lange die Sequenz dauert, ist
uns egal, aber sie endet, wenn das Raumschiff 1000 einheiten weit an uns
vorbeigeflogen ist. Das Schiff fliegt konstante 25 Einheiten pro Sekunde. Das
Raumschiff wird etwas hinter und oberhalb der Kamera positioniert und los
geht’s: rendern, Z-Koordinate des Raumschiff um 1 dekrementieren, und
widerholen bis die Z-Koordinate ≤ −1000 ist.
6.2.1
Rigid Body Animation
Die vorangegangenen einfachen Beispiele 6.2 kann man als “Rigid Body Animation”
kategorisieren, weil die Objekte ihre Form nicht ändern. Damit lässt sich schon
sehr viel machen, aber die Objekte bleiben starr: nur Translationen und Rotationen
werden zur Transformation genutzt.
Der Begriff “Rigid Body” hat eine Konnotation von Leblosigkeit, aber mit starren Körpern und den “Rigid-Body-Transformations” (Translation, Rotation) lassen
sich auch Objekte realisieren, die ihre Form ändern. Man kann aus Gruppen von
6.2. COMPUTER ANIMATION - EINLEITUNG ZUR 3D-ANIMATION
120
“Rigid Bodies” interessantere Objekte erstellen, und durch koordinierte Bewegung
der Einzelteile den Eindruck eines sich verformenden Objekts schaffen.
Eine Windmühle, bei der sich (nur) der Flügel dreht, könnten wir mit elementaren Transformationen schon hinbekommen. Oder wir basteln eine Figur, bei
der Kopf, Oberköper, Arme, Hände, Beine und Füße jeweils statische Modelle
sind. Durch koordinierte Bewegungen der Einzelteile entsteht der Eindruck eines
zusammenhängenden Roboters, statt einer Menge Einzelteile.
In der Koordination der Teile liegt die Komplexität: speziall wenn Einzelteile
über rotierende Achsen miteinander verbunden sind (der Normalfall). Eine Rotation eines Teils sollte sich korrekt auf verbundene Teile, ihre relative Position
und Orientierung auswirken. Eine Bewegung hat ggf. Auswirkungen auf ganze
Ketten von verbundenen Gliedern. Es muss einiges berücksichtigt werden, damit
der Zusammenhang der Einzelteile erhalten bleibt.
Wer darüber nachdenkt und sich fragt: “wie rotiere ich eigentlich um eine
beliebige Achse?” Oder “muss ich mir nicht alle möglichen relativen Beziehungen
und Zustände merken? Wie halte ich die Informationen fest und werte sie aus?”,
der wird erleichtert sein, zu wissen, dass es hierfür ein methodisches Vorgehen gibt.
Das wird im Abschnitt 6.6 vorgestellt.
Als nächstes werden Techniken Vorgestellt, mit denen sich die Positionierung
und Orientierung von Gegenständen effektiv und flexibel animieren lassen - erstmal
von einfachen Objekten (Rigid Bodies) ausgehend.
Bei den bisher vorgestellten Methoden wurden die Modelle entweder “von
Hand” Bild für Bild animiert, oder, wie bei den 3D-Beispielen von oben 6.2 mit
einfachen Funktionen, die einen Parameterwert (Koordinate, Rotation) abhängig
von der Zeit ausdrücken.
Man könnte auch beliebig komplexe, speziell zugeschnittene Skripte schreiben,
die Objekte einer Szene zeitabhängig arrangieren. Aber das ist weder besonders
effektiv (geringe Wiederverwendbarkeit) noch besonders elegant. Anstatt das Rad
neu zu erfinden und komplexe Animations-Skripte für Probleme zu schreiben,
die längst gelöst wurden, lässt sich für viele Aufgaben auf bewährte Verfahren
zurückgreifen, mit denen sich Bewegungsabläufe definieren und durchführen lassen.
In Animationssoftware-Paketen sind entsprechende Werkzeuge integriert; Animateure basteln im GUI mit Schaltflächen, Zeitleisten, Pfad-Definitionen und manipulieren Figuren mit der Maus.
6.3. KEY-FRAMING
6.3
121
Key-Framing
Die Werkzeuge, die Animateure unterstützen, sollten ihnen möglichst viel Arbeit abnehmen, und gleichzeitig Möglichkeiten bieten, soviel Kontrolle über die Animation
zu haben, wie nötig.
Bei den Beispielen, die in (6.2) skizziert wurden, gab es nur primitive Bewegung,
die sich mit einer trivialen Funktion bzw. Iteration umsetzen ließ. Nur selten wird
es reichen, Objekte entsprechend einer mathematischen Funktion über die Zeit zu
verschieben und rotieren: die Animateure müssen flexibel gestalten können, um
variablere, interessantere Sequenzen animieren zu können.
Eingangs wurde das Tweening beim Zeichentrickfilm erwähnt und darauf hingewiesen, dass es eine Entsprechung in der 3D-Animation hat. Was beim Zeichentrickfilm die “Tweener” erledigt haben, wird bei der Computer-Animation vom
Computer errechnet. Key-Framing in der Computer-Animation ist vielseitiger, als
das Keying beim Zeichentrick-Verfahren. Beim Zeichentrick wurde - wenn wir das
Schichten von transparenten Folien beiseite lassen - die ganze Szene gezeichnet.
Beim CG Key-Framing brauchen nur die nötigen Parameter festgehalten zu werden: etwa ein einziger Punkt für die Position eines Modells, ein Rotations-Winkel,
Orientierungs-Vektor oder eine sonstige Eigenschaft, die sich in der Animation
widerspiegelt.
Für die Parameter, deren Werte für Schlüssel-Momente festgehalten wurden
muss natürlich klar sein, wie sie sich auf welche Objekte der Szene auswirken.
Häufig werden die Beziehungen zwischen Objekten und die Parameter in einem
Hierarchischen Modell (6.6) festgehalten, für das festgelegt ist, wie sich ein Parameter auf welche Teile auswirkt.
Wenn die Voraussetzungen erfüllt sind, lassen sich die Key-Frames für die Szene
definieren und der Computer ist in der Lage, alle Einzelbilder für die Szene in einem
Rutsch ohne Eingriffe von Animatoren zu generieren. Hierzu werden die Parameter
der Key-Frames interpoliert und die Szene für die Einzelbilder arrangiert.
6.4
Interpolation
Es gibt ein paar Sachen zu beachten im Kontext von Keyframing. Wenn zwischen
Keyframes interpoliert wird, erwartet man i.d.R. dass klar ist, wie die ZwischenWerte ausfallen. Wenn man sich wenig Gedanken über die Frames macht, die man
anlegt, können unerwartete Ergebnise resultieren.
6.4. INTERPOLATION
122
Angenommen es wird ein hüpfender Ball animiert und wir geben naiv einen KeyFrame pro Sekunde an. Dann ist abzusehen, dass der Ball in aufeinanderfolgenden
Key-Frames i.d.R. nicht in der gleichen Auf- oder Abwärtsbewegung ist und was
resultiert, ist eine Animation eines Balls, der nur selten den Boden berührt und sich
erratisch in der Luft hin und her bewegt. Es ist also wichtig, Key-Frames an den
Stellen zu definieren, an denen sich eine Bewegung stark ändert.
Es müssen also geeignete Keyframes definiert werden, die signifikante Momente einer Bewegung festhalten. Außerdem ist die Wahl der Parameter, über die
interpoliert wird und die Interpolationsmethode wichtig.
Es lohnt sich nochmal auf Unterschiede zwischen Tweening beim Zeichentrick
und Keyframing bei der Computeranimation hinzuweisen, um zu verstehen, warum
die Wahl der Parameter und die Interpolationsmethode eine Rolle spielen. Beim
Zeichentrick besteht ein Keyframe aus einer kompletten Zeichnung: für Menschen
ist das geeignet und eindeutig, für Maschinen nicht: da der Computer keine Ahnung
hat, was durch Bilder oder Anordnungen von Eckpunkten im 3D-Raum dargestellt
wird, kann er schlecht folgern, wie ein Zwischenbild aussieht, wenn man ihm nicht
“unter die Arme greift”. Bei der cg-Animation hält man deswegen Parameter fest,
die die Anordnung von 3D-Modellen beeinflussen: und zwar so eindeutig, dass
ein Rechner durch bloßes Regelfolgen die Zwischenbilder erzeugen kann. Und da
stellt sich die Frage, welche Parameter beschreiben eine Bewegung am besten (Eine
Position? Ein Drehungswinkel? Was ist der Bezugspunkt?) und welches Verhalten
erwarten wir von der Bewegung noch? Wie ändern sich die Parameter (gleichmäßig,
sprunghaft, graduell, variabel schnell)?
Hierzu ein weiteres Ball-Beispiel: Angenommen, wir animieren einen Ball, der
schräg nach oben gewurfen wird und fällt, und wir wollen nicht so viele Frames
definieren. Wir legen 3 Positionen fest: den Start-Punkt, den Scheitel und den Punkt,
wo der Ball den Boden berührt. Wenn linear zwischen den Keyframes interpoliert
wird, sieht die Flugbahn unnatürlich aus, wegen des spitzen Winkels. Authentischer
wäre eine Parabel, statt eines umgedrehten “V”. Außerdem würde man erwarten,
dass der Ball beim Scheitelpunkt abbremst und sich im Fallen wieder beschleunigt.
Die Probleme könnten umgangen werden, indem man eine große Anzahl von
Keyframes definiert - aber das ist keine echte Option, vor allem wegen des hohen
Aufwands, aber es bliebe auch der Defekt, dass sich die Geschwindigkeit des Balls
sprunghaft ändert - auch wenn das bei vielen Keyframes nicht mehr auffällt. Im
folgenden Abschnitt werden Methoden angesprochen, die es ermöglichen, einen
besseren Ball zu animieren.
6.4. INTERPOLATION
123
Abbildung 6.2: Flugbahn des Balls durch 3 Punkte definiert. Unterschiedliche Interpolationsmethoden
6.4.1
Interpolation von parametrischen Kurven
Abbildung 6.3: Splines in 2D. Graue Kontrollpunkte sind durch graue Linien verbunden
(lineare Interpolation). Rote Punkte: Auswertung d. Splines in gleichmäßigen Schritten.
Links: mit Arclength Re-Parametrisierung; Rechts: ohne
Abbildung 6.4: Eine Spline in 3D definiert einen Bewegungs-Pfad
Parametrische Kurven wurden in den Vorträgen zur geometrischen Modellierung behandelt und ich gehe davon aus, dass B-Splines bekannt sind. Ich will
die hier nochmal im Kontext der Interpolation aufgreifen, weil sie nicht nur beim
modellieren, sondern auch beim Animieren eine große Rolle spielen.
Zur Erinnerung: Parametrische Kurven sind durch Kontrollpunkte und eine
interpolierende Funktion definiert. Für einen Parameter aus dem Definitionsbereich
der Kurve interpoliert die Funktion den Wert der Kurve.
Weiter Oben 6.4 wurde an einem Interpolationsbeispiel mit einem Ball gezeigt,
dass lineare Interpolation für bestimmte Aufgaben unbefriedigende Ergebnisse
6.4. INTERPOLATION
124
liefert. Wir hatten 3 Positionsangaben für den Ball, und die Interpolation lieferte
einen spitzen Winkel am Scheitelpunkt.
Wenn die Positionswerte als Kontroll-Punkte einer Spline genutzt werden und
wir über die interpolieren, sieht das Ergebnis deutlich natürlicher aus, weil eine
Kurve abgetastet wird.
Für die meisten natürlichen Bewegungen sind Kurven natürlicher als GeradenSegmente mit spitzen Winkeln. Interpolation über Parametrische Kurven wirkt meist
natürlicher, weil man von Gegenständen mit Masse meist erwartet, dass sie ihre
Orientierung graduell ändern.
Der fliegende Ball lässt sich mit Spline-Interpolation schon viel schöner animieren, aber da war noch die Sache mit der Geschwindigkeit, die unnatürlich wirkte.
Wie man damit umgehen kann ist im folgendem Abschnitt 6.4.2 beschrieben.
Bevor es damit weitergeht, noch ein Hinweis zur Interpolation von Splines.
Gleichmäßige Abstände der Parameterisierungs-Variable haben nicht gleichmäßige
Abstände beim Wert zur Folge (Siehe Zusammenhang zw. Knotenvektor, Kontrollpunkten und dem Parameter). Man bevorzugt aber häufig ein lineares Verhältnis
zwischen Argument und Wert, damit sich beim Abtasten der Kurve in gleichmäßigen
Parameter-Abständen der ermittelte Wert ebenfalls gleichmäßig ändert und nicht
abhängig von der Kurvenform unterschiedlich schnell.
Eine Möglichkeit, die lineare Beziehung herzustellen, ist, die Spline einmal
in kleinen Schritten auszuwerten und jeweils die Distanz zwischen 2 Werten zu
errechnen (Pfad-Abschnitt). Die Summer der Pfad-Abschnitte ist die Gesamtlänge
der Kurve. Beim ermitteln der Gesamtlänge entgehen uns die Teillängen nicht (wir
summieren ja die Teillängen auf, um die Gesamtlänge zu ermitteln). Für einen
Abschnitt von U0 bis U1, dessen Länge wir ermitteln notieren wir für U1 in einer
Tabelle die bisher aufsummierte Länge in einer Tabelle - aus der Tabelle und der
Gesamtlänge der Kurve lässt sich nachher ablesen, dass an Stelle U1 eine bestimmte
Strecke der Kurve zurückgelegt wurde. Durch die Gesamtlänge geteilt ergibst das
eine Prozentangabe.
Wie gesagt: eine Spline, die auf [0,100] definiert ist liefert mit Argument U=50
i.A. nicht den Mittel-Punkt einer von der Kurve beschriebenen Linie. Mit der
Tabelle können wir aber zwei Argumente finden, von denen eins ¡50 und eins ¿= 50
Prozent der zurückgelegten Strecke entspricht. Ein gewichtetes Mittel dieser beiden
Argument-Werte wird als Ersatz-Argument eingesetzt und wir haben eine praktisch
lineare Beziehung zwischen Argument und Pfad-Länge. Vergleiche Abb. 6.3.
Im nächsten Unterabschnitt (6.4.2) wird die “Re-Parametrisierung” noch thema-
6.4. INTERPOLATION
125
tisiert werden, wenn wir die Dynamik, mit der eine Kurve abgetastet wird selbst
bestimmen wollen.
6.4.2
Dynamik von Bewegungen
Wenn eine Spline für einen Parameter ausgewertet wird, der sich über die Zeit
ändert, können wir von einer Geschwindigkeit sprechen, mit der der interpolierte
Punkt auf der Kurve bewegt. Bei der oben angerprochenen Re-Parametrisierung,
ging es darum, eine gleichmäßige “Geschwindigkeit” zu ermöglichen. Hier geht es
darum, eine eigene Dynamik zu definieren, mit der die Kurve abgetastet wird.
Um noch ein letztes Mal auf das Beispiel mit dem Ball 6.4 zu sprechen zu
kommen: der letzte Punkt an dem noch etwas auszusetzen war, war, dass die
Geschwindigkeit nicht passte. Um das Problem zu lösen, wollen wir die Dynamik
der Bewegung entlang des Pfads kontrollieren. Bei einem gewurfenem Ball könnte
man dies auch mit einer physikalischen Formel tun, aber hier soll die Dynamik mit
einer Spline-Kurve geregelt werden.
Gegeben sei eine Pfad-Angabe in Form einer Spline, die - man kann es ja
willkürlich wählen - zwischen 0-100 definiert ist (0=Start, 100=Ziel). Durch ReParametrisierung verhält sich das Argument linear zum Wert. D.h. 50 ergibt die
Mitte des Pfades, 33,3 entspricht einem Drittel, usw. (die oben erwähnte ParameterErsetzung erfolgt transparent in der Auswertungs-Funktion).
Jetzt definieren wir eine Spline für die Dynamik: das Argument ist die Zeit und
der Wert ist eine Zahl zwischen 0 und 100, der die Stelle des Pfades angibt. Für das
gewünschte Ball-Verhalten sieht unsere Dynamik-Kurve etwa so aus: sie steigt, geht
in ein Plateau über (das ist der Zeitpunkt zu dem der Ball auf dem Scheitelpunkt
der Kurve ist) und steigt dann weiter bis 100. Wir setzen nun s(t) in die Funktion
ein, die druch Parameter-Ersetzung das u einsetzt, für das p(u) dem Pfad-Anteil s(t)
entspricht.
Abbildung 6.5: Links: Pfad-Position s(t) für Zeit t. Rechts: Die Kurve für Parameter u.
Position für Gegebenes t ist durch p(reparam(s(t))) gegeben
6.5. ANIMATIONS-ZYKLEN
126
Die Geschwindigkeit ist, wie der Pfad, durch eine stetige Kurve definiet, was
dazu führt, dass Be- und Ent-Schleunigung auf Anhieb recht natürlich wirken. Dass
der Pfad und die Geschwindigkeit seperat definiert sind, hat auch den Vorteil, dass
man etwa nachträglich die Dynamik fein-tunen kann.
Die Dynamik-Kurve muss nicht monoton steigen: man kann damit genausogut
bewirken, dass ein eine Kurve vor- und rückwärts abgetastet wird: u.U. möchte man
modellierte Bewegungen ja vor- und rückwärts ausführen. Ein Beispiel: Angenommen, wir modellieren mit einer Kurve nochmal die Position eines Balls dessen Aufund Abwärtsbewegung symmetrisch ist (der Ball wird gedribbelt). Den Pfad definieren wir nur für eine Richtung und eine Dynamik-Kurve beschreibt die Pfad-Position
in eine Richtung und zurück (für t=0..100 geht s(t) von 0 auf 100 und zurück auf 0).
Wir haben also ein Dribbling definiert, bei dem der Ball an der Stelle endet, wo er
anfangs war.
Wir könnten übrigens, weil der Ball exakt da endet, wo er gestartet ist, die
Bewegung, die bei t=100 endet, problemlos bei t=0 fortsetzen. Mit t =< Zeit >
%100 hätten wir ein passendes t, um die Bewegung sich zyklisch wiederholen zu
lassen.
6.5
Animations-Zyklen
Einige Bewegungen wiederholen sich regelmäßig. Weiter oben war die Rede davon,
dass man Objekten einen Positions-Pfad vorgeben kann, die Bewegungs-Dynamik
seperat definieren kann und sich auch andere Parameter, z.B. die Orientierung nach
gleichem Muster definieren und interpolieren kann. So elegant die Methode ist, für
wiederkehrende, gleiche Abläufe ist das definieren von immer neuen Frames zu
aufwändig.
Wenn wir ein Auto animieren, sollen sich die Räder während der Fahrt drehen.
Es wäre eine Sisyphos-Arbeit, nur der Räder wegen Key-Frames für einzelne RadUmdrehungen zu definieren, wenn eigentlich eine Pfad- und Dynamik-Definition
schon alle Informationen zum Autofahren liefert: Mit der Dynamik wird gesteuert,
wie schnell das Auto wann fährt, aus dem Pfad lässt sich die Orientierung des Autos
errechnen (vgl. Frenet Frame). Das Verhalten der Räder lässt sich als Funktion
ausdrücken: pro zurückgelegter Einheit auf der Strasse, dreht sich das Rad X mal,
dann ist die nötige Reifen-Rotation: (Entf ernung ∗ X ∗ 360)%360 Grad.
Bei Armen und Beinen, die während des Gehens einer Figur eigentlich immer
das gleiche tun, sieht es ähnlich aus. Eine Funktion für die Körper-Animation zu
6.6. HIERARCHISCHE MODELLE UND KINEMATIK
127
finden ist etwas komplizierter als einen Reifen zu drehen. Eine Möglichkeit ist, eine
kurze Posen-Sequenz für die Figur anzufertigen, bei der die letze Pose nahtlos in
die erste übergeht. Vergleiche hierzu Abbildung 6.1.
Das kann man nach Bedarf verfeinern durch Funktionen, die mehr Parameter betrachten und mehr Posen kennen (z.B. Rechts-, Links-, Rückwärts-Laufbewegungen,
die je nach Pfad-Krümmung und positiver/negativer Geschwindigkeit genutzt werden).
Angenommen eine Zyklusche Bewegung ist durch Schlüsselposen definiert.
Für einfache Spiele und Simulationen reicht es u.U. aus, eine diskrete Anzahl von
Posen direkt anzusteuern. Für anspruchsvollere Animation ist das nicht gut genug:
da möchte man flüssige Übergänge zwischen den Schlüssel-Posen haben. Dafür
würde man zwischen den Posen interpolieren: das passt zum Key-Framing Schema.
Um die Zwischen-Posen einer Figur ermitteln zu können, muss die Figur in
einer Form modelliert sein, die für die Interpolation geeignet ist. Einzelne Posen als
Rigid-Body-Modell zu haben, deren Vertizes interpolieren werden, führt zu absurden
Zwischenposen; und eine lose Anordnung von Rigid-Bodies, die zusammen die
Figur ausmachen, einzeln bzgl. Orientierung und Position zu interpolieren, ist kaum
besser. Wenn man sich für beide Fälle die Zwischenposen vorstellt für Pose-1: Arm
nach unten ausgestreckt und Pose-2: Arm nach oben ausgestreckt, sieht man, dass
es so nicht geht: in dem einen Fall verschwindet der Arm zwischenzeitlich, in dem
anderen trennen und sich Schulter, Ober- und Unterarm. (Das Problem mit den
positionell interpolierten Vertizes ist offensichtlich; Beim zweiten Fall - Glieder
unkoordiniert interpolieren - würde der Unterarm nicht der Rotation des Oberarms
folgen, sondern sich um seine eigene Achse drehen und aufwärts translieren.)
Im Abschnitt Key-Framing 6.3 wurde erwähnt, das klar sein müsse, wie sich
interpolierte Parameter auf welche Objekte auswirken sollen - das gilt speziell
für zusammengesetzte, sogannate “artikulierte” Objekte. Im folgenden Abschnitt
6.6 wird ein Modell vorgestellt, das sich zur Interpolation von sogenannten Posen
eignet. Posen sind - wie der Name vermuten lässt - Haltungen von Figuren - Bei
hierarchischen Modellen werden sie durch eine Menge Parameter ausgedrückt, die
bewirken, dass eine Figur ebenjene Haltung einnimmt.
6.6
Hierarchische Modelle und Kinematik
Die Idee der im Abschnitt 6.2.1 angesprochenen Gruppierung von Körpern, um sie
gemeinsam zu manipulieren, lässt sich zu hierarchichen Modellen ausbauen. In dem
6.6. HIERARCHISCHE MODELLE UND KINEMATIK
128
Abbildung 6.6: Matrix-Transformation: Translation, Rotation
Modell werden Beziehungen zwischen einzelnen Körpern definiert.
Eine typisches Hierarchisches Modell, ist als Baum modelliert, bei dem in
Knoten und Kanten Informationen festgehalten werden, die miteinander verbundene
Objekte auszeichnen und in Beziehung zueinander setzen.
Wenn ein Mensch modelliert wird, definieren Knoten ein Körperteil, während
Kanten das Bindeglied zu weiteren Körperteilen sind. Man kann sich die Kanten
als Gelenke vorstellen: sie speichern z.B. die Information, in welchem Winkel und
mit welcher Verschiebung die Kind-Knoten verbunden sind. Gelenke mit mehreren
Freiheitsgraden lassen sich durch hintereinanderschalten von einfachen Gelenken
konstruieren. So kann man für ein Gelenk den Offset des Modells (Körperteil,
der am Gelenk sitzt) und einen Orientierungs-Vektor (Rotations-Achse) konstant
speichern und hat als Variable nur eine Winkel-Angabe (Rotations-Winkel).
Das Vortragsthema “Mathematical foundations - transformations and coordinates” hätte Translationen, Rotationen, und das Rechnen mit Matrizen vorgestellt.
Interessant zu wissen ist, dass sich Transformationen mit Matrizen ausdrücken
lassen, und dass sich Kompositionen von Transformationen durch Multiplikation
der Matrizen darstellen lässt (siehe Abb. 6.6).
Wie gesagt, wird für jeden Knoten (Körperteil) festgehalten wie es relativ zum
Elternknoten versetzt ist und in welchem Winkel er gedreht ist. Der Wurzelknoten
bezieht sich entweder auf den Ursprung des globalen Koordinatensystems oder des
Kontexts in dem das Modell platziert wird.
Wenn wir die Rotationen kurz ignorieren, können wir für jeden Knoten im
Baum die Koordinaten des Kontext-Koordinaten-Systems (ggf. Welt-Koordinaten)
bestimmen, indem wir einem Pfad zur Wurzel folgen und die Offsets zu den jeweils
übergeordneten Knoten aufsummieren.
Wenn ein solches Modell erstellt wurde, steht die Figur in ihrer Ausgangs-Pose.
Zum Zeichnen des Modells wird ein Tiefendurchlauf durch den Baum gemacht:
6.6. HIERARCHISCHE MODELLE UND KINEMATIK
129
Abwärtsgehend werden die Transformationen akkumuliert (Komposition der Abbildungen durch Matrix-Multiplikation) und die resultierende Transformations-Matrix
mit jedem Schritt tiefer im Baum auf einen Stack ge-pushed - sie wird für die
anderen Teilbäume ab diesem Knoten noch gebraucht. Aufwärtsgehend wird die
Matrize vom Stack ge-popped (Arbeit an diesem Teilbaum ist abgeschlossen), und
die Matrize des Eltern-Knotens wird zur aktuellen Transformations-Matrix. Wenn
z.B. der Daumen ein Blatt des Baums ist, das gerade abgearbeitet wurde, wird
seine Transformations-Matrix vom Stack ge-popped, oben auf dem Stack findet sich
die Hand-Transformations-Matrix wieder. Sie wird zur aktuellen TransformationsMatrix, mit der der Transformationsvorgang der restlichen Finger beginnt.
Bei jedem Knoten, der betrachtet wird, wird die Transformations-Matrix mit der
Translations- und Rotations-Matrix multipliziert. Die Vertices, die das Objekt am
Knoten definieren werden mit der Matrix multipliziert und an die Render-Pipeline
übergeben. Danach geht es mit der Traversierung des Baums weiter.
Die Menge der Winkel-Angaben an den Gelenken ergibt die Pose (Offsets und
Rotationsachsen sind konstante - interessant sind die Variablen). Man spricht auch
von einem “Pose-Vector”. Zur Animation eines Hierarchichen Modells können
vordefinierte Posen-Vektoren oder dynamisch errechnete Posen-Vektoren genutzt
werden. Betrachten wir Abb. 6.1 und denken nochmal an Animations-Zyklen (s.
Abschnitt 6.5): wir könnten uns Bewegungs-Posen für das Gehen anlegen und
zwischen den Pose-Vektoren interpolieren (nach Pose n geht’s mit Pose 1 weiter,
usw.), um eine fließende Bewegung zu animieren. Das Steuern eines hierarchischen
Objekts über die Gelenk-Angabe nennt man “Forward-Kinematics”: der Pose-Vektor
bestimmt eindeutig die Position und Orientierung der Einzelglieder.
Beispiel für Animation mit FW-Kinematik Siehe hierzu Abbildung 6.7.
Es soll ein Gang modelliert werden. Der Einfachheit halber wird nur ein
Bein von der Hüfte bis zum Unterschenkel betrachtet und der Fuß wird auch
ignoriert.
Die Hüfte stellt den Wurzelknoten der Hierarchie dar. Sie wird in das globale
Koordinatensystem transliert. Der Oberschenkel ist über ein Gelenk mit der
Hüfte verbunden und der Unterschenkel ist am Knie mit ihm verbunden. Die
Hüfte animieren wir, indem wir ihr eine Gerade als Pfad vorgeben und die
sie entsprechend positionieren. Jetzt müssen noch die Beine bewegt werden.
Details wie Hüft-Wippen oder das anpassen der Beinbewegung, so dass es zur
Geschwindigkeit der Hüft-Translation passt, klammern wir aus - die Beine
6.6. HIERARCHISCHE MODELLE UND KINEMATIK
130
sollen sich erstmal einfach bewegen.
Wir haben ein hierarchisches Modell, und die Pose hängt von den Winkeln
der Gelenke ab. Jetzt interpolieren wir die Gelenkwinkel, indem wir Kurven
definieren, die die Winkel für gegebene Zeit ausdrücken. Der Winkel zwischen
Hüfte und Oberschenkel ist anfangs 0◦ , wächst auf 45◦ an (Bein ist vorne),
verringert sich auf -35◦ und nimmt zu, bis er wieder 0◦ ist. Der Winkel
zwischen Knie und Unterschenkel variiert zwischen 0◦ und -35◦ . Während
der Oberschenkel sich nach vorne orientiert, ist das Knie geknickt. Beim
Auftreten vorne ist es wieder durchgedruckt und nach dem Abrollen des
Fußes (der hier nicht modelliert wird) ist das Knie wieder geknickt und der
Unterschenkel um -35◦ gedreht.
Wie weiter oben im Abschnitt erwähnt, müssen die Transformationen
vom Wurzel-Knoten ausgehend akkumuliert werden. Die Vertizes des
Unterschenkel-Modells werden folgendermaßen Transformiert: (Tranlation: Hüfte zu Welt) * (Translation: Oberschenkel zu Hüfte) * (Rotation d.
Oberschenkels) * (Translation: Knie zu Oberschenkel) * (Rotation d. Unterschenkels) * (Vertizes)
Abbildung 6.7: FW-Kinematik, Animation eines Beins - Quelle: [Wat93]
Die Forward Kinematik setzt voraus, das die Animatoren die Posen vorgeben:
Also Key-Frames oder Skripte anlegen, die die Gelenk-Winkel definieren. Eine
Pose zu modellieren, ist mit einigem Aufwand verbunden. Komfortabler wäre es für
die Animatoren, wenn sie die Pose einer Figur definieren könnten ohne alle Winkel
anzugeben. Wenn es in einer Sequenz darauf ankommt, dass zwei Figuren sich die
Hände schütteln, wäre es schön, wenn man allein die Position und Orientierung der
Hände angeben müsste und der Rechner errechnet, wie sich Unter- und Oberarm
bewegen und die Rotationen an Ellenbogen und Schulter ausfallen.
6.7. CHARAKTER ANIMATION MIT SKELETT-MODELL
131
Mit solchen Problemen beschäftigt sich die Inverse Kinematik (IK): Wir kennen
die gewünschte Pose (die Winkelangaben) nicht, bekannt ist nur die aktuelle Pose.
Wir fordern, dass ein Teil eine bestimmte Orientierung und Position haben soll. Zum
Beispiel könnten wir fordern, dass die Hand einer Figur am Griff einer Teekanne sein
soll, die in der Nähe steht. Ein sogenannter “IK-Solver” soll uns zur Problemstellung
die geeignete Pose ermitteln.
Formeller: gegeben sind eine oder mehrere sog. “End-Effektoren” mit geforderter Orientierung und Position. Gesucht sind die Winkel-Angaben, die zu einer Pose
führen, die die Forderungen erfüllt. Häufig gibt es noch zusätzliche Einschränkungen
für die Gelenke, die nur Winkel in einem bestimmten Intervall haben dürfen. Oder
es werden einzelne Körperteile “verankert”, sodass sich nur deren Kind-Knoten frei
bewegen dürfen. End-Effektoren sind die Körperteile, deren Position und Orientierung vom Animator gegeben wird. Ensprechend ihrer Vorgabe ist der Rest zu
errechnen.
Eine Ansicht des Problems ist ein Gleichungssystem, bei dem jede Gleichung
einen Winkel und seinen Einfluss auf den Fehler (bzgl. gewünschter Konstellation
des Endeffektors) beschreibt. Ein analytisches Vorgehen ist häufig so kompliziert,
dass man stattdessen versucht, sich iterativ heranzutasten. U.U. gibt es keine oder
beliebig viele Posen, die die Forderungen erfüllen. Gute Lösungen zu finden, die
gleichzeitig natürlich aussehen ist eine Herausforderung. Das Thema ist zu komplex,
um es hier zu behandeln, aber ich wollte die Problemstellung zumindest erwähnt
haben.
6.7
Charakter Animation mit Skelett-Modell
Bei der Animation von Wirbeltieren werden häufig einfache Skelett-Modelle zugrundegelegt, die die für die Animation wesentlichen Knochen enthalten. Ein Skelett
könnte folgendes enthalten: Unterschenkel, Oberschenkel, Oberkörper, Schädel,
Oberarme, Unterarme, Hände. Die Knochen haben eine Platzhalter-Funktion.
Das Skelett enthält die Teile, deren Anordnung das Gesamtbild eines Menschen
oder Tieres wesentlich ausmachen. Dieses Gerüst wird animiert und zu jeder Pose
wird auf ihm die “Haut” angebracht - das heisst, Oberflächenmodelle, die i.d.R. als
Patches statt fertiger Polygon-Meshes vorliegen (dazu gleich mehr). Es ist bekannt,
wo Arme, Beine, etc. relativ zu den Knochen zu plazieren sind: wenn einzelne
Oberflächen nicht dynamisch generiert werden, oder sich über mehrere Knochen
strecken, muss die Oberfläche nur den Offset zum Knochen und dessen Orientierung
6.8. KOLLISIONS-ERKENNUNG
132
nachvollziehen (siehe Hierarchischen Modelle 6.6). Andernfalls kann man entlang
den Knochen wandern und die Oberfläche durch Platzierung von Vertices formen
(“Sweeping”).
Man kann Posen und Animations-Zyklen für das Skelett entwerfen und es für
unterschiedliche Charaktere nutzen, indem man eine andere “Skin” anbringt. Für
unterschiedlich gebaute Charaktere nutzt man eine skalierte Variante des Skeletts.
Damit beim Charakter die Körperteile schlüssig miteinander verbunden sind,
werden Vertizes an den Kontaktstellen miteinander “verschmolzen” (VertexSkinning). Das wird bewirkt, indem die Rand-Kontrollpunkte von benachbarten
Patch-Oberflächen verbunden werden. Die aufgesetzten Oberflächen können sich so
bei Gelenkbewegungen strecken oder kontraktieren und es entstehen keine Lücken
oder Kanten zwischen Körperteilen.
Abbildung 6.8: Skelett-Modell, mit und ohne Skin. - Quelle: vrlab.epfl.ch/ alegarcia
6.8
Kollisions-Erkennung
Abbildung 6.9: Kollisionserkennung. Interpretation: Mitte: Kollisionen von BoundingSpheres; Rechts: Präzisierung der festgestellten Überlappung - Quelle: isg.cs.tcd.ie
Auf das Thema will ich nur kurz eingehen, auf Ansätze und Einsatzgebiete
hinweisen und Stichworte zur möglichen Vertiefung nennen.
Kollisionserkennung beschäftigt sich damit, eingetretene, aber u.U. auch künftig
eintretende Kollisionen bzw. Überlappungen von Objekten zu erkennen.
6.8. KOLLISIONS-ERKENNUNG
133
Häufig prüft man auf Kollisionen mit der Absicht, irgendwie darauf zu reagieren.
Im einem einfachen Fall möchte man vielleicht das weitere Ineinander-Bewegen
der Objekte verhindern, oder die Kollision in einem Shooter-Spiel als Treffer registrieren. In anderen Fällen könnte die Kollision genauer untersucht werden, um die
Objekte voneinander apprallen zu lassen oder entsprechend der Krafteinwirkung zu
deformieren. Das sind Beispiele aus der Simulation und Spiele-Welt - man könnte
meinen, bei einer Animation, in der die Bewegungen selbst festgelegt werden,
braucht man keine Kollisionserkennung. Aber auch hier gibt es Szenarien dafür.
In vorigen Abschnitten wurden zunehmend abstraktere Methoden zur Beschreibung von Bewegungen angesprochen, bei denen der Rechner sich um die lästige
Detail-Arbeit kümmert und die Animateure einen Teil der Kontrolle abgeben. Beispiele bei denen in einer Animation Kollisionen auftreten können sind
• Kinematik: Ein IK-Solver sollte berücksichtigen, dass sich Teile eines Körpers
nicht schneiden durfen. Für die Interpolation der Posen gilt das ebenso.
• Partikel-Effekte: Sprühende Funken sollten nicht durch Gegenstände fliegen.
• Physikalische Effekte an Personen: Anstatt einer steifen “Helm-Frisur” könnte
eine Figur wehendes Haar haben, dessen Bewegung mit physikalischen Formeln erzeugt wird. Bei soviel Aufwand sollte man auch noch sicherstellen,
dass die Haare nicht durch Gesicht und Schultern wehen.
Es gibt einige Methoden, auf Kollisionen zu prüfen. Eine ganz exakter Test
kann sehr rechenintensiv sein, deshalb gibt man sich häufig damit zufrieden, dass
ein Test grob stimmt. Eine Methode, die Kollisionen immer korrekt erkennt, aber
auch mal falsche Positive meldet ist meist akzeptabel.
Ein sehr einfacher Ansatz ist der Bounding-Box Test: Zu jedem Objekt ermittelt
man eine Kiste, die das Objekt umfasst, indem man vom Objekt die Minima und
Maxima der X, Y und Z Koordinaten ermittelt. Mit dieser Box testet man dann
auf Kollision: überlappen sich keine Boxen, können sich deren Inhalte auch nicht
überlappen. Überlappen sich die Boxen, dann könnten sich die Objekte schneiden
und man kann die Stelle, die in Frage kommt genauer testen. U.U. muss man es
nicht so genau wissen. Wenn man mit Hierarchischen Modellen arbeitet, kann man
Boxen für Einzelteile errechnen, die man von 2 Objekten prüft, wenn sich deren
Boxen überlappen - so bekommt man weniger falsche Positive.
Statt Bounding-Boxes können natürlich auch Bounding-Spheres genutzt werden:
die sind leicht zu testen, umfassen aber Objekte i.d.R. weniger eng, als eine Box,
6.9. DEFORMATION
134
deren Dimensionen unterschiedlich sein können.
Ein weiterer Ansatz ist, den Raum mittels Binary Space Partition Trees aufzuteilen in belegte Sektoren, die untersucht werden. Zu BSP, siehe die Ausarbeitung
zu Ray-Tracing
Für einfache geometrische Figuren (Linien, Ebenen, Kugeln, Würfel) sind
Intersektionsformeln bekannt und für komplexe Modelle lassen sich ihre Einzelteile
betrachten, sodass ein exakter Kollisionstest für ein Modell eine große Menge von
einfachen Tests erfordert. Präzise Verfahren finden für Objekte eine (oder mehrere)
konvexe Hüllen, deren Oberflächen-Ebenen gegen alle in Frage kommenden VertexVerbindungen auf einen Schnitt getestet werden. Um unnötiges Testen zu vermeiden
bietet sich an, zuerst mit Bounding-Boxes /-Spheres zu schauen, ob eine Kollision
überhaupt möglich ist.
6.9
6.9.1
Deformation
Globale Deformation
Abbildung 6.10: Populäre globale Deformationen - Quelle: [Wat93]
Deformationen, die dadurch erreicht werden, dass alle Vertizes eines Modells
durch eine Mathematische Funktion manipuliert werden, nennt man auch globale
Deformationen.
Man kann sich natürlich unendlich viele Funktionen ausdenken, aber es gibt
ein paar Funktionen die so gängig sind, dass sie einen Namen haben. Die Funktionen werden einzeln auf jeden Vertex eines Modells angewandt und nutzen als
Parameter nur die Vertex-Koordinaten und ggf. Parameter, die einmalig für die
Funktionsanwendung festgelegt oder berechnet wurden. Mit sonstigen Parametern
meine ich Werte, die die Deformation charakterisieren: z.B. Winkel und Position
einer Biegung u.ä..
Gängige Deformationen:
• Taper: Verschlankung der Form durch Skalierung
6.9. DEFORMATION
135
• Displace: Versetzen von Vertizes
• Twist: Vertizes um eine Achse drehen
• Bend: Vertizes werden (mithilfe einer Rotations-Funktion) verbogen.
6.9.2
Free Form Deformation
Abbildung 6.11: Free-Form Deformation, simuliert - Quelle: www.medhfz.unibas.ch
Die Globale Deformation baut auf einfache Mathematische Funktionen auf.
Durch Parametrisierung der Funktionen und Kombinationen aus mehreren Deformationen lassen sich aufwändige Verformungen erreichen.
Wenn wir eine ganz bestimmte Verformung erreichen wollen, mag es sein,
dass sich die mit einer bestimmten Kombination elementaren Verformungen hinbekommen lässt, aber solche Lösungen kann man sich schwer spontan ausdenken.
Angenehmer wäre eine Methode, bei der sich ein Objekt wie Knete formen lässt.
Free-Form-Deformation ist eine Technik, die genau das realisiert: man kann frei
an Objekten “herumkneten”, und mit geeignetem Feedback ein Modell interaktiv
bearbeiten.
Bei der FFD wird um ein Modell oder eines Teils davon, ein 3-dimensionales
Gitter gedacht, das als eine Art Erzatz-Koordinatensystem dient. Die Punkte des
Gitters sind Kontrollpunkte von parametrischen Kurven (z.B. Splines), die im Moment noch als gerade Linien durch das Gitter gehen. Die Vertizes des Modells,
das verformt werden soll, werden relativ zu den Kontrollpunkten des Gitters berechnet. Dann wird verformt, indem die Kontrollpunkte des Gitters manipuliert
werden. Nach der Manipulation des Gitters (d.h. sämlicher Splines, die zusammen
das Gitter ausmachen), wird die neue Position der Modell-Vertizes entsprechend
des verformten Gitters errechnet (Siehe 6.11).
6.10. GESICHTS-ANIMATION
6.9.3
136
Animierte Deformation
Free-Form Deformationen sind nicht auf einmalige Verformungen beschränkt. Wir
können ein sogenanntes “Deformation Tool” - so bezeichnet man das Tupel: (Gitter, Verformtes Gitter) - über Modelle streichen oder Modelle in und aus dem
Einflussbereichs eines Verformers bewegen.
Damit lassen sich einige Effekte erzielen: Z.B. könnten wir eine gedehnte
Stelle entlang eines Schlauchs bewegen (vergleiche in etwa Abb. 6.12), eine Raupe
animieren, einen Geist in eine Flasche quetschen oder einen Zerrspiegel simulieren.
Abbildung 6.12: Deformation in Bewegung- Quelle [Wat93]
Wenn wir die Kontrollpunkte eines Gitters selbst animieren, etwa indem wir
sie durch eine zeitabhängige Funktion bewegen, werden neue Arten von Effekten
denkbar.
Lassen wir die Kontrollpunkte sich dezent konzentrisch kontraktieren und ausdehnen und platzieren das “Verformungs-Werkzeug” über den Oberkörper einer
Figur, dann sieht das so aus, als würde die Figur ein- und ausatmen. Lassen wir die
Kontrollpunkte hin und her, auf und ab schaukeln, können wir Wellen simulieren.
Es ist schon auffällig, wie viel sich mit Kurven und Interpolation anstellen lässt.
6.10
Gesichts-Animation
Bei der Animation von Charakteren ist das Skelett (siehe Skeletal Animation 6.7)
wohl am bedeutendsten - seine Anordnung bestimmt das Aussehen einer Figur
extrem. Was Muskeln und Sehnen machen, sticht nicht so ins Auge und meistens
macht sich ihre Aktivität nur indirekt durch Bewegung des Skeletts bemerkbar.
Gesichter sind anders: hier bewegen die Muskeln keine Knochen, sondern
beeinflussen die Mimik. Die Mimik spielt eine grosse Rolle dabei, Charaktere
authentisch wirken zu lassen. Deswegen wurden zur Animation von Gesichtern
aufwändige Techniken entwickelt.
Ein Gesicht wird, damit es sich gut animieren lässt, aus Patches modelliert
(siehe Abb. 6.13) und hat eine Menge Kontroll-Punkte. Bei einer relativ einfachen Animations-Methode, wird eine überschaubare Anzahl signifikanter Gesichtsausdrücke modelliert. Sie unterscheiden sich, durch die Anordnung der Kontroll-
6.10. GESICHTS-ANIMATION
137
Punkte. Das Gesicht wird dann animiert, indem eine gewichtete Mischung aus den
gewünschten Posen erzeugt wird: z.B. Könnten die Posen “Fröhlich” und “Skeptisch”
zu gleichen Anteilen gemischt werden, indem man zwischen den Kontrol-Punkten
der beiden Posen interpoliert.
Die Qualität der Bewegungen hängt davon ab, Posen zu haben, deren Übergänge
glaubwürdig aussehen. Bei diesem einfachen Ansatz würden wir einfach die Kontrollpunkte linear zwischen Posen interpolieren. Das ist beim Gesicht viel unproblematischer als bei Knochen- und Gelenk-Konstrukten, da Punkte des Gesichts
praktisch keine Rotationen um andere Punkte durchmachen.
aufwändigere Verfahren modellieren Muskeln (in Form von Splines oder Patches) nach, die sich auf Kontroll-Punkte des Gesichts in ihrer Umgebung auswirken.
Das hat eine gewisse Ähnlichkeit zu den Free-Form-Deformations 6.9.2, aber die
Kopplung der Kontroll-Punkte des Gesichts zu den Kontroll-Punkten der Muskeln
ist i.d.R. aufwändiger realisiert als bei der FFD, weil das anatomische Vorbild
nachempfunden wird. Das beginnt damit, dass Punkte die weniger direkt auf der
Linie der Zugrichtung eines Muskels liegen, schwächer beeinflusst werden, und geht
soweit, dass gezogene Kontroll-Punkte eine Gegenkraft ausüben, die sich wiederum
auf ihre Nachbarpunkte auswirkt (Elastizität und Gewebeverdrängung).
Mit letzterem Verfahren, bei dem die jeweiligen Mimik-Parameter einzeln geregelt werden können, lassen sich Gesichter sehr flexibel animieren. Siehe Abbildung
6.13
Abbildung 6.13: Links: Gesichts-Modellierung ausgehend von einer Zeichnung - Quelle:
Web/unbekannt; Rechts: Parametrisierte Mimik bei Nvidias Dawn Demo
Kapitel 7
Image-Based Rendering
Selimkhan Achmerzaev
7.1
Einleitung
Die meisten 3D Techniken, die wir bis jetzt kennen gelernt haben, versuchen
3D-Szenen und Objekte so realistisch wie möglich zu gestalten. Dabei kommen
verschiedene Techniken zum Einsatz: Unter anderem realistische Modelle (z.B.
Vortrag über Splines und Nurbs von Jacqueline Spexard), Texturen (GPU, Christoph
Sackl), Reflexionen und Beleuchtung (Raytraycing, Tobias Pfeiffer).
Bei Image-Based Rendering (IBR), auf der anderen Seite, werden reale
Bilder und reale Szenen benutzt, um diese in die 3D-Welt zu übertragen. Dies kann
in vielen Fällen sehr hilfreich sein. Wenn man aus einem oder mehreren 2D Bildern
ein Objekt (bzw. eine gesamte Szene) der realen Welt schnell und realistisch als ein
3D-Modell (3D-Szene) realisieren kann, kann es einiges an Modellierungsarbeit,
Beleuchtung und Texturierung ersparen. Die Komplexität der Szene spielt hierbei
auch keine Rolle.
Mit Hilfe von Image-Based Modeling (IBM) und Image-Based Rendering
(IBR) ist es möglich, dreidimensionale Szenen auf Basis von zweidimensionalen
Bildern zu erstellen. Bei den zugrunde liegenden Bildern kann es sich entweder um
Fotografien der realen Welt handeln, oder um bereits vorberechnete Bilder. Dies
geschieht, indem man versucht, in den Quellbildern die Struktur, Beschaffenheit,
Raumwirkung und Beleuchtung zu erkennen. Die so gewonnene Information wird
138
7.1. EINLEITUNG
139
dann in die 3D Welt übertragen und es können neue Bilder erzeugt werden.
Ein weiteres Verfahren, welches reale Bilder in die 3D-Welt einbindet, ist
Image-Based Lighting (IBL). Image-Based Lighting erlaubt es, reale Bilder als
Lichtquellen zu benutzen und somit eine sehr realistische globale Beleuchtung einer
Szene zu realisieren.
Diese Ausarbeitung wird zwei Image-Based Modelling and Rendering Verfahren (IBMR) kurz vorstellen:
• - Light Field und View Interpolation als Teil von Image Based Modelling
und Rendering
und ein Image-Based Lighting Verfahren (IBL):
• - Globale Beleuchtung mit Hochkontrastbildern
Der Leser soll am Ende eine übersichtliche Vorstellung dieser Techniken haben. Es
werden viele Bilder zum Einsatz kommen und Bezüge zur praktischen Anwendung
dieser Techniken vorgestellt.
Es gibt unterschiedliche Methoden von Image Based Modelling: solche,
die ohne Geometrie (z.B. Light Field Rendering), mit impliziter Geometrie (View
Interpolation) oder expliziter Geometrie rendern[HS00].
Das Grundprinzip hinter diesen Verfahren ist es den Lichtfluss, also die
Bewegung der Lichtstrahlen in der Szene, parametrisieren und festhalten zu
können (plenoptische Funktion). Wie das genau geschieht, wird beim Light Field
Rendering Verfahren vorgestellt.
Vorausetzung für die IBMR-Verfahren ist jedoch, dass die benutzten Quellbilder zusammenhängend sind, dieselbe Szene repräsentieren und möglichst aus
derselben Richtung und unter gleichen Lichtbedingungen aufgenommen wurden.
Ansonsten kann es zu Fehlern und Missinterpretationen kommen.
7.2. LIGHT FIELD
7.2
140
Light Field
Light Field Rendering [LH96] ist eines der Image Based Rendering Verfahren.
Mit Hilfe von Light Fields ist man in der Lage, durch Aufnahmen eines realen,
digitalisierten oder synthetischen Objekts, neue Ansichten von diesem Objekt zu
generieren. Dabei werden viele Bilder des Objekts benötigt, aber keine Information
über die Geometrie der Szene.
Um zu verstehen, wie das realisiert wird, sollte das Konzept der Plenoptischen Funktion erklärt werden, da diese Funktion alle visuellen Eigenschaften
einer Szene definiert. In der Computergrafik wird Licht häufig als Strahl (eng: Ray)
betrachtet. Die Menge des Lichtes, welches durch diesen Strahl wandert, nennt man
Strahldichte (engl.: radiance).
Die Plenoptische Funktion (vorgestellt durch Adelson und Bergen [AB91])
beschreibt die Intensität von Lichtstrahlen an jedem Punkt (Vx , Vy , Vz ), unter jedem
möglichen Winkel(θ, φ).
P = (Vx , Vy , Vz , θ, φ)
(7.1)
Da wir davon ausgehen können, dass zwischen der Kamera und dem Objekt ein
freier Raum ist (nur Luft), wodurch sich die Wellenlänge des Lichtes nicht verändert,
da der Lichtstrahl keinen weiteren Objekte trifft, kann man die plenoptische
Funktion auf vier Faktoren reduzieren, wodurch wir eine 4D Funktion erhalten. Die
Farbe eines Lichtstrahls, im freien Raum, bleibt auf ihrem Weg konstant.
Um diesen Lichtstrahl parametrisieren zu können, reichen zwei parallele Ebenen,
die sich zwischen dem Objekt und der Kamera befinden und eine konvexe Hülle
bilden (Abbildung 7.1).
L(u, v, s, t)
(7.2)
Dabei stehen u und v für die Koordinatenachsen einer Ebene und s,t für die Koordinatenachsen der anderen Ebene.
Die beiden Ebenen werden als: (u,v)-Ebene (Objektebene) und (s,t)-Ebene
(Kameraebene) bezeichnet. Sie haben eine feste Entfernung zu einander und der
Lichtstrahl bewegt sich durch die beiden Ebenen. In der Praxis wird die Breite
und die Höehe der beiden Ebenen festgelegt. Dadurch kann man die Lage des
Lichtstrahls parametrisieren, da die Koordinaten, an denen der Lichtstrahl die beiden Ebenen schneidet, bekannt sind. Diese Darstellung wird auch als ’light slab’ -
7.2. LIGHT FIELD
141
Abbildung 7.1: Darstellung von einem Light Slab. Aus [LH96]
Darstellung bezeichnet.
Abbildung 7.2: links: ein Light Slab; rechts: vier Light Slabs aus vier verschiedenen
Richtungen
7.2.1
Sampling
Als weiterer Schritt erfolgt das Sampling (Abtastung). Dabei sollte man sich
vorstellen, als platziere man eine Kamera in einem Punkt in der (s,t)-Ebene und
würde jeden Punkt in der (u,v)-Ebene damit aufnehmen, wodurch wir das Light
Field von diesem Punkt aus hätten. Die dadurch gewonnenen 2D-Bilder könnte
man wiederum in die 4D-Funktion L(s,t,u,v) einsetzen. Dies könnten wir von jedem
Punkt aus auf der (s,t)-Ebene machen. Somit wäre das Einfügen dieser Bilder in
L unser Light Field. Das Extrahieren von 2D Bildern aus dieser 4D-Funktion
ermöglicht es neue Bilder aus neuen Perspektiven zu bekommen, indem die
Nachbarsamples interpoliert werden.
7.2. LIGHT FIELD
142
Außerdem kann man sowohl von jedem Punkt auf der (s,t)-Ebene alle Punkte der
(u,v)-Ebene aufnehmen, aber auch von allen Punkten in der (s,t)-Ebene einen
bestimmten Punkt in der (u,v)-Ebene. (siehe Abbildung 7.3)
Desweiteren können auch spezielle 4D-Filter (z.B. 4D-Tiefpassfilter [LH96])
Abbildung 7.3: Oben: Erfassung eines Punktes in der (s,t)-Ebene, durch jeden Punkt in
der (u,v)-Ebene
Unten: Erfassung jedes Punktes in der (s,t)-Ebene, aus einem Punkt in der (u,v)-Ebene
zum Einsatz kommen, um Aliasing zu vermeiden und einen besseren Übergang
zwischen benachbarten Light Fields zu erzielen.
7.2.2
Technische Probleme
Prinzipiell ist es nicht möglich, unendlich viele Bilder (bzw. unendlich viele Samples) aus verschiedenen Perspektiven aufzunehmen. Dies wäre mit einem sehr hohen
Aufwand verbunden. Zudem würde sich eine sehr große Datenmenge ansammeln.
Aus diesem Grund ist man gezwungen, möglichst wenige Samples zu verwenden.
Gewöhnlich wird die (s,t)-Ebene in MxM Quadrate (meist 32x32 Punkte) und die
(u,v)-Ebene in NxN Quadrate(256x256) aufgeteilt. Man sollte bedenken, dass
man selbst bei dieser Menge an Samples, auf etwa 1GB Daten kommt, wenn
man mit 24-Bit pro Pixel das Objekt von allen sechs Seiten aufnimmt. Um die
Datenmenge gering zu halten, kommen spezielle Kompressionsmethoden zum
Einsatz. Dabei werde die anfallenden großen Datemengen komprimiert gespeichert.
Eins dieser Kompressionsverfahren ist eine zweistufige Pipeline bestehend aus
Vektorquantisierung mit fester Bitrate und anschließender Entropiekodierung mit
dem Lempel-Ziv-Algorithmus, die eine Verarbeitung in Echtzeit ermöglicht (Aus
7.2. LIGHT FIELD
143
”Light Field Rendering”von M.Levoy, P.Hanraham. [LH96]).
Ein weiteres Problem stellt die Bewegung und die Positionierung der Kamera dar. Die Kamera muss für jeden Sample korrekt positioniert werden, denn
sonst wären die Bilder ungenau, unscharf, verschwommen und unregelmässig
voneinander entfernt.
7.2.3
Resampling / Erzeugen von neuen Bildern
Anhand der gewonnenen Samples ist man nun in der Lage, neue Bilder aus anderen
Blickrichtungen zu generieren. Zunächst wird die Position der Kamera festgelegt.
Danach werden die (s,t)- und (u,v)-Ebenen für unsere Bildstrahlen ermittelt und
die Samples extrahiert, die am nähsten zu dieser neuen Blickrichtung liegen.
Anschließend werden diese ”resampled”, wobei eine Interpolation der benachbarten
Samples bzw. Farbwerte stattfindet, um ein bestmögliches Ergebnis zu erzielen.
Abbildung 7.4 zeigt zwei Beispielbilder, die durch Light Fields erzeugt
wurden.
Abbildung 7.4: beide Bilder gerendert mit Light Fields anhand von samples [LH96]
7.2.4
Zusammenfassung
Light Field Rendering ermöglicht anhand vorhandener Bilder realistische Szenen
mit realistischer Beleuchtung unter neuen Blickwinkeln in kurzer Zeit zu erzeugen.
Mit heutiger Hardware ist das Generieren von Light Fields in Echtzeit möglich.
7.3. VIEW INTERPOLATION
144
Man sollte jedoch nicht vergessen, dass es auch gewisse Schwierigkeiten mit sich
bringt, so z.B.:
• - Hohe Anzahl an Samples für besseres Endergebnis (grosse Datenmengen
notwendig)
• - Genaue Positionierung der Kamera erfordert Automatisierung
• - Statische Beleuchtung notwendig
7.3
View Interpolation
Unter View Interpolation versteht man ein Verfahren, bei dem man mindestens
zwei Referenzbilder einer Szene benutzt, um neue Bilder zu erzeugen. Gewöhnlich
entstehen diese neuen Bilder aus einer Perspektive, die zwischen den beiden Referenzbildern liegt und werden durch das Interpolieren der Referenzbilder erzeugt.
Abbildung 7.5: Das mittlere Bild wird anhand der beiden Referenzbilder interpoliert
Das Verfahren, welches hier vorgestellt wird ist auf Chen und Williams (1993)
”View Interpolation for Image Synthesis” zurückzuführen[CW98]. Bei diesem Verfahren wird die Kamera im 2D Raum, parallel zu einer statischen Szene, bewegt und
es werden mindestens zwei Quellbilder aufgenommen, anhand derer später neue
Zwischenbilder erstellt werden sollen. Im Vergleich zu Light Field Rendering, wird
bei View Interpolation implizitet Geometrie verwendet.
Um eine Interpolation eines neuen Bildes aus zwei vorhandenen Bildern zu
erreichen, sollten die beiden Eingabebilder nah aneinander aufgenommen sein, so
dass es eine gewisse Überlappung gibt und man Punkte oder Geometrie eines, der
beiden Bilder, im anderen wiederfindet.
7.3. VIEW INTERPOLATION
145
Das bedeutet, dass man Ähnlichkeiten und Korrespondenz in den beiden
Bildern benötigt. Anhand dieser Ähnlichkeiten werden die Quellbilder ”gemorpht”
und wenn nötig Fehler, die in dem neuen künstlichen Bild entstanden sein könnten,
entfernt.
Das Morphen von Bildern kommt in verschiedenen Bildbearbeitungsanwendungen
vor. Bei dieser Bildverarbeitungstechnik können ein oder mehrere Motive
miteinander verflochten und durch Veränderung von Betrachtungsparametern in ein
anderes Motiv verwandelt werden. Verfahrensmäßig werden beim Morphing die
Attribute zweier Objekte aufeinander abgestimmt. Die Zwischenobjekte werden
über die Interpolation der Quellobjekte erstellt, wobei ein stufenloser Übergang das
Ziel ist.
Abbildung 7.6: Image Morphing. links - Original, rechts - Spiegelung, mitte - Morphed
Image
7.3.1
Pixel Interpolation
Mit vorgegebenem Bewegungsfeld, d.h. wenn die Bewegung der Kamera bekannt
ist, und mindestens zwei benachbarte Quellbilder vorliegen, ist es möglich, die
korrespondierenden Pixel aus einem der Quellbilder im anderen wiederzufinden
(Abbildung 7.7).
Da sich bei einer Kamerabewegung, die Objekte, welche sich näher an der
Kamera befinden, schneller in die entgegengesetzte Richtung bewegen, als die im
Hintergrund, kann eine relative 3D-Position jedes Pixels bzw. Objekts festgehalten
werden. Auf diese Weise wird die Pixelkorrespondenz zwischen den Pixeln auf
den beiden Quellbildern mit Hilfe einer Transformationsmatrix berechnet. Es wird
7.3. VIEW INTERPOLATION
146
Abbildung 7.7: Pixel Interpolation. Links und rechts sind die beiden Quellbilder und in
der Mitte das interpolierte Zwischenbild. Bewegung der Kamera ist von links unten nach
rechts oben.
außerdem eine so genannte ”morph map”(”Bewegungskarte”) für jeden Pixel in
den Quellbildern erstellt, welche die Bewegungsvektoren speichert.
Beim Generieren des gewünschten Zwischenbildes anhand von zwei Quellbildern, werden die Bewegungsvektoren jedes Pixels der beiden Quellbilder linear
interpoliert und somit die neue Position des Pixels im Zwischenbild berechnet.
7.3.2
Probleme
Beim Interpolieren der beiden Ansichten muss man bedenken, dass gewisse Stellen
der Szene durch andere Objekte verdeckt sein könnten und das neue Zwischenbild
womöglich Lücken aufweist, da diese individuelle Stelle des Bildes in keinem der
Quellbilder zu erkennen ist. Abbildung 7.8 verdeutlicht dieses Szenario. Diese
Lücken sind Bereiche, die nicht von den Quellbildern festgehalten wurden und
interpoliert werden müssen. Je näher die Quellbilder aneinander sind, umso besser
ist das Zwischenbild (siehe Abschnitt 7.3.4).
Abbildung 7.8: Die dunkleren Stellen sind in keinem der Quellbilder A und B zu sehen,
jedoch in dem Zwischenbild M
7.3. VIEW INTERPOLATION
7.3.3
147
Lösung
Eine der Lösungen dieses Problems ist z.B. das Übermalen dieser Lücken mit
derselben Farbe der benachbarten Pixel. Dabei werden die Lücken zuerst mit der
Farbe der Pixel, die eher im Hintergrund sind (geometrisch betrachtet weiter entfernt
von der Kamera), übermalt und dann mit der Farbe der Pixel, die sich weiter vorne
(näher an der Kamera) befinden. Falls man, anhand vorher gewonnener Information,
die Geometrie der Szene ersehen kann (z.B. mit Hilfe der Bewegungsvektoren),
wird ein besseres Ergebniss beim Übermalen erzielt, da keine Farbe der Objekte aus
dem Hintergrund plötzlich im Vordergrund auftreten kann. Als Regel gilt - je mehr
Quellbilder vorliegen und je kleiner der Abstand zwischen den Quellbildern, um so
weniger Lücken entstehen und umso genauer kann das Übermalen dieser Lücken
sein.
7.3.4
Beispiele
Abbildung 7.9 verdeutlicht das Problem der Lücken (blaue Bereiche im Bild). In
Abbildung 7.10 sieht man, wie das Entstehen von größeren Lücken vermieden wird
(indem die Quellbilder sehr nah aneinander aufgenommen werden) und wie das
interpolierte Endbild aussieht.
Abbildung 7.9: Lücken, die entstehen, wenn man die Kamera nach rechts dreht
Abbildung 7.10: (a) Lücken bei nur einem Quellbild; (b) bei zwei Quellbildern; (c) bei
zwei Quellbildern, die sehr nah an einander aufgenommen wurden; (d) Lücken durch
Interpolieren gefüllt
7.3. VIEW INTERPOLATION
7.3.5
148
Beipiel aus der Filmindustrie
View Interpolation, View Morphing (ähnlich wie View Interpolation) und Image
Morphing sind recht leistungsstarke Verfahren, um realistische Zwischenbilder
anhand von vorhandenen realen Bildern zu erstellen.
Schon heute werden diese Verfahren z.B. in der Filmindustrie erfolgreich angewendet, wie beispielsweise in dem Film ’The Matrix’[Sil03]. Der Bullet-Time Effekt
wird realisiert, indem man viele einzelne Kameras um die Szene herum aufstellt, die
sehr nah aneinander in einem Kreis oder Halbkreis angeordnet sind. Die Kameras
nehmen, entweder zeitlich versetzt oder alle gleichzeitig, Bilder der Szene auf. Anschließend werden alle diese benachbarten Bilder interpoliert und man erhält einen
weichen Übergang. Dabei entsteht der Effekt, als sei die Zeit in diesem Moment
angehalten worden und eine Kamera bewege sich sehr schnell um die Szene herum.
Abbildung 7.11: Die schwarzen Punkte im linken Bild sind einzelne Kameras.
7.3.6
Zusammenfassung
View Interpolation ist ein einfaches Verfahren, um neue Zwischenbilder anhand
von vorhandenen Bildern zu generieren, ohne einen grossen technischen Aufwand
investieren zu müssen. Die erforderliche Datenmenge kann zwischen zwei einzelnen
Bildern, bis zu n Bildern variieren, je nach dem wie gut das Endergebniss sein soll.
Die Geometrie der Szene wird implizit einbezogen (bei Light Field Rendering
keine Geometrieinformation notwendig).
Je näher die Quellbilder aneinander sind, um so besser sieht das interpolierte
Zwischenbild aus. Es können immernoch leicht verschwommene Stellen entstehen,
wenn grössere Lücken übermalt werden müssen.
Es ist vorteilhafter, wenn die Szene statisch ist und eine feste, statische Beleuchtung
hat, weil dadurch weniger Missinterpretationen bei der Interpolation entstehen
können.
Es sollte noch erwähnt werden, dass man bei View Interpolation auch andere
7.4. IMAGE BASED LIGHTING MIT HIGH DYNAMIC RANGE IMAGES 149
Verfahren benutzt, um Tiefenunterschiede zu bestimmen, unter anderem Depth
Fields [DML+ 99] und Stereobilder der Szene. Anhand dieser Bilder kann man
erkennen, welche Teile der Szene näher an der Kamera sind und welche weiter im
Hintergrund liegen und somit ein besseres Ergebniss beim Übermalen der Lücken
erreichen (siehe Abbildung 7.12).
Abbildung 7.12: Stereobild, Tiefenwirkung anhand von zwei Quellbildern [DML+ 99]
7.4
Image Based Lighting mit High Dynamic Range
Images
Image Based Lighting (IBL) [Deb02] ist ein Verfahren, bei dem eine reale oder
synthetische Szene (bzw. ein 3D Objekt) realistisch beleuchtet wird. Realisiert wird
dies mit Hilfe von Bildern des Lichtes, welche in der realen Welt aufgenommen
wurden.
Im Gegensatz zu bisherigen Verfahren (Radiosity, Raytraycing) findet hier keine
physikalische Simulation statt.
IBL erlaubt es künstlich erstellte, dreidimensionale Objekte und Szenen in Bilder
der realen Welt realistisch einzubinden und schafft sehr realistische Reflexionen.
Bei IBL kommen High-Dynamic-Range-Bilder (HDR-Bilder) zum Einsatz.
HDR-Bilder sind Hochkontrastbilder einer realen Szene, die wesentlich mehr
Information beinhalten, als nur eine Farbe pro Pixel. In der Computergrafik steht
”Dynamic Range”(Dynamikumfang) für den Quotienten aus größtem und kleinstem
Helligkeitswert eines digitalen Bildes.
7.4. IMAGE BASED LIGHTING MIT HIGH DYNAMIC RANGE IMAGES 150
Vorgestellt wurde ”high dynamic range imaging”von Greg Ward [WAR94]
und später weiterentwickelt von Paul Debevec [DM97], der als einer der führenden
Entwickler auf diesem Gebiet gilt.
Das menschliche Auge kann höhere Kontrastwerte wahrnehmen, als die
gängigen Monitore darstellen können (Auge etwa 1:1 000 000, Monitor: 1:10 000
oder weniger). Die meisten uns bekannten Bildformate, wie z.B. JPEG, werden als
LDR-Bilder bezeichnet (Low-dynamic-range-image). Die Unterscheidung, ob ein
Bild ein LDR-Bild oder HDR-Bild ist, ist von den Bits pro Pixel abhängig.
Die meisten LDR-Bildern sind 8-Bit-Bilder (aber auch 16-Bit). Das bedeutet, dass
für jeden Farbkanal 8 Bits zu Verfügung stehen, also insgesamt 24 Bit für jeden
Pixel für alle drei Farben (RGB). Solche LDR-Bilder repräsentieren nur einen
Bruchteil des Dynamikumfangs (Dynamikumfang der Helligkeitswerte). Wenn eine
Szene zu hell ist, werden die entsprechenden Pixel nur auf ihren Maximalwert
gesättigt (in unserem Fall 255 bei 8 Bit), unabhängig davon wie hell die reale Szene
tatsächlich ist. Bei HDR-Bildern werden 32 Bit für jeden Farbkanal verwendet
(insgesamt 96 Bit pro Pixel). Die Farben werden mit Fließkommazahlen kodiert,
wodurch sehr hohe Werte darstellbar sind (bei 32 Bit sind es über 4 Milliarden).
Eine weitere Eigenschaft von HDR-Bildern ist es, dass die Pixelwerte linear
7.4. IMAGE BASED LIGHTING MIT HIGH DYNAMIC RANGE IMAGES 151
proportional zu der Lichtmenge der realen Welt sind. Einige HDR-Bildformate sind
z.B. Radiance RGBE (.hdr) oder OpenEXR (.exr). [HDR07b]
Um HDR-Bilder aufzunehmen, werden mehrere Bilder derselben Szene unter verschiedenen Belichtungsreihen aufgenommen um alle Helligkeitsbereiche
abzudecken. Die Belichtungsreihe erstreckt sich von einer extremen Unterbelichtung bis hin zu einer extremen Überbelichtung.
Abbildung 7.13: Unterschiedliche Belichtungsreihen
Abbildung 7.14: Vergleich zwischen einem LDR- und einem HDR-Bild bei 1/32 Helligkeitsabnahme.
In Abbildung 7.13 sieht man links 8 Bilder einer Szene, die unter verschiedenen
Belichtungsreihen aufgenommen wurden. Mit Hilfe dieser 8 Bilder sehen wir rechts
die Lichtintensität an jedem Punkt dieser Szene (blau: sehr wenig, rot: sehr helle
Stellen)
Abbildung 7.14 verdeutlicht den Unterschied zwischen einem LDR-Bild und einem
HDR-Bild. Bei einer 1/32 Helligkeitsabnahme wirkt das HDR-Bild immernoch
realistisch, da man immernoch einen guten Kontrast zwischen den hellen Fenstern
und dem Rest des Raumes erkennt, was beim LDR-Bild nicht der Fall ist.
7.4. IMAGE BASED LIGHTING MIT HIGH DYNAMIC RANGE IMAGES 152
7.4.1
Light Probes
Light Probe Bilder sind omnidirektionale (in jede Richtung im Raum), HighDynamic-Range-Bilder, die die Information über die einfallende Beleuchtung an
einem bestimmten Punkt im Raum beinhalten. Neben der Eigenschaft omnidirektional zu sein, gibt es für jede Richtung des Raumes einen korrespondierenden Pixel
in der Light Probe [Deb02].
Des Weiteren ist in jedem dieser Pixel die Information über die Lichtintensität und
die Lichtmenge gespeichert.
Abbildung 7.15: Einige Light Probes. Light Probe Image Gallery www.debevec.org
Es gibt mehrere Möglichkeiten omnidirektionale Bilder der Umgebung aufzunehmen. Eine Möglichkeit ist es, eine verchromte Kugel auf einem Stativ im Raum
zu platzieren und diese Kugel mit einer Kamera aufzunehmen. Damit erfasst man
fast die komplette Umgebung. Weitere Methoden sind z.B. mit Hilfe einer Panoramakamera oder ”Fischaugekamera”. Man kann auch Bilder in jede Richtung der
Umgebung aufnehmen und diese dann später zusammenfügen. Bei der Aufnahme
mit Hilfe einer spiegelnden Kugel werden in der Regel mehrere Bilder dieser Kugel
aufgenommen. Gewöhnlich nimmt man zwei Bilder unter einem Winkel von 90◦
auf. Das ermöglicht die Kamera und den Fotografen in der Mitte der Kugel zu übermalen, so dass diese im Bild nicht zu sehen sind. Die Reflexionen an den Rändern
dieser Kugel weisen jedoch leichte Verzerrungen und Streckungen auf [HDR07a].
Es ist möglich seine eigenen Light Probes zu erstellen. Dafür gibt es einige Software Lösungen, um normale Bilder in .hdr Bilder umzuwandeln (Bsp. HDRShop
http://www.ict.usc.edu/graphics/HDRShop/), aber man findet auch genug fertige
Light Probes im Internet (Bsp. http://www.debevec.org/Research/HDR), die man
direkt mit den meisten gängigen 3D-Programmen benutzen kann (Bsp. 3dsmax,
Maya, Cinema4D).
7.4. IMAGE BASED LIGHTING MIT HIGH DYNAMIC RANGE IMAGES 153
Abbildung 7.16: Aufnahme der Umgebung mit einer Kugel und ein Fishauge-Objektiv
7.4.2
Environment Mapping
Die eigentliche 3D-Szene wird entweder mit einer riesigen Kugel (Sphere) oder
einem Quader (Cube) übersehen, die quasi unendlich weit entfernt sind. Auf
diese Sphere , bzw. Cube wird dann das HDR-Bild projiziert. Das Motiv auf dem
HDR-Bild wird somit zur Environment Map (Umgebungsbild), welche sich in den
Objekten der Szene widerspiegelt. Dadurch wirkt die Szene, vor allem spiegelnde
Objekte wie Metall oder Glas, besonders realistisch.
Da das Cube Mapping als Verbesserung von Spherical Mapping entwickelt
wurde, hat es in manchen Fällen Vorteile, da es beim letzteren teilweise zu
Unkorrektheiten kommen kann. Der Grund dafür ist, dass bei Spherical Mapping
eine Light Probe von einer spiegelnden Kugel verwendet wird und, wie oben
schon erwähnt, sind die Ränder dieser Kugel gestreckt und verzerrt, wodurch die
Reflexionen in den Objekten der Szene manchmal unkorrekt oder verschwommen
wirken können. [HDR07a]
Abbildung 7.17: Spherical und Cubical Environment Mapping
7.4. IMAGE BASED LIGHTING MIT HIGH DYNAMIC RANGE IMAGES 154
7.4.3
Beispiele
Die folgenden Beispiele sollen die Vorteile und den Photorealismus, den man mit
Hilfe von IBL und HDRI erreicht, verdeutlichen.
In der folgenden Szene habe ich fünf verschiedene Kugeln platziert und
mit unterschiedlichen Texturen und Materialen übersehen. Die Kugeln sind aus
unterschiedlichen Glasstrukturen, Metall und Spiegel.
Abbildung 7.18: links: ambiente Standardbeleuchtung; rechts: globale Beleuchtung(Raytracing)
In Abbildung 7.18 (links) wurde eine Standardbeleuchtung benutzt (ambiente
Beleuchtung der Szene mit einer festen Lichtquelle). Das ist der Grund für das
künstliche Aussehen. Ausserdem ist es schwer die Materialbeschaffenheit der
rechten beiden Kugeln zu erkennen. Das Bild rechts (Abbildung 7.18) wurde
mit Hilfe von globalen Beleuchtung (hier:Raytraycing) erstellt. Die Szene wirkt
realistischer, jedoch fehlen mehr Reflexionen der Umgebung und die Beleuchtung
ist überall monoton und gleichmäßig.
Die Bilder in Abbildung 7.19 wurden mit unterschiedlichen Light Probes
gerendert. Es sind viele Überstrahlungen und sehr helle Stellen an den gläsernen
Kugeln zu sehen. Die Reflexionen der Umgebung verleihen den Bildern einen
starken photorealistischen Effekt und man kann deutlicher erkennen aus welchen
Materialien die Kugeln sind.
Auch wenn es den Eindruck erweckt, als seien die Bilder unter grossem
Berechnungsaufwand und längeren Renderzeiten entstanden, benötigt man mit
heutigen Mittelklasserechnern (X2 4200+, 2GB RAM, DirectX 9 Grafikkarte) für
so ein Bild etwa 2-4 Minuten Renderzeit bei einer Auflösung von 640x480 Pixeln.
7.4. IMAGE BASED LIGHTING MIT HIGH DYNAMIC RANGE IMAGES 155
Abbildung 7.19: Renderings mit 4 verschiedenen HDRImages
Ein weiteres Beispiel ist in Abbildung 7.20 zu sehen.
7.4.4
Einsatz von IBL in der Industrie
Image Based Lighting kommt in verschiedenen Bereichen zum Einsatz: in Industrial
Design, Filmindustrie. In der Videospielindustrie wird zur Zeit nur HDR-Rendering
benutzt. Die Möglichkeit ein synthetisches Objekt in eine reale Szene einzubinden,
damit es realistisch in dieser Szene wirkt, erlaubt es einiges an Kosten zu ersparen.
So kann man neue Produkte modellieren und sie in eine reale Szene übertragen.
Das kann besonders bei Bauunternehmen, oder bei größeren Fahrzeugprototypen,
Materialkosten ersparen.
Auch in der Filmindustrie (siehe Spider Man 2 und The Matrix Trilogy)
werden realistische Szenen mit Hilfe von IBL umgesetzt.
7.4. IMAGE BASED LIGHTING MIT HIGH DYNAMIC RANGE IMAGES 156
Abbildung 7.20: links: Standardbeleuchtungsmodell, rechts: dasselbe Objekt (selbe Material) aber mit IBL
Abbildung 7.21: Das Spiel Far Cry mit und ohne HDR Rendering
7.4.5
Zusammenfassung
IBL ist ein leistungsstarkes Verfahren, welches sehr realistische Beleuchtung und
Reflexionen schafft. Es findet schon heute in vielen Bereichen der Industrie Verwendung. Mit Hilfe von HDRI-Technik und IBL kann man 3D-Szenen in die reale Welt
überführen und ein künstliches 3D-Objekt in eine reale Szene einbinden.
IBL ist so gut wie in jedem gängigen 3D-Grafikprogramm vorhanden und HDRBilder lassen sich mit geringem Aufwand erstellen. Somit ist diese Technik allen
zugänglich und leicht zu realisieren (schon ab DX7-Schnittstelle möglich).
Es wird vermutlich auch weiterhin entwickelt und verbessert und schon bald verbreitete Verwendung auch in der Videospielindustrie finden. Schon heute gibt es
Möglichkeiten IBL in Echtzeit zu realisieren ( Masaki Kawase, rthdribl v.1.2 (DirectX9), Real-Time High Dynamic Range Image-Based Lighting ).
Literaturverzeichnis
[AB91]
Edward H. Adelson and James R. Bergen. The plenoptic function
and the elements of early vision. Computational Models of Visual
Processing, pages 3–20, 1991.
[AK89]
James Arvo and David Kirk. A survey of ray tracing acceleration
techniques. In Andrew Glassner, editor, An Introduction to Ray Tracing.
Academic Press Ltd, 1989.
[Coo89]
Robert L. Cook. Stochastic sampling and distributed ray tracing. In
Andrew Glassner, editor, An Introduction to Ray Tracing. Academic
Press Ltd, 1989.
[CW98]
Shenchang Eric Chen and Lance Williams. View interpolation for
image synthesis. SIGGRAPH 1998, pages 381–390, 1998.
[dB93]
Mark de Berg. Ray Shooting, Depth Orders and Hidden Surface
Removal. Springer-Verlag, 1993.
[Deb02]
Paul E. Debevec. A tutorial on image-based lighting. In IEEE Computer
Graphics and Applications, 2002.
[DG05]
Stefan Turek Dominik Goddeke, Robert Strzodka. Double precision on
gpus, 2005. http://numod.ins.uni-bonn.de/research/
papers/public/GoStTu05double.pdf.
[DM97]
Paul E. Debevec and Jitendra Malik. Recovering high dynamic range
radiance maps from photographs. In SIGGRAPH ’97: Proceedings
of the 24th annual conference on Computer graphics and interactive
techniques, pages 369–378, New York, NY, USA, 1997. ACM Press.
[DML+ 99] Paul E. Debevec, M.Cohen, L.McMillan, C.Bregler, R.Szeliski, and
F. Sillion. Image-based modeling, rendering, and lighting. Course
Notes for Course #39 at SIGGRAPH 1999. SIGGRAPH 1999, 1999.
[DSC93]
Heiko Duin, Günter Symanzik, and Ute Claussen. Beleuchtungsalgorithmen in der Computergrafik. Springer-Verlag, 1993.
157
LITERATURVERZEICHNIS
158
[FK03]
Randima Fernando and Mark J. Kilgard. The Cg Tutorial. Addison
Wesley, 2003.
[Fou06a]
OpenGL Foundation.
Opengl specifications 2.1, 2006.
http://www.opengl.org/documentation/specs/
version2.1/glspec21.pdf.
[Fou06b]
OpenGL Foundation.
Opengl specifications 2.1, 2006.
http://www.opengl.org/documentation/specs/
version2.1/glspec21.pdf Page 90 ff.
[Fou07]
GPGPU Foundation. Gpgpu, 2007. http://www.gpgpu.org.
[Gib07]
Steve Gibson. How subpixel font rendering works, [Stand: 16.11.2007].
http://www.grc.com/ctwhat.htm.
[Gla89]
Andrew S. Glassner. Surface physics for ray tracing. In Andrew
Glassner, editor, An Introduction to Ray Tracing. Academic Press Ltd,
1989.
[Hai89]
Eric Haines. Essential ray tracing algorithms. In Andrew Glassner,
editor, An Introduction to Ray Tracing. Academic Press Ltd, 1989.
[Han89]
Pat Hanrahan. A survey of ray-surface intersection algorithms. In
Andrew Glassner, editor, An Introduction to Ray Tracing. Academic
Press Ltd, 1989.
[HB97]
Ronald Hearn and Pauline Baker. Ch3: Output primitives. In Computer
Graphics, C Version Second Edition, Upper Saddle River, New Jersey,
1997. Prentice Hall.
[HDR07a] HDRShop. Creating a light probe, 2007. http://gl.ict.usc.
edu/HDRShop/tutorial/tutorial5.html.
[HDR07b] HDRSoft. Faq - hdr images for photography, 2007. http://www.
hdrsoft.com/resources/dri.html.
[HS00]
H.Shum and S.B.Kang. A review of image-based rendering techniques.
In Microsoft Research, 2000.
[Inc07]
Ziff Davis Media Inc.
3d pipelining, 2007.
http:
//www.extremetech.com/article2/0,1697,1155159,
00.asp.
[Ins07]
National Instruments. Pci express - an overview of the pci express
standard, 2007. http://zone.ni.com/devzone/cda/tut/
p/id/3767.
LITERATURVERZEICHNIS
159
[Kom07]
Elektronik Kompendium.
Grafikkarte, 2007.
http:
//www.elektronik-kompendium.de/sites/com/
0506191.htm.
[LH96]
Marc Levoy and Pat Hanrahan. Light field rendering. In SIGGRAPH
’96: Proceedings of the 23rd annual conference on Computer graphics
and interactive techniques, pages 31–42, New York, NY, USA, 1996.
ACM Press.
[Mic07]
Microsoft. Microsoft typography, [Stand: 16.11.2007]. http://www.
microsoft.com/typography/default.mspx.
[MPS07]
Andrew Moss, Dan Page, and Nigel Smart. Toward acceleration of
rsa using 3d graphics hardware. In Cryptography and Coding, pages
369–388. Springer-Verlag LNCS 4887, December 2007.
[nVi06a]
nVidia. Nvidia geforce 8800 architecture technical brief, 2006. http:
//www.nvidia.com/object/IO_37100.html.
[nVi06b]
nVidia. Nvidia geforce 8800 architecture technical brief, 2006. http:
//www.nvidia.com/object/IO_37100.html.
[nVi07]
nVidia. Compute unified device architecture, 2007.
developer.nvidia.com/object/cuda.html.
[PR]
POV-Ray. Pov-ray hall of fame. http://de.wikipedia.org/
wiki/Raytracing. Stand: 11.11.2007.
[Pyg07]
Pygame. Grafik-apis im Überblick, 2007. http://www.pygame.
de/news/grafik-apis-im-uberblick/.
[Shi05]
Peter Shirley. Fundamentals of Computer Graphics. A K Peters, 2005.
[Sil03]
Steve Silberman. Matrix2, 2003. http://www.wired.com/
wired/archive/11.05/matrix2_pr.html.
[TB94]
Spencer W. Thomas and Rod G. Bogart. Ii.3: Color dithering. In
Graphics Gem 2, University of Michigan Ann Arbor, Michigan, 1994.
Academic Press.
[Uni07]
Stanford University. Folding@home, 2007. http://folding.
stanford.edu/.
[uotad99]
The university of texas at dallas. Hazards, 1999. http://www.
utdallas.edu/˜cantrell/ee2310/s1hazard.pdf.
[WAR94]
G. J. WARD. Real pixels. In Graphics Gems IV. Academic Press,
Boston, 1994.
http://
LITERATURVERZEICHNIS
160
[Wat93]
Alan Watt. 3D Computer Graphics. Addison-Wesley, 1993.
[Wik]
Wikipedia. Raytracing. http://de.wikipedia.org/wiki/
Raytracing. Stand: 11.11.2007.
[Wik07a]
Wikipedia.
Comparison of nvidia graphics processing units,
2007.
http://en.wikipedia.org/wiki/Comparison_
of_NVIDIA_Graphics_Processing_Units.
[Wik07b]
Wikipedia. Grafikkarte, 2007. http://de.wikipedia.org/
wiki/Grafikkarte.
[Wyv93]
Brian Wyvill. 2d rendering. In Graphics Gem 1, University of Calgary
Alberta, Canada, 1993. Elsevier LTD, Oxford.