Augmented Reality mit korrekter Beleuchtung durch Light Probe

Transcrição

Augmented Reality mit korrekter Beleuchtung durch Light Probe
Augmented Reality mit korrekter
Beleuchtung durch Light Probe
Tracking
Studienarbeit
vorgelegt von Fabian Scheer
Institut für Computervisualistik
Arbeitsgruppe Computergraphik
Betreuer: Dipl.-Inform. Thorsten Grosch
Prüfer: Prof. Dr. Stefan Müller
Koblenz, Februar 2006
INHALTSVERZEICHNIS
1
Inhaltsverzeichnis
1 Einführung
3
2 Grundlagen
4
2.1
2.2
2.3
2.4
2.5
2.6
2.7
ARToolkit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
2.1.1
Grundlagen ARToolkit . . . . . . . . . . . . . . . . . . . .
4
2.1.2
Das Tracking Verfahren im ARToolkit . . . . . . . . . . .
6
2.1.3
Begrenzungen des Trackingverfahrens . . . . . . . . . . .
8
2.1.4
Applikationsentwicklung . . . . . . . . . . . . . . . . . . .
9
Stereokamera . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
2.2.1
Probleme . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
Umgebungsmapping . . . . . . . . . . . . . . . . . . . . . . . . .
16
2.3.1
Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . .
16
2.3.2
Blinn/Newell Methode . . . . . . . . . . . . . . . . . . . .
18
2.3.3
Sphärisches Mapping . . . . . . . . . . . . . . . . . . . . .
19
Multitexturing . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
2.4.1
Multitexturing in OpenGL . . . . . . . . . . . . . . . . .
25
Beleuchtungsmodell . . . . . . . . . . . . . . . . . . . . . . . . .
27
2.5.1
OpenGL Beleuchtungsmodell . . . . . . . . . . . . . . . .
27
2.5.2
Verwendetes Beleuchtungsmodell . . . . . . . . . . . . . .
28
Schatten Volumen . . . . . . . . . . . . . . . . . . . . . . . . . .
33
2.6.1
Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . .
33
2.6.2
Probleme . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
Verfahren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
3 Implementierung
39
4 Ergebnisse
53
4.1
Bewertung und Performanz . . . . . . . . . . . . . . . . . . . . .
5 Fazit
5.1
Schlußfolgerungen
53
57
. . . . . . . . . . . . . . . . . . . . . . . . . .
1
57
INHALTSVERZEICHNIS
5.2
2
Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
57
1. Einführung
1
3
Einführung
Die Verschmelzung von Realität und Virtualität hat in den letzten Jahren in
einem erstaunlichen Maße zugenommen. Fiktive Wesen die sich früher nur in
Science-Fiction oder Fantasy Romanen finden ließen, bevölkern nun die Bildschirme der Menschen zuhause. Gerade die Filmindustrie zeigt in beeindruckenden Maße, wie sehr die vorherige, intuitiv klare Trennung zwischem realem
Schauspieler oder Gegenstand und virtueller Erschaffung von Charakteren und
Welten verschwimmt. Leider ist der damit verbundene Aufwand, diese Verschmelzung in einem realistischen Maße zu betreiben, enorm hoch. Besonders
die Beleuchtung der virtuellen Objekte spielt in diesem Zusammenhang eine
bedeutende Rolle, denn wer kennt es nicht, daß ein virtuelles Objekt in einer
realen Szene von einer anderen Richtung beleuchtet wird, als es die realen Begebenheiten erwarten lassen würden. An diesem Punkt setzt meine Arbeit an.
Die Zielsetzung besteht darin, die Beleuchtung virtueller Objekte an die aktuelle
Beleutungssituation der realen Szene in Echtzeit anzupaßen, um störende Faktoren, die die Immersion des Betrachters beeinträchtigen könnten, auszuschließen.
Da viele gängige Systeme und Methoden daran ansetzen, Beleuchtungen virtueller Objekte in realen Szenen durch Nachbearbeitungsprozeße zu erreichen, wird
diese Arbeit die Bestrebung verfolgen, dies in Echtzeit zu erreichen. Dabei wird
die zentrale Problemstellung der realistischen Darstellung in zwei Kernprobleme
unterteilt:
Zum einen wird versucht die aktuelle Beleuchtungssituation in jedem Schritt
der Darstellung zu erfaßen, um das Objekt korrekt zu beleuchten. Zum anderen
soll das Objekt mit der realen Umgebung in dem Maße interagieren können, als
das es einen Schatten auf die Objekte der realen Szene wirft.
3
2. Grundlagen
4
Abbildung 1: Marker
2
Grundlagen
2.1
ARToolkit
Um die oben genannten Ziele zu erreichen wurde die Softwarebibliothek ARToolkit eingesetzt, die im folgenden vorgestellt wird.
2.1.1
Grundlagen ARToolkit
ARToolkit ist eine Softwarebibliothek zur Entwicklung von Augmented Reality Applikationen. Die Bibliothek stellt Funktionalitäten zur Verfügung, um
Bilder einer realen Szene, die mit einer Kamera aufgenommen wurden, mit virtueller Information anzureichern. Um dies zu gewährleisten werden Marker eingesetzt, aus deren Position und Ausrichtung zum Betrachter Daten gewonnen
werden können, die es ermöglichen virtuelle Objekte perspektivisch korrekt in
Abhängigkeit zum Marker darzustellen. Abbildung 1 zeigt exemplarisch solche
Marker. Abbildung 2 zeigt ein solches System im Einsatz1 . Das um virtuelle Informationen angereicherte Bild kann dabei am Bildschirm oder über Brillen, die
der Benutzer trägt dargestellt werden. In der Abbildung wird ein Head Mounted
Display, ein sogenannter HMD, verwendet, der über winzige LCD Bildschirme in
der Brille und über eine Kamera zur Aufnahme der Szenerie verfügt. Eines der
Hauptprobleme bei Augmented Reality besteht darin, die Orientierung und die
Position des Benutzer, d.h. der Kamera in Relation zur beobachteten Szenerie
1 Billinghurst:
ARToolkit,
http://www.hitl.washington.edu/artoolkit/, [Stand: 22.12.2005]
4
2.1
ARToolkit
5
Abbildung 2: Head Mounted Display, Vgl. Billinghurst: ARToolkit
festzustellen, um virtuelle Objekte relativ zu dieser Position und Orientierung
anzeigen zu können. ARToolkit nutzt Algorithmen aus dem Bereich Computer
Vision, um die Position und Orientierung der realen Kamera in Relation zu
den betrachteten Markern in Echtzeit zu errechnen. Die Features des ARToolkit
bestehen im wesentlichen aus den Folgenden2 :
• Ein einfaches Framework um Echtzeit AR Applikationen zu erstellen
• Eine Multiplattformbibliothek (Windows, Linux, Mac OS X, SGI)
• Überlagerung von Markern im Bild mit virtuellen 3D Objekten
• Multiplattform Videobibliothek mit:
– Unterstützung mehrerer Quellen (USB, Firewire, capture card)
– Unterstützung mehrerer Formate (RGB/YUV420P, YUV)
2 Billinghurst:
ARToolkit,
http://www.hitl.washington.edu/artoolkit/documentation/features.htm, [Stand: 02.01.2006]
5
2.1
ARToolkit
6
Abbildung 3: Diagramm ARToolkit, Vgl. Billinghurst: ARToolkit
– Unterstützung für ein Tracking mehrerer Kameras
• schnelles und kostengünstiges 6D Marker Tracking
• Erweiterbarer Marker Ansatz (eigene Marker können erstellt werden, doch
die Performanz nimmt mit steigender Zahl an zu trackenden Markern ab)
• einfacher Kalibrierungsmethode
• einfacher Graphikbibliothek basierend auf GLUT
• schnellem Rendering basierend auf OpenGL
• 3D VRML Unterstützung
• einfacher und modularer API, geschrieben in C
• Unterstützung anderer Programmiersprachen wie Java oder Matlab
2.1.2
Das Tracking Verfahren im ARToolkit
Die prinzipielle Technik des ARToolkit die Position und Orientierung der realen Kamera relativ zu einem beobachteten Marker zu berechnen, funktioniert
6
2.1
ARToolkit
7
folgendermaßen3 :
1. Zuerst wird das reale Videobild von einer Kamera aufgenommen und an
den Rechner gesandt
2. Dann wird jedes aufgenommene Bild des Videostreams anhand eines einstellbaren Treshholds binarisiert, der sich mit variierenden Lichtverhältnissen auch ändern sollte, um ein stabiles Tracking zu gewährleisten
3. Anschließend wird das binarisierte Bild mit Methoden der Bildverarbeitung nach quadratischen Regionen bzw. Formen durchsucht. Da jedoch
viele quadratische Regionen bzw. Formen im Bild auftreten können, werden alle gefundenen quadratischen Formen mit vortrainierten Mustern verglichen. Bei diesem Vergleich wird das Muster mit Markern verglichen, die
sich der Benutzer erstellt hat. Diese Erstellung geschieht in einem Schritt
der Vorverarbeitung, bei der der Benutzer seine erstellten Marker mit einer
Kamera aufnimmt und sie in einem eigenen Format abgelegt.
4. Hat das ARToolkit nun eine Übereinstimmung eines detektierten Musters
mit einem vortrainierten Marker gefunden, so wird die Position und Orientierung der realen Videokamera relativ zum detektierten Marker berechnet. Die Berechnung basiert im Prinzip darauf, daß die Originalgröße
des Markers anhand der Trainings bekannt ist, sich somit ein Distanzwert
abschätzen lässt, und die Orientierung anhand der Rotation des Markers
im Bild wiedergewonnen werden kann.
5. Als Ergebnis des oben beschriebenen Prozeßes erhält man eine 3x4 Matrix,
welche die Position und Orientierung der realen Videokamera relativ zu
dem detektierten Marker angibt. Diese Matrix wird dann verwendet um
die Position und Orientierung der virtuellen Kamera in OpenGL zu setzen.
Da die virtuelle und die reale Kamera nun die gleiche Position aufweisen,
3 Billinghurst:
ARToolkit,
http://www.hitl.washington.edu/artoolkit/documentation/userarwork.htm,
02.01.2005]
7
[Stand:
2.1
ARToolkit
8
werden die virtuellen Objekte präzise auf dem detektierten Marker im
Videobild gezeichnet.
Um das Verfahren stabiler zu halten, sollte man möglichst keine symmetrischen
Gebilde als Muster für die zu erkennenden Marker wählen, damit die Detektion
der Marker, die Positions-, und die Orientierungsberechnung eindeutige Ergebnisse ermitteln können. Desweiteren sollte man sich der Tatsache bewusst sein,
daß der Treshold nicht dynamisch berechnet wird und sich das Verfahren verschlechtert bzw. auch ganz ausfällt, wenn sich die Lichtverhältnisse aufgrund
von Kameraschwenks stark ändern. Dies ist z.B. der Fall wenn man auf ein
Fenster mit Gegenlicht schwenkt. Die von mir verwendete ARToolkit Version
ARToolKitDirectShow2.52VRML besaß zumindest nicht diese Fähigkeit. Allerdings existiert mittlerweile eine Version, die mit einem dynamischen Verfahren
zur Bestimmung des Tresholds arbeitet4 .Dabei handelt es sich um eine Weiterentwicklung der Originalsoftware. Die Originalsoftware kann man unter der
folgenden Adresse beziehen:
http://sourceforge.net/projects/artoolkit
2.1.3
Begrenzungen des Trackingverfahrens
Das Trackingverfahren des ARToolkits funktioniert nur, wenn ein Marker im
Bild zu detektieren ist. Die Objekte sind in ihrer Bewegung durch die Größe
des Bildes eingeschränkt und sie werden gar nicht angezeigt, sobald die Marker
verdeckt sind5 . Eine weitere Einschränkung der Markererkennungsfähigkeit des
Systems ist die Abhängigkeit zwischen der Größe der Marker und der Entfernung
des Betrachters zum Marker.
4 Schmalstieg:
Studierstube,
http://studierstube.org/handheld ar/download/ARToolKitPlus Autothresholding.avi,
[Stand: 02.01.2006]
5 Billinghurst: ARToolkit,
http://www.hitl.washington.edu/people/grof/SharedSpace/Download/ARToolKit2.33doc.pdf,
[Stand: 02.01.2006]
8
2.1
ARToolkit
9
Marker Größe(cm)
Reichweite(cm)
6,98
40,6
8,89
63,5
10,79
86,7
18,72
127
Tabelle1: TrackingReichweite
Die Komplexität der zu erkennenden Muster beeinträchtigt die Erkennung und
führt dazu, daß die Reichweite in der die Marker noch korrekt erkannt werden,
proportional mit der Komplexität abnimmt. Auch die Orientierung des Benutzers zum Marker spielt bei der Erkennung eine wichtige Rolle, denn die Markererkennungsfähigkeit nimmt mit dem Betrachtungswinkel ab. Je flacher der
Benutzer den Marker betrachtet, desto mehr an sichtbarer Fläche des Markers
verschwindet und ein Tracking wird unmöglich6 .
2.1.4
Applikationsentwicklung
Um nun ein Programm mit dem ARToolkit zu entwickeln sind folgende Schritte
notwendig7 :
1. Initialisierung: Initialisierung des Video Grabbings“, Einlesen der zu er”
kennenden, vortrainierten Markermuster und Einlesen der per Kalibrierung ermittelten Kameraparameter
2. MainLoop:
(a) Grabbing eines Bildes des Videostreams
(b) Erkennen der Markermuster im Videobild
6 Billinghurst:
ARToolkit,
http://www.hitl.washington.edu/people/grof/SharedSpace/Download/ARToolKit2.33doc.pdf,
[Stand: 02.01.2006]
7 Billinghurst: ARToolkit,
http://www.hitl.washington.edu/artoolkit/documentation/devprinciple.htm,
02.01.2006]
9
[Stand:
2.1
ARToolkit
10
(c) Berechnung der Kameratransformation relativ zu den erkannten Markern
(d) Zeichnen der virtuellen Objekte auf bzw. relativ zu den erkannten
Markern
3. Beenden: Schließen des Videostreams
Im folgenden werden die oben genannten Schritte weiter erläutert:
• Initialisierung: init() Methode:
• Setzen der initialen Kameraparameter:
if( arParamLoad(cparam_name, 1, &wparam) < 0 ) {
printf(\"Camera parameter load error !!\");
exit(0);
}
• Transformation der Parameter für die entsprechende
Bildgröße(hier 320x240):
arParamChangeSize( &wparam, xsize, ysize, &cparam );
• Setzen der an die Bildgröße angepassten Kameraparameter:
arInitCparam( &cparam );
• öffnen des Graphik Fensters mit den entsprechenden Parametern:
argInit( &cparam, 2.0, 0, 0, 0, 0 );
• Einlesen der VRML Objekte aus den Dateien, objectnum gibt
die dabei zu ladende Anzahl an:
10
2.1
ARToolkit
11
if( (object=read_VRMLdata(model_name, &objectnum)) == NULL )
exit(0);
Main Loop:
• Ein Bild von der Kamera grabben:
camera.GrabFrame();
if((dataPtr = (ARUint8 *)camera.GetBuffer()) == NULL ) {
arUtilSleep(2);
return;
}
• Zeichnen des Videobildes:
argDrawMode2D();
argDispImage(dataPtr, 0,0);
• Erkennen der Marker im Videobild:
if(arDetectMarker(dataPtr,thresh,
&marker_info,&marker_num)<0){
cleanup();
exit(0);
}
Der Vertrauenswert eines Markers(cf) gibt die Zuverlässigkeit des Trackings
an, und die Marker IDs werden entsprechend diesen Werten vergeben. Eine
Modifikation des Originalprogramms merkt sich gleichzeitig den höchsten
Vertrauenswert und die damit verbundene Marker ID, um später mit dem
am besten getrackten Marker arbeiten zu können. Gleichzeitig wird mit
der Funktion arGetT ransM at und arGetT rasM atCont die Matrix bestimmt, die die Transformation zwischen dem Marker und der Kamera
beinhaltet. Dies ist davon abhängig ob das Objekt sichtbar ist oder nicht:
11
2.1
ARToolkit
12
for( i = 0; i < objectnum; i++ ) {
k = -1;
for( j = 0; j < marker_num; j++ ) {
if(marker_info[j].cf > cf ) {
cf=marker_info[j].cf; id=marker_info[j].id;
}
if( object[i].id == marker\_info[j].id ) {
if( k == -1 ) k = j;
else {
if( marker_info[k].cf < marker_info[j].cf )
k = j;
}
}
}
if( k == -1 ) {
object[i].visible = 0;
continue;
}
if( object[i].visible == 0 ) {
arGetTransMat(&marker_info[k],
object[i].marker_center, object[i].marker_width,
object[i].trans);
}
else{
arGetTransMatCont(&marker_info[k], object[i].trans,
object[i].marker_center, object[i].marker_width,
object[i].trans);
}
object[i].visible = 1;
}
12
2.1
ARToolkit
13
Die Position und Orientierung der realen Kamera finden sich in der 3x4
Matrix object[i].trans. Nach diesen Schritten können endlich die virtuellen
Objekte auf den Markern gezeichnet werden:
draw();
argSwapBuffers();
Das Zeichnen der Obejekte unterteilt sich wiederum in drei Bearbeitungsschritte. Erstens muss das 3D Zeichnen initialisiert werden durch8 :
argDrawMode3D();
argDraw3dCamera( 0, 0 );
glClearDepth( 1.0 );
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
Anschließend wird die 3x4 Matrix in ein Array mit 16 Werten konvertiert,
um diese Matrix in OpenGL laden zu können:
argConvGlpara(patt_trans, gl_para);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixd( gl_para );
Nun können beliebige Transformationen ausgeführt werden, um das zu
zeichnende Objekt in die gewünschte Position und Ausrichtung zu bringen:
glTranslatef( 0.0, 0.0, 25.0 );
glRotatef(45,0.0,1.0,0.0);
glutSolidCube(50.0);
8 Billinghurst:
ARToolkit,
http://www.hitl.washington.edu/artoolkit/documentation/devstartup.htm,
02.01.2005]
13
[Stand:
2.2
Stereokamera
14
In einem letzten Schritt wird die Cleanup() Methode aufgerufen:
argCleanup();
Dies war eine grobe Zusammenfassung zur Erstellung einer Applikation mit
dem ARToolkit. Der Leser sollte sich jedoch bewusst sein, daß sich von Version
zu Version des ARToolkits Änderungen in den oben beschriebenen Schritten
ergeben können. Informationen zum ARToolkit und verschiedene Versionen zum
Herunterladen lassen sich unter http://artoolkit.sourceforge.net/ finden.
2.2
Stereokamera
Zur Ermittlung der Tiefeninformation der aufgenommenen Szene wird eine
Stereokamera eingesetzt. Im Lieferumfang der Kamera ist ein Software Development Kit(SDK) enthalten, mit dem es möglich ist, sowohl normale Farbbilder mit einer Auflösung von 1024x768 bei 15fps zu grabben, als auch ein
schwarz/weiß Tiefenbild mit einer Bildrate von 4fps.
2.2.1
Probleme
Leider hat sich im Laufe der Entwicklung herausgestellt, daß ein rein optisches
Verfahren nicht ausreicht, um verlässliche Tiefenwerte der Szene zu ermitteln.
Das Hauptproblem hierbei war, daß für die Anwendung ein Tiefenbild der gesamten Szene benötigt wurde. Um dies zu erhalten, musste die Kamera allerdings so parametriert werden, daß am Ende nicht mehr validierte Tiefenwerte
pro Pixel gewonnen werden konnten, und das Bild somit fehlerhafte Tiefeninformationen lieferte, wie in Abbildung 4 besonders am Rand und an den Objektkanten ersichtlicht ist. Parametrierte man die Kamera dermaßen, daß man nur
validierte Tiefenwerte erhalten hat, so erhielt man nicht mehr für jeden Pixel
des Bildes einen Tiefenwert, was allerdings von der Anwendung gefordert wurde. Desweiteren war die Begrenzung der Darstellung der Tiefenbilder auf 255
Grauwerte ein Problem. Somit wurden die Abstände eng beieinander liegender
Objekte, die sich in dem Tiefenbild lediglich durch ein paar wenige Grauwerte
14
2.2
Stereokamera
15
Abbildung 4: Szene mit Tiefenbild
unterschieden, in der realen Szene jedoch einige Zentimeter weit auseinanderlagen, verfälscht und konnten nicht mehr maßstabsgetreu in den OpenGL Tiefenbuffer geschrieben werden. Um dies zu verbessern musste man die Parametrierung der Kamera ändern, was allerdings wieder zu oben genanntem Problem
führte, und die Unzulänglichkeit der Auflösung der Tiefenwerte auch nicht zufriedenstellend beseitigte. Auch die Anpassung der OpenGL Tiefenwerte an die
Tiefenwerte der Stereokamera bereitete Probleme. Um die beiden Systeme aneinander anzupassen, wurden Referenzpunkte in beiden Systemen gewählt, die
den Mittelpunkten der Markern entsprachen. Leider unterlagen die Tiefenwerte der Referenzpunkte der Stereokamera großen Schwankungen aufgrund von
Bildrauschen und fehlerhaft ermittelten Tiefenwerten, wodurch sich bei starken
Schwankungen erhebliche Fehler der Tiefenwerte ergaben und somit die Szene
nicht realistisch wiedergegeben werden konnte. In den Kapiteln 4 und 5 wird auf
diese Sachverhalte genauer eingegangen und es wird eine Möglichkeit vorgestellt,
um die Tiefenbilder in ihrer Qualität zu verbessern.
15
2.3
Umgebungsmapping
2.3
16
Umgebungsmapping
Um die Objekte realistisch zu beleuchten, wurden Umgebungsmaps eingesetzt,
die im folgenden näher beschrieben werden.
2.3.1
Grundlagen
Umgebungsmapping, auch Reflexionsmapping genannt, vereinfacht das Rendern
von verspiegelten Objekten, die ihre Umgebung reflektieren. Die Umgebungsmapping Methoden bieten besonders bei der Darstellung gekrümmter Flächen
eine gute Möglichkeit, die Reflexionen der Umgebung des Objekts anzunähern.
Die verschiedenen Verfahren des Umgebungs-Mappings beginnen alle mit der
Bestimmung des Blickstrahls, der vom Betrachter zum Objekt führt. Dieser
Blickstrahl wird unter Berücksichtigung der Normalen des Oberflächenpunkts
reflektiert. Die Richtung des dadurch gewonnenen Reflexionsvektors fungiert
als Index für die Umgebungsmap (s. Abb.5). Die Näherung der Reflexionen des
Umgebungsmapping setzen voraus, das sich die Objekte der Umgebung weit
entfernt vom darzustellenden Objekt befinden. Dies ist der Fall wenn sich z.B.
ein kleines Objekt in einem großen Raum befindet. Eine weitere Vorraussetzung
ist, daß sich der Reflektor nicht selbst reflektiert, d.h. das Objekt darf nicht
konkav sein9 , denn dies ist mit einer Umgebungsmap nicht zu erfassen. Es gibt
zwei Arten eine Umgebungsmap zu erstellen:
1. Syntethisch: Die Umgebungsmap wird virtuell erzeugt. Zum einen kann
man eine reflektierende Kugel in seine virtuelle Szene setzen und diese
mit der Ray Tracing Methode beleuchten. Somit hat man die Beleuchtungssituation der gesamten Szene in der Kugel fesgehalten und kann diese
gerenderte Kugel als Umgebungsmap für sphärisches Umgebungsmapping
verwenden. Man kann sich aus Texturen für kubisches Umgebungsmapping
auch per Image Warping eine Umgebungsmap für sphärisches Umgebungsmapping generieren10 . Will man hingegen kubisches Umgebungsmapping
9 Vgl.
Watt, 2002: 275
Generating
10 Blythe:
a
Sphere
16
Map
for
Specular
Reflection,
2.3
Umgebungsmapping
17
abgetasteter
Pixel
Betrachter
n
r
b
Umgebungs
Map
Die Projektionsfunktion
erzeugt aus dem
Reflexionsvektor (x,y,z)
Texturkoordniaten (u,v)
Reflektierende
Oberfläche
Abbildung 5: Prinzip der Umgebungsmap
verwenden, das Texel über das Verfolgen des Reflektionsvektors auf sechs
Seiten eines Würfels indiziert, so muß man die Szene aus sechs Blickrichtungen rendern, um die Texturen für die sechs Seiten des Würfels zu
erhalten.
2. Real : Hierbei wird die Umgebungsmap direkt aus einer realen Szene gewonnen, indem man eine reflektierende Kugel fotografiert. Mathemathisch
betrachtet gilt hierbei die Anforderung, daß die Kamera über eine unendliche Brennweite verfügen sollte und sich auch unendlich weit vom Objekt
entfernt befinden sollte11 , um möglichst die gesamte Beleuchtungssituation der Szene zu erfaßen.
Da sich die Arbeit mit der augmentierten Realität auseinandersetzt und sich
somit an realen Begebenheiten und nicht an synthetisch erzeugten orientiert,
wird hier im weiteren die Methode der Erzeugung der realen Umgebungsmap
verwendet.
http://www.opengl.org/resources/tutorials/sig99/advanced99/notes/node179.html,
[Stand: 16.12.2005]
11 Vgl. Shreiner [et al.], 2002: 428
17
2.3
Umgebungsmapping
18
Abbildung 6: Kugel Koordinatenverlauf, Vgl. Möller/Haines, 2002:155
2.3.2
Blinn/Newell Methode
1976 entwickelten Blinn und Newell12 den ersten Umgebungsmapping Algorithmus. In ihrem Algorithmus berechnen sie für jeden Pixel des Objekts den Reflexionsvektor, ausgehend vom Blickstrahl des Betrachters zu diesem Punkt. Der
erhaltene Reflexionsvektor wird dann in sphärische Koordinaten (ρ, φ) transformiert. Das Verfahren wird auch manchmal als Längen/Breiten-Mapping bezeichnet, denn ρ, variierend zwischen 0 und 2π, stellt bei der sphärischen Projektion den Längengrad dar und φ, variierend zwischen 0 und π, den Breitengrad.
ρ und φ berechnen sich dabei folgendermaßen:
ρ = arccos(−rz )
(1)
φ = atan2(ry , rx )
(2)
Der Reflexionsvektor r in den Gleichungen berechnet sich durch:
r = b − 2(n · b)n
(3)
b ist dabei der Blickstrahl und n ist die Oberflächennormale in dem durch den
Blickstrahl festgelegten Punkt auf der Oberfläche. Um nun gültige (u, v) Texturkoordinaten zu erhalten, werden die sphärischen Koordinaten (ρ, φ) in den
Wertebereich [0, 1) transformiert. Aufgrund der Transformation in spärische Koordinaten kann man sich die Umgebungsmap auch als Bild einer aufgefalteten
Kugel vorstellen
12 Vgl.
13 Vgl.
13
(s. Abb.6). Es wird klar, warum diese Projektion manchmal
Möller/Haines, 2002:154
Möller/Haines, 2002:155
18
2.3
Umgebungsmapping
19
auch Längen/Breiten-Mapping genannt wird, denn die beiden Texturkoordinaten (u, v) entsprechen dem Längen/Breitengrad der Kugel. Es folgen nun einige
charakteristische Punkte der Projektion14 :
Name
Koordinate
Winkel
N(Nordpol)
(0,0,1)
ρ = π,φ ist nicht definiert
S(Südpol)
(0,0,-1)
ρ = 0,φ ist nicht definiert
M
(1,0,0)
ρ = π/2,φ = 0
O
(0,1,0)
ρ = π/2,φ = π/2
P
(-1,0,0)
ρ = π/2,φ = π
Q
(0,-1,0)
ρ = π/2,φ = 3π/2
Tabelle2: Wertebereichstabelle
Leider weist diese Methode einige Schwachpunkte auf:
Zum einen befindet sich bei φ = 0 ein Rand und desweiteren konvergiert die
Umgebungsmap an den Polen. Aufgrund des Wertebereichs der (u, v) Koordinaten von [0, 1) ist φ an den Polen nicht bestimmt. Daher kann es an den Polen
zu Verzerrungsproblemen kommen, da die vertikalen Nahtstellen der Map nicht
übereinstimmen15 . Ein anderer Schwachpunkt ist, daß bei der Interpolation zwischen zwei Texturkoordinaten Probleme auftreten können. Geht man z.B. von
einer zu rendernden Linie aus, die durch die Punkte P und Q definiert ist, wobei im Punkt P die u Koordinate bei 0.97 liegt und im Punkt Q bei 0.02. Dann
wird ein Fehler (wir vernachläßigen in diesem Bespiel die Nahtstellen der Textur) auftreten, weil sich die Interpolation von 0.97 abwärts hin zu 0.02 bewegen
würde ( 0.96, 0.95 ..... 0,01, 0,02)16 .
2.3.3
Sphärisches Mapping
Sphärisches Mapping war das erste Umgebungsmapping, das von kommerzieller
Graphikhardware unterstützt wurde17 . Der normalisierte Blickvektor vom Be14 Vgl.
Möller/Haines,
Möller/Haines,
16 Vgl. Möller/Haines,
17 Vgl. Möller/Haines,
15 Vgl.
2002:155
2002:156
2002:156
2002:158
19
2.3
Umgebungsmapping
20
trachter zum Vertex auf der Oberfläche des Objekts wird als b bezeichnet. Die
Berechnung findet im Kamerakoordinatensystem statt, wobei sich die Kamera
im Ursprung an der Stelle des Betrachters befindet, und b die Position des Vertex
auf der Oberfläche im Kamerakoordinatensystem darstellt. Die Normale n wird
ebenfalls ins Kamerakoordinatensystem durch Multiplikation mit der transponierten inversen Modelviewmatrix gebracht, und anschließend normalisiert. Um
den Reflektionsvektor zu berechnen, wird die folgende Gleichung verwendet:
r = b − 2(n · b)n
(4)
Da b und n normalisiert sind, erhält man mit dem Refklektionsvektor r ebenfalls
einen normalisierten Vektor und kann ihn sich als 3D Punkt auf der Einheitskugel vorstellen. Der Normalenvektor n ist genau der halbierte Winkel zwischen
Reflektionsvektor und Blickstrahl. Letzterer entspricht (0,0,1) im lokalen Koordinatensystem der Einheitskugel. Also ergibt sich der Normalenvektor einfach
aus der Summe des Blickstrahls und des Reflektionsvektors:
(rx , ry , rz ) + (0, 0, 1) = (rx , ry , rz + 1)
(5)
Diesen Vektor gilt es anschließend noch zu normalisieren:
m=
q
n=
rx2 + ry2 + (rz + 1)2
rx ry rz + 1
, ,
m m
m
(6)
(7)
Die Koordinaten dieser Einheitsnormalen entsprechen dem Punkt h der Normalen auf der Einheitskugel (Vgl. Abb.7). Nun verfügen wir also über den Reflektionsvektor, der uns unsere Umgebungsmap indizieren kann, müssen ihn aber
noch in den 2D Raum transfomieren, damit wir korrekte Koordinaten für die
Umgebungsmap erhalten. Die Reduktion auf den 2D Raum entspricht einer
Projektion auf die Einheitskugel in der rz = 0 Ebene:
m=
q
rx2 + ry2 + (rz + 1)2
u=
rx
+ 0, 5
2m
20
(8)
(9)
2.3
Umgebungsmapping
21
y
h_y
v
n
r
h
Zum Auge
Ursprung
rad
ius
z
=1
Unterer Rand der
spärischen Map
Abbildung 7: Schaubild Umgebungsmap, Vgl. Möller/Haines, 2002:160
v=
ry
+ 0, 5
2m
(10)
Da r normalisiert ist, wird auch rx und ry normalisiert sein und daher im Wertebereich [−1, 1] liegen. Um korrekte Texturkoordinaten zu erhalten, benötigen
wir aber Koordinaten im Bereich [0, 1]. Die Transformation des Wertebereichs
wird in Gleichung (9) und (10) durch die Skalierung von 0,5 und durch die
Addition von 0,5 erreicht. Sphärisches Mapping bietet im Gegensatz zu dem
Verfahren von Blinn und Newell diverse Vorteile:
Zum einen existiert keine Texturnaht, über die man interpolieren müßte und es
liegt auch nur eine Singularität an den Rändern der Map vor, die aber wenig
Probleme bereitet, da sich alle gültigen Texturbereiche im Innern des Kreises
der Umgebungsmap befinden, und so die Ränder nicht überschritten werden18 .
Leider hat das Verfahren auch einige Nachteile:
1. Der Abstand zwischen zwei Punkten der spärischen Map ist nicht linear.
Wie in der Methode von Blinn und Newell ist die lineare Interpolation auf
der Textur lediglich eine Approximation und Fehler treten umso häufiger
auf, je mehr man sich den Rändern der Map nähert19 .
2. Die Spärische Map ist nur gültig für eine bestimmte Blickrichtung, d.h.
wenn der Betrachter seine Position verändert und die Map nicht aktua18 Vgl.
19 Vgl.
Möller/Haines, 2002:160
Möller/Haines, 2002:161
21
2.4
Multitexturing
22
lisiert wird, so wird das virtuelle Objekt unter der neuen Blickrichtung
dennoch so gerendert, als würde der Betrachter an seiner unsprünglichen
Position stehen. Dies kann, da sich der Blickstrahl ändert, zu visuellen
Artefakten führen. Es ist zwar möglich die Texturkoordinaten für jede
neue Blickrichtung in jedem Frame berechnen zu lassen, jedoch kann auch
dies zu visuellen Artefakten führen, weil manche Teile der spärischen Map
aufgrund der neuen Blickrichtung vergrößert erscheinen, und die Singularitäten an den Rändern auch zu einem Problem werden20 . Sphärisches
Umgebungsmapping ist also von der Blickrichtung abhängig. Um speziell dieses Problem zu umgehen, wird in dem hier vorgestellten Verfahren,
in jedem Frame eine sphärische Umgebungsmap erstellt, so daß die oben
genannten Probleme vermieden werden.
2.4
Multitexturing
Unter einfachem Texturmapping versteht man die Abbildung einer zweidimensionalen Textur auf ein dreidimensionales Objekt. Multitexturing hingegen erlaubt die Kombination mehrerer Texturen um ein dreidimensionales Objekt zu
texturieren. Man unterscheidet zwischen Single-, und Multipass Multitexturing.
Singlepass Multitexturing verwendet die Graphikhardware um mehrere Tex”
ture Units“ in einem einzigen Renderingschritt darzustellen. Als Textur Unit“
”
bezeichnet man hierbei eine Textur in der Pipeline“ des Multitexturings (Vgl.
”
Abb.8). Leider unterstützt erst die modernere Graphikhardware Multitexturing.
Ob die eigene Graphikhardware Multitexturing unterstützt kann man durch
einen einfachen OpenGL Befehl herausfinden:
const GLubyte *glGetString(GLenum name);
Als Parameter name ist dabei GL EXT EN SION S anzugeben. Lässt sich
GL ARB M ultitexture im Rückgabestring finden, so wird Multitexturing unterstützt. Wie viele einzelne Textureinheiten man dabei verwenden kann, hängt
von der jeweiligen Graphikhardware ab und kann mit:
20 Vgl.
Möller/Haines, 2002:161
22
2.4
Multitexturing
23
glGetIntegerv (GL_MAX_TEXTURE_UNITS_ARB, &num)
herausgefunden werden. Multipass Multitexturing hingegen zeichnet ein 3D Objekt n-mal an der gleichen Stelle, wobei n-mal eine andere Textureinheit verwendet wird. Die n Textureinheiten werden über Blending vermischt. Diese
Arbeit wird im folgenden das Singlepass Multitexturing verwenden, um sich
der Vorteile der Graphikhardware in Bezug auf die Geschwindigkeit zu bedienen. Wie oben bereits erwähnt, verläuft das Multitexturing in einer eigenen
Pipeline“ (s. Abb.8). In jeder Textur Unit verbinden sich die Farbwerte des
”
aktuell darzustellenden Fragments mit den Farbwerten der bereits in den vorherigen Textur Units vermischten Fragmente. Dabei kann man wie gewohnt
die Texturingsumgebungen GL REP LACE, GL M ODU LAT E, GL DECAL,
GL BLEN D, GL ADD und GL COM BIN E verwenden. Singlepass Multi-
Abbildung 8: Multitexturing, Vgl. Shreiner [et al.], 2002:432
texturing erspart dem Benutzer somit nicht nur zusätzliche Renderingschritte,
sondern es lassen sich auch sehr komplexe Shading Models“ darstellen. Zum
”
Beispiel lässt sich ein Beleuchtungsmodell, welches die Gleichung (A·B)+(C ·D)
verwendet, mit einfachem Texturemapping nicht darstellen. Ein Multipass Algorithmus könnte A·B in zwei Renderingschritten kombinieren und C im nächsten
Schritt hinzufügen. Jedoch würde nicht C · D hinzugefügt, denn es kann jeweils
23
2.4
Multitexturing
24
nur eine Farbe im Color Buffer“ gespeichert werden. Mit Multitexturing hin”
gegen, könnte der erste Renderschritt A · B berechnen, der zweite könnte C · D
berechnen und das Ergebnis zu A · B im Color Buffer addieren21 .
Somit lassen sich mit Multitexturing fortgeschrittene Renderingtechniken wie
z.B. Beleuchtungseffekte, Decals“, Compositing“ und detailierte Texturen im”
”
plementieren22 .
21 Vgl.
22 Vgl.
Möller/Haines, 2002:146 f.
Shreiner [et al.], 2002:432
24
2.4
2.4.1
Multitexturing
25
Multitexturing in OpenGL
Multitexturing ist in OpenGL eine Erweiterung, die vom Architecture Review
Board (ARB) spezifiziert wird. Sie wird ferner nicht von jeder Graphikkarte unterstützt (s.o.). Wird Microsoft Win32 verwendet, so müssen um Multitexturing
anzuwenden, erst einmal die Zeiger auf die Extensionfunktionen mit wglGetProcAddress() gesetzt werden:
PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB = NULL;
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL;
PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL;
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)
wglGetProcAddress(glMultiTexCoord2fARB);
glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)
wglGetProcAddress(glActiveTextureARB);
glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)
wglGetProcAddress(glClientActiveTextureARB);
Es ist ferner die Header Datei glext.h“ einzubinden, und es müssen Texturko”
ordinaten vergeben werden. Mit
glMultiTexCoord{1234}{sifd}(GLenum texUnit, TYPE coords)
kann man jedem Vertex mehrere Texturkoordinaten zuweisen. Verwendet man
stattdessen
glTexCoord*(...)
wie beim normalen Texturmapping, entspricht dies dem Aufruf23 :
MultitexCoord*(GL_TEXTURE0,....)
Anschliessend defininert man sich die anzuzeigenden Texturen:
glGenTextures(2, texNames);
glBindTexture(GL_TEXTURE_2D, texNames[0]);
23 Vgl.Shreiner
[et al.], 2002:436
25
2.4
Multitexturing
26
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXTRES, TEXTRES,
0, GL_RGBA, GL_UNSIGNED_BYTE, texture1);
//------------------------------------------------------------glBindTexture(GL_TEXTURE_2D, texNames[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXTRES, TEXTRES,
0, GL_RGBA, GL_UNSIGNED_BYTE, texture2);
Die Texturen sind nun erzeugt und stehen zur Anwendung bereit:
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(G_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texNames[0]);
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
/-----------------------------------------------------------glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texNames[1]);
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
Obiges Texturmapping addiert die Farbwerte der einzelnen Texturen.
glActiveT extureARB(GLenumtexU nit) gibt dabei die im Moment zu aktivierende Textur an. Jetzt kann das zu texturierende Objekt mit der Multitexturingtextur gezeichnet werden.
26
2.5
2.5
Beleuchtungsmodell
27
Beleuchtungsmodell
Im Folgenden wird das klassische OpenGL Beleuchtungsmodell erklärt und dem
verwendeten Beleuchtungsmodell gegenübergestellt.
2.5.1
OpenGL Beleuchtungsmodell
Das Beleuchtungsmodell, das in OpenGL verwendet wird, drückt sich durch
folgende Beleuchtungsformel aus:
L = M e + M a · La +
Lq
X
(Ma · La,i + Md · cos ϕi · Ld,i + Ms · cosn ψi · Ls,i ) (11)
i=1
Diese Formel stellt allerdings keine physikalisch korrekte Form der Beleuchtung
Abbildung 9: Beleuchtung, Vgl.Müller: Licht und Materialien
dar, sondern kann lediglich als eine Annäherung an die menschliche Wahrnehmung des Lichtes betrachtet werden. In der Formel vereinigen sich der Emissionsterm des Objektes Me , der ambiente Term, der sowohl global Ma · La als
auch pro Lichtquelle Ma · La,i in die Berechnung mit eingeht, der diffuse Term
Md · cos ϕi · Ld,i und der spiegelnde Term Ms · cosn ψi · Ls,i . Damit stellt sich
das Licht in OpenGL als Summe aus den oben genannten Komponenten dar,
wobei der ambiente Term, der diffuse Term und der spiegelnde Term über alle
Lichtquellen aufsummiert werden und dieses Ergebnis der Summe aus emissions
und globalem ambienten Term hinzugefügt werden. Die einzelnen Komponenten
sind in Abb.9 und 12 nochmals zur graphischen Veranschaulichung dargestellt 24 .
24 Müller:
Licht und Materialien,
http://geri.uni-koblenz.de/ws0203/cg2folien/9 lichtmat 6.pdf, [Stand: 04.01.2006]
27
2.5
Beleuchtungsmodell
2.5.2
28
Verwendetes Beleuchtungsmodell
Abbildung 10: Aufbau
Während bei OpenGL die Eckpunkte anhand obiger Formel, unter der Voraussetzung, daß die Lichtquellen und Materialien der Objekte entsprechend gesetzt wurden, beleuchtet werden, verfolgt diese Arbeit den Ansatz, die Beleuchtung aus einer realen Szene abzuleiten und die Objekte letztlich durch Texturierung zu beleuchten. Es sollen Texturen aus der realen Szene gewonnen werden,
welche die Beleuchtungssituation der Szene in der Textur speichern und durch
Kombination der Texturen ein virtuelles Objekt so ”beleuchten”bzw. texturieren, als wäre es ein Bestandteil der realen Szene. Um dies zu erreichen, wurden
zwei Kugeln eingesetzt, die die Beleuchtungssituation des Raumes einfangen.
Den Aufbau der Kugeln mit den entsprechenden Markern um die Kugeln zu
tracken sieht man in Abbildung 10. Mit einem weiter unten vorgestellten Verfahren wurden diese beide Kugeln getrackt und aus dem Videobild ausgeschnitten,
um sie als Textur für die virtuellen Objekte zu verwenden. Die ausgeschnittenen
Texturen sieht man in Abbildung 11. Aus der reflektierenden Kugel wurde ferner eine Textur gewonnen, die die Glanzlichter der Szene darstellen sollte. Dazu
wurde die Textur der reflektierenden Kugel binarisiert, wobei der Schwellschwert
28
2.5
Beleuchtungsmodell
29
Abbildung 11: Diffuse und reflektierende Kugel
einstellbar ist, so dass sich die Menge und Größe der Glanzlichter eines Objektes
parametrieren lassen, entsprechend der Glanzzahl in OpenGL. Mit der Textur
des 3D Objekts ergeben sich so 4 Texturen, mit denen im weiteren gearbeitet
wird. Wie man die einzelnen Texturen letztlich miteinander kombiniert, ist dem
Benutzer bzw. dem gewünschten Ergebnis überlassen, doch für eine realistische
Darstellung machen nicht alle Kombinationen Sinn. Um das Beleuchtungsmodell
von OpenGL annähernd abzubilden, kann man beispielsweise alle 4 Texturen gewichtet aufsummieren, wobei die Gewichte der jeweiligen Textur parametrierbar
sind, ähnlich der Festlegung der Parameter der Lichtquellen und der Materialien, die in OpenGL vorzunehmen sind. Abbildung 12 und 13 veranschaulichen
dieses Prinzip. Die erste Kugel stellt dabei die Textur des Objekts dar. Die
zweite Kugel hält den diffusen Anteil des Lichts in der Szene fest, ähnlich dem
diffusen Anteil jeder Lichtquelle und des Materials in OpenGL. Durch die dritte
Abbildung 12: Texturierungsverfahren
Kugel wird die komplette Szene eingefangen, da diese Kugel verspiegelt ist. In
Analogie zu OpenGL, könnte man diese Kugel als den ambienten Anteil sowie
den spekularen Anteil betrachten. Um aber die Glanzlichter unabhängig von
der verspiegelten Kugeln parametrieren zu können, wird die vierte Kugel wie
oben bereits beschrieben aus der dritten Kugel gewonnen. Somit erhält man ei29
2.5
Beleuchtungsmodell
30
Abbildung 13: Beleuchtungstexturen
ne ungefähre Analogie zu OpenGL, wobei in diesem Modell weit mehr ermittelt
bzw. festgehalten wird, als es mit der Standardbeleuchtung in OpenGL möglich
ist. Durch Verwendung einer verspiegelten Kugel kann man Objekte verspiegelt darstellen, was in OpenGL standardmäßig nicht möglich ist. Ferner erhält
man in einem Pixel der reflektierenden Kugel alle Lichtinformation der Szene,
d.h. es wird auch indirektes Licht wiedergegeben. Drückt man den Weg, den
das Licht von der Lichtquelle zum Auge nehmen kann durch einen Formalismus
wie LA aus, so kann in OpenGL maximal eine diffuse Fläche dazwischenliegen, also LDA. Die reflektierende Kugel gibt das komplette Licht der Szene,
daß in diesem Pixel eintrifft wieder. Damit sind also auch Wege des Lichtes wie
LD*A, oder Wege mit dazwischenliegenden spiegelnden Objekten möglich, also
LS*D*A, wobei S* angibt, daß beliebig viele spiegelnde Flächen dazwischenliegen können. Es wird also jeder mögliche Weg, den das Licht gehen kann, in der
reflektierenden Kugel erfasst. In rein virtuellen Umgebungen stellt gerade diese
Erfassung des Lichts ein großes Problem dar, daß nur über sehr rechenaufwändige Verfahren wie Radiosity oder Ray Tracing gelöst werden kann und für alle
möglichen Wege des Lichts noch nicht in Echtzeit berechnet werden kann. In
30
2.5
Beleuchtungsmodell
31
der erweiterten Realität kann man hingegen den Vorteil nutzen, das man über
die verspiegelte, sowie die diffuse Kugel bereits alle notwendigen Informationen
gewinnen kann, um die virtuellen Objekte so zu beleuchten, als würden sie sich
in der realen Szene befinden. Man setzt die beiden Kugeln quasi als Lichtmesser
ein, um die realistische Darstellung der Beleuchtung nicht mehr aufwendig simulieren zu müssen, sondern aus der realen Szenerie abzuleiten. Die realistische
Darstellung von Licht muss dabei die Beleuchtungsgleichung erfüllen:
Z
ρ (dAe , d$i , d$0 ) · Li (dAe , d$0 ) · cos θi · d$i
L0 (dAe , d$0 ) = Le (dAe , d$0 )+
2π
(12)
Diese Gleichung25 wird durch verschiedene Verfahren wie Ray Tracing und Radiosity simuliert angenähert, um eine realistische Darstellung der Objekte zu
ermöglichen. Durch erfassen der beiden Kugeln im Bild, welche die aktuelle
Beleuchtungssituation des Raumes einfangen, erhält man
L0 (dAe , d$0 )
(13)
Um dieses Ergebnis wieder in die einzelnen Bestandteile der obigen Formeln zu
zerlegen, bzw. die einzelnen Bestandteile anzunähern, um Materialeigenschaften von Objekten modellieren zu können, wurden 2 Kugeln eingesetzt, wobei es
durchaus auch möglich gewesen wäre, die Textur der diffusen Kugel rechnerisch
aus der reflektierenden Kugel zu gewinnen, wie Ramamoorthi und Hanrahan in
ihrer Arbeit zeigen26 . Leider ist mit dem Verfahren keine realistische Darstellung transparenter Objekte möglich, da Lichtbrechungen innerhalb des virtuellen Objektes nicht berücksichtigt werden. Man könnte diese Brechungen zwar
innerhalb des Objektes berechnen, müsste aber darauf verzichten, daß dieses
Licht wieder in der realen Szene dargestellt wird. Um die verschiedenen Texturen zu kombinieren, werden Techniken des Multitexturing angewendet, die
25 Müller:
Photorealistische Computergraphik,
http://www.uni-koblenz.de/FB4/Institutes/ICV/AGMueller/Teaching/SS05/PCG,
[Stand:
04.01.2006]
26 Ramamoorthi, Hanrahan: An Efficient Representation for Irradiance Environment Maps,
http://graphics.stanford.edu/papers/envmap/,
[Stand: 10.12.2005]
31
2.5
Beleuchtungsmodell
32
Abbildung 14: Konkrete Beleuchtungen
oben bereits erwähnt wurden. Abbildung 13 zeigt die oben beschriebenen ermittelten Texturen. Abbildung 14 demonstriert die Anwendung der Texturen
zur Beleuchtung. In dem linken Bild wurden dabei folgende Parameter gesetzt:
OriginalTextur:
1.0
Diffuse Kugel:
0.0
Spiegelnde Kugel:
0.3
Glanzeffekt:
0.2
Schwellwert: 235
Bei der Darstellung des rechten Bildes wurden hingegen diese Parameter verwendet:
OriginalTextur:
0.9
Diffuse Kugel:
0.3
Spiegelnde Kugel:
0.0
Glanzeffekt: 0.5
Schwellwert: 215
32
2.6
2.6
Schatten Volumen
33
Schatten Volumen
Im folgenden Abschnitt wird das verwendete Schattierungsverfahren vorgestellt.
Es soll zur Schattierung der realen Szene eingesetzt werden.
2.6.1
Grundlagen
Schattenvolumen stellen ein robustes Verfahren dar, um beliebige Objekte zu
schattieren. Sie verwenden dazu den Stencilbuffer, um den schattierten Bereich
in einem Bild auszumaskieren. Das Verfahren basiert im Prinzip auf der Tatsache, daß man sich für jedes Objekt und jede Lichtquelle der darzustellenden Szene ein eigenes Schattenvolumen berechnet. Um das Schattenvolumen effizient zu
berechnen, werden für die Berechnung des Volumens nur die Vertices der Polygone herangezogen, die in Richtung der betrachteten Lichtquelle ausgerichtet sind.
Für jeden dieser Vertices errechnet man sich den Vektor li,j von der Lichtquelle
zum Vertex, wobei i = 1, ...n der Anzahl der Lichtquellen und j = 1, ..., n der
Anzahl der den Lichtquellen zugewandten Vertices entspricht. Diese Vektoren
sollte man sich als unendliche Vektoren vorstellen, denn durch die Verlängerung
der Vektoren wird das eigentliche Schattenvolumen aufgespannt (Vgl. Abb.15).
Stellt man sich ferner alle Polygone die der Lichtquelle zugeneigt sind, als eine
Region und alle die der Lichtquelle abgeneigt sind, als eine andere Region vor, so
liegt an der Grenze dieser beiden Regionen die Schattenkante des betrachteten
Objekts. Eine effizientere Methode das Schattenvolumen zu berechnen, ergibt
sich dadurch, daß man nur die Vertices einer Schattenkante betrachtet und diese verlängert, um das Schattenvolumen aufzuspannen. Um nun herauszufinden
ob sich ein Objekt des Bildes innerhalb des Schattens eines anderen Objekts
liegt oder nicht, nutzt man den Stencilbuffer. Zuerst wird der Stencil Buffer
gelöscht, um etwaige Einträge zurückzusetzen. Anschließend wird die darzustellende Szene in den Frame Buffer gezeichnet. Da das Schattenvolumen zur reinen
Ermittlung des Schattens verwendet wird und nicht Bestandteil der darzustellenden Szene ist, wird im nächsten Schritt das Schreiben in den Tiefen,- und
Colorbuffer abgeschaltet. Nun erhöht man an allen Stellen des Bildes, an denen
33
2.6
Schatten Volumen
34
Abbildung 15: Prinzip des Schattenvolumen
sich eine dem Betrachter zugewandte Seite des Schattenvolumens befindet, den
Wert des Stencil Buffers um 1. Darauf folgend erniedrigt man an allen Stellen
des Bildes, an denen sich eine dem Betrachter abgewandte Seite des Schattenvolumens befindet, den Wert des Stencil Buffers um 1. Es bleibt nur der Bereich
im Stencil Buffer maskiert, an dem sich der Schatten des Objektes befindet.
Abbildung 16 veranschaulicht dieses Prinzip.
Um den schattierten Bereich dann darzustellen, zeichnet man ein Polygon das
den gesamten Bildbereich überdeckt und sich orthogonal zum Betrachtungspunkt befindet. Dieses wird genutzt um die Szene genau an den vom Stencil
Buffer ausmaskierten Stellen per Blending abzudunkeln. Zusammenfassend kann
man also sieben Schritte des Verfahrens festhalten:
1. Schattenvolumen aus den errechneten verlängerten Vektoren bilden
2. Stencil Buffer zurücksetzen
3. Zeichnen der darzustellenden Szene ohne Schattenvolumen
4. Ausschalten des Tiefen-, sowie des Color Buffers
5. Zum Betrachter ausgerichtete Polygone des Schattenvolumens zeichnen
34
2.6
Schatten Volumen
35
Abbildung 16: Berechnung des Schattenvolumen
und den Stencil Buffer dabei um 1 erhöhen
6. Vom Betrachter abgewandte Polygone des Schattenvolumens zeichnen und
den Stencil Buffer dabei um 1 erniedrigen
7. Polygon zeichnen, daß den gesamten Bildbereich abdeckt und orthogonal
zum Betrachter ausgerichtet ist. Per Blending dann die Schattenbereiche,
d.h. die durch den Stencil Buffer ausmaskierten Bildbereiche abdunkeln.
Es ist ferner möglich nicht nur harte Schatten mit dem Verfahren darzustellen,
sondern es ist auch möglich weiche Schatten abzubilden. Stellt man sich vor, man
verwendet mehrere Lichtquellen in einer Szene, die für jedes beleuchtete Objekt,
daß sich im Raum befindet ein Schattenvolumen erzeugen, so gibt es Stellen an
denen sich mehrere Schattenvolumen überschneiden. Damit erhöht sich auch
der Wert des Stencil Buffers an den betreffenden Stellen und man erhält einen
aus heterogenen Werten bestehenden Stencil Buffer. Anhand der verschiedenen
Werte ist es nun möglich weiche Schatten über Blending Methoden zu zeichnen.
35
2.6
Schatten Volumen
36
Abbildung 17: Problem mit dem Schattenvolumen
2.6.2
Probleme
Ein Problem des Verfahrens besteht darin, ersichtlich in Abbildung 17, daß der
Schatten nicht nur auf dem in der Abbildung dargestellten Quader liegen bleibt,
sondern auch in dem Bereich hinter dem Quader. Die korrekte Darstellung findet sich in Abbildung 18.
Ein weiteres Problem besteht in der Darstellung von Objekten, die die Farbe
des Lichtes verändern, wie z.B. verschmutztes Glaß
27
.
Letztendlich hängt die Performanz des Verfahrens von der Anzahl der Polygone
des Schatten werfenden Objekts ab. Dennoch lässt sich das Verfahren durch die
oben dargestellte Verbesserung, d.h. durch die Reduktion der Eingangsdaten
auf die Schattenkanten des Objekts, erheblich optimieren, im Vergleich zu der
brute-force“ Methode, bei der alle Vertices, der zu der Lichtquelle ausgerichte”
ten Polygone in die Berechnung des Schattenvolumens mit eingehen.
27 Vgl.
Möller/Haines, 2002:267
36
2.7
Verfahren
37
Abbildung 18: Lösung des Problems mit dem Schattenvolumen
2.7
Verfahren
Das in dieser Arbeit erarbeitete Verfahren teilt sich in verschiedene Bearbeitungsschritte auf, die im folgenden beschrieben und auf die im nächsten Abschnitt näher eingegangen wird. Generell besteht das erste Problem darin, die
Texturen der beiden Kugeln aus dem Videobild auszuschneiden, d.h. die Position der beiden Kugeln im Bild zu verfolgen und immer an der richtigen Stelle die
Pixel, die die Kugeln darstellen, aus dem Bild zu extrahieren. Dies lässt sich mit
den Markern und den Funktionen des ARToolkit implementieren. Wie aus Abbildung 10 hervorgeht werden jeder Kugel zwei Marker zugewiesen. Es sollten
zwei Marker sein, damit das System eine gewisse Ausfallsicherheit gewährleisten kann, denn es kommt vor, daß das Trackingverfahren des ARToolkits aus
Gründen, die bereits im Kapitel 2.1 erläutert wurden, versagt. Hat man nun
die Kugeln erfolgreich getrackt, muss man die 2D Koordinaten des Kugelmittelpunktes und des Kugelrandes bestimmen, um die Kugel aus dem 2D Bild
auszuschneiden. Dazu programmiert man einen Teil der OpenGL Renderingpipeline nach, um aus den 3D Koordinaten die projezierten 2D Koordinaten zu
gewinnen. Hat man die zwei Ausschnitte mit den Kugeln erhalten, so müssen
diese auf eine 2er Potenz skaliert werden, um als Textur dargestellt werden zu
37
2.7
Verfahren
38
Marker Erkennung
Texturierung/
Beleuchtung
Tracken der Kugeln
Textur der Kugeln im Bild ermitteln
Kombination der Texturen per Multitexturing
Schattierung
Tiefenbild grabben
Tiefenwerte in OpenGL z-Buffer schreiben
Schatten zeichnen durch Shadow Volumes
virtuelle Objekte in reale Szene zeichnen
Abbildung 19: Übersicht über das Verfahren
können. Die ermittelten Texturen werden anschließend wie im Kapitel 2.4 beschrieben per Multitexturing in beliebiger Weise kombiniert und auf das Objekt
gebracht. Als nächstes wird von der Stereokamera ein Tiefenbild der Szene genommen. Ein mögliches Tiefenbild ist in Abbildung 4 zu sehen. Die Tiefenwerte
werden dabei als Grauwerte dargestellt, also im Bereich von 0...255. Objekte,
die sich nah an der Kamera befinden, werden dabei heller dargestellt, als Objekte die weiter entfernt sind. Es gilt also, daß das am weitesten entfernte Objekt
den Farbwert Schwarz mit dem Grauwert 0 und das Objekt mit der geringsten Distanz zur Kamera den Farbwert Weiß mit dem Grauwert 255 zugewiesen
bekommt. Diese Tiefenwerte gilt es nun in den Tiefenbuffer von OpenGL zu
schreiben, wobei die Werte aus dem Bild an den Wertebereich der Tiefenwerte
im OpenGL Tiefenbuffer angepasst werden müssen, damit einheitlich auf den
Werten gearbeitet werden kann. Nachdem die Tiefenwerte der realen Szene im
Tiefenbuffer von OpenGL stehen, kann man mit der Berechnung des Schattens
beginnen. Hierzu spannt man sich ein Schattenvolumen zwischen dem darzustellenden Objekt und einer Lichtquelle auf. Befinden sich mehrere Lichtquellen in
der virtuellen Szene, so werden mehrere Schattenvolumen aufgespannt. Durch
das Schattenvolumenverfahren erhält man einen Schatten, der zusammen mit
dem darzustellenden Objekt gerendert wird. Der Schatten kommt dabei nicht
38
3. Implementierung
39
nur auf virtuell dargestellten Objekten zum liegen, sondern auch auf realen Objekten, weil die Tiefenwerte der realen Szene in den Tiefenbuffer von OpenGL
übernommen wurden. Die Schwierigkeit bei dem ganzen Verfahren besteht darin, die erwünschte Darstellung in Echtzeit erhalten zu können, damit die Immersion des Betrachters nicht beeinträchtigt wird. Auf die erwähnten Aufgaben und
Probleme, die sich aus der obigen Beschreibung ergeben, wird im nächsten Kapitel detailierter eingegangen. Abbildung 19 veranschaulicht die verschiedenen
Bearbeitungsschritte.
3
Implementierung
Während dieser Arbeit sind letztlich zwei verschiedene Softwareversionen entstanden, die sich lediglich in dem Punkt unterscheiden, daß die eine Version mit
einer normalen Webcam zu betreiben ist, und die andere mit der Stereokamera arbeitet. Im folgenden wird die Softwareversion, die mit der Stereokamera
arbeitet, vorgestellt. Diese Version unterscheidet sich von der anderen Version
nur in Bezug auf die Verwendung von der Stereokamera ermittelten Tiefenwerte. Die Version, die mit der Webcam arbeitet, simuliert lediglich Tiefenwerte
der realen Szene, in dem sie nachmodellierte Objekte der realen Szene als 3D
Modell in den OpenGL Tiefenbuffer zeichnet. Da die Stereokamera auf 4 Tiefenbilder pro Sekunde beschränkt ist und dies damit den Flaschenhals der Applikation darstellt, werden mit der Webcamversion weit höhere fps Raten erzielt.
Durch Erstellung beider Softwareversionen ist es ferner möglich, einen genaueren Vergleich bzw. eine genauere Analyse bezüglich der Echtzeitanforderung
der Applikation zu erstellen. Da die verwendete Stereokamera Bilder in einer
Auflösung von 1024x768 liefert, das ARToolkit als Eingabe jedoch Bilder mit
einer Auflösung von 320x240 erwartet, muss das Eingangsbild auf 320x240 mittels: intz = gluScaleImage(GL RGBA, 1024, 768, GL U N SIGN ED BY T E,
data, 320, 240, GL U N SIGN ED BY T E, buf ) herunterskaliert werden. Leider
ist dieser Funktionsaufruf im Vergleich zu allen anderen in dieser Arbeit verwendeten Algorithmen der am rechenintensivste und somit der teuerste. Es wird
39
3. Implementierung
40
im Kapitel Performanz weiter darauf eingegangen. Nach der Initialisierung der
Applikation, in der die notwendigen Einstellungen des ARToolkits, der 3D Kamera, und der für die Applikation wichtigen Variablen initialisiert werden, sowie
die VRML Modelle geladen werden, folgen die bereits in Kapitel 2.7 beschriebenen Schritte des MainLoops. Zu Beginn wird jeweils ein Bild der Kamera
genommen, aus dem mit den Routinen des SDKs der Stereokamera ein Tiefenbild gewonnen wird. Dieses Tiefenbild gilt es nun in den Tiefenbuffer von
OpenGL zu schreiben, und die Wertebereiche des Bildes und des OpenGL Tiefenbuffers anzupassen. Die Variable depthV alue stellt dabei den Tiefenwert des
Mittelpunkts des aktuell zum Zeichnen der Objekte verwendeten Markers in
OpenGL dar. Die Variablen depthDif f.x, depthDif f.y hingegen den Tiefenwert des Markermittelpunkts im Tiefenbild der Stereokamera.
float *depthImageTemp;
if(depthValue != 0) {
int w,h; w = 320; h=240;
depthImageTemp = new float[w*h];
for(int i=0; i<w*h; i++) {
// scale to range 0...1 and invert
// to ensure the values range from 0...1 not from 1...0
depthImageTemp[i] = 1.0 -(depthImage.data[i]/255.0);
}
int t1 = depthDiff.x;int t2 = depthDiff.y;
// Only if a marker is detected, the factor is set correctly,
// otherwise set to 1
double factor = 0;
factor = depthImageTemp[t1*ROW+ t2] / depthValue;
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glClear(GL_DEPTH_BUFFER_BIT);
glDepthFunc(GL_ALWAYS);
glDrawPixels(w,h, GL_DEPTH_COMPONENT,GL_FLOAT, depthImageTemp);
40
3. Implementierung
41
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
Es werden zuerst die Pixel aus dem Bereich [0...255] in den Bereich [0...1] umgerechnet. Mittels glDrawP ixels() werden dann die von der Stereokamera gewonnenen Tiefenwerte in den Tiefenbuffer von OpenGL geschrieben. Wichtig hierbei
ist das Schreiben in den Colorbuffer zu deaktivieren, um nicht das angezeigte Videobild zu überzeichnen. Damit das normale Farbbild der Stereokamera korrekt
angezeigt wird, ist die oben erwähnte Skalierung auf eine Auflösung von 320x240
Pixeln notwendig. Anschließend werden die Marker in dem Videobild mit den
Funktionen des ARToolkits detektiert. Die Informationen der VRML Objekte
bezüglich der Marker werden im ARToolkit getrennt von den Informationen der
Marker selbst abgelegt:
typedef struct {
int
area;
int
id;
int
dir;
double
cf;
double
pos[2];
double
line[4][3];
double
vertex[4][2];
} ARMarkerInfo;
In der ARM arkerInf o Struktur werden alle notwendigen Informationen, wie
die ID, der Vertrauenswert, die Position des Markerzentrums in idealen Bildschirmkoordinaten, die Eckpunkte des Markers in idealen Bildschirmkoordinaten und die den Marker umgebenden Linien als Werte der Liniengleichung
a · x + b · y + c = 0 in idealen Bildschirmkoordinaten abgespeichert:
typedef struct {
char
name[256];
int
id;
int
visible;
41
3. Implementierung
42
double
marker_coord[4][2];
double
trans[3][4];
double
marker_width;
double
marker_center[2];
} ObjectData_T;
In der ObjectData T Struktur werden hingegen die Informationen der geladenen VRML Objekte bezüglich der Marker angegeben, d.h. der Name und die
Referenz ID des Markers des Objekts, ob der Marker des Objekts sichtbar ist,
die Transformationsmatrix, um das Objekt so in OpenGL zu transformieren,
daß es auf dem Marker gezeichnet wird und die Breite und das Zentrum des
Markers. Werden die Marker getrackt, so wird eine Referenz auf die ID des
Markers gesetzt so dass klar ist, auf welchen Marker sich die Transformationsmatrix trans[3][4] bezieht. Um sicher zu sein, dass der referenzierte Marker auch
im Bild sichtbar ist, sollte man prüfen, ob das Objekt bzw. der Marker überhaupt im aktuellen Bild sichtbar ist, wobei die Information der Sichtbarkeit in
der Variable visible enthalten ist und bei Sichtbarkeit den Wert 1 enthält. Im
nächsten Schritt wird geprüft, ob überhaupt einer der beiden Marker, der der
jeweiligen Kugel zugeordnet wurde, sichtbar ist. Sind beide sichtbar, so wird
sich der Marker gemerkt, der den höheren Vertrauenswert hat, d.h. der am besten getrackt wurde. Dies wird durchgeführt, um immer mit dem am besten
getrackten Marker zu arbeiten, um zu große Abweichungen der Trackingwerte
zu vermeiden. Das folgende Beispiel zeigt das Verfahren, um den Marker mit
dem höchsten Vertrauenswert der reflektierenden Kugel zu bestimmen:
//----------------- Reflektierende KUGEL -----------------// Marker der reflektierenden Kugel detektieren
// die Objektinformationen werden entsprechend den Referenzids
// der Marker eingelesen und es wird sich die Markerid mit
// dem h"ochsten cf gemerkt um die Kugeln richtig auszuschneiden
int patt0,patt1; patt0 = patt1 = -1;
for(int i=0; i < marker_num; i++) {
42
3. Implementierung
43
if(marker_info[i].id == 0){ patt0 = i;}
if(marker_info[i].id == 1){ patt1 = i;}
}
//Reflektierende Kugel, nur die Reflektierende detektieren
//Nur ein einzelner Marker detektiert? ids entsprechend setzen
if (patt1 > -1 \&\& patt0 == -1) {
argConvGlpara(object[1].trans, gl_paraRefl);
id1 = 1;
}
else if (patt0 > -1 && patt1 == -1) {
argConvGlpara(object[0].trans, gl_paraRefl);
id1 = 0;
}
else if (patt1 != -1 && patt0 != -1) {
if ( marker_info[patt0].cf < marker_info[patt1].cf ) {
argConvGlpara(object[1].trans, gl_paraRefl); id1 = 1;
}
else { argConvGlpara(object[0].trans, gl_paraRefl); id1 = 0;}
}
Mittels argConvGlpara(object[i].trans, gl paraRef l) wird schließlich die Transformationsmatrix des am besten getrackten Markers, die die Transformation von
der Kamera zum Marker angibt, in einem 1D Array abgespeichert. Das gleiche
wird auch für die diffuse Kugel durchgeführt und man hat die beiden Transformationsmatrizen, falls die entsprechenden Marker im Bild sichtbar sind, für
beide Kugeln erhalten. Nun gilt es die beiden Kugeln aus dem Videobild auszuschneiden.
43
3. Implementierung
44
Dazu wurde eine kleine Hilfsstruktur definiert, welche 2D Pixelinformationen
speichern kann:
struct pixpos{
double x;
double y;
};
Es wird zuerst die Funktion getM id2Edge() aufgerufen, welche zwei pixpos
Strukturen zurückliefert, in denen die 2D Bildschirmkoordinaten des Kugelmittelpunkts und des Kugelrandes enthalten sind. Anhand dieser Information kann
man sich den Radius der Kugel errechnen, der zusammen mit dem Kugelmittelpunkt an die Funktion getScaledT ext() übergeben wird, welche schließlich
die gewünschte Kugel aus dem Bild ausschneidet und eine auf eine 2er Potenz
skalierte Textur erzeugt. Der folgende Programmausschnitt zeigt das Verfahren
zum Ausschneiden der verspiegelten Kugel:
//------------------// Verspiegelte Kugel
//------------------pixpos mid2edge[2];
getMid2Edge(gl_paraRefl, mid2edge, id1);
pixpos middle = mid2edge[0], edge = mid2edge[1];
// Radius der Kugel bestimmen
int rad = (int)fabs(edge.x - middle.x);
getScaledText(rad, textureRefl, buf, middle);
In der Funktion getM id2Edge() wird zuerst die Matrix für den entsprechenden
Marker geladen. Anschließend werden relativ zu dieser Position Transformationen angegeben, um auf die Stelle zwischen den Markern der realen Szene zu
verweisen, d.h. auf den Mittelpunkt der Kugel im Videobild. Die Transformationen werden entsprechend der ID des betrachteten Markers gesetzt. Sind die
Transformationen gesetzt, erfolgt noch eine Korrektur des Blickwinkels, damit
44
3. Implementierung
45
der Bildausschnitt nicht entsprechend dem Blickwinkel der Orientierung zum
Marker verkürzt wird. Dies ist erforderlich, um die Kugel im Videobild korrekt
auszuschneiden. Danach wird die Pixelposition des Kugelmittelpunktes durch
get2DChoords() berechnet. Dies wird sowohl für den Kugelmittelpunkt als auch
für den Rand der Kugel berechnet. Um den Rand der Kugel zu bestimmen, wird
vor der Berechnung der 2D Bildschirmkoordinaten noch die erforderliche Tranlation gesetzt. Letztlich gibt die Funktion dann die 2D Bildschirmkoordinaten
des Kugelmittelpunktes und des Kugelrandes zurück:
getMid2Edge(double gl_para[16], pixpos midedge[2], int &id){
//Transformationsmatrix fuer den aktuellen Marker laden
//um an die Kugelposition zu verschieben
glLoadMatrixd( gl_para );
if(id==0) {
glTranslatef(140.0,0.0,120.0);
glScalef(3.0,3.0,3.0);
}
else if(id==1) {
glTranslatef(-140.0,0.0,120.0);
glScalef(3.0,3.0,3.0);
}
else if(id==2) {
glTranslatef(140.0,0.0,90.0);
glScalef(3.0,3.0,3.0);
}
else if(id==3) {
glTranslatef(-140.0,0.0,90.0);
glScalef(3.0,3.0,3.0);
}
//Blickwinkelkorrektur um die Textur korrekt auszuschneiden
correctAngle(gl_para[4]);
45
3. Implementierung
46
//Kugelmittelpunkt zum Ausschneiden bestimmen
pixpos middle = get2DCoords();
midedge[0] = middle;
//um den Kugelradius verschieben
glTranslatef(27.3,0.0,0.0);
// 2D coord des Kugelrandpunkts ermitteln
pixpos edge = get2DCoords();
midedge[1] = edge;
}
Die Funktion get2DChoords() bildet einen Teil der OpenGL Renderingpipeline ab, um aus den Werten der aktuellen Modelviewmatrix ,d.h. der Matrix
zur Transformation des Objekts auf den Marker und den anschließenden Transformationen zur Abbildung auf den Kugelmittelpunkt und den Kugelrand, die
2D Bildschirmkoordinaten des Kugelmittelpunktes und Kugelrandes zu ermitteln. Hierzu wird zuerst die aktuelle Projektionsmatrix mit der aktuellen Modelviematrix multipliziert und darauf folgend die perspektivische Division durchgeführt. Dann wird die aktuell durch die Transformationen referenzierte Position und Orientierung der Viewporttransformation übergeben und man erhält
die gewünschten 2D Bildschirmkoordinaten:
static pixpos get2DCoords() {
double gl_proj[16], gl_screen[16], gl_model[16];
glMatrixMode(GL_MODELVIEW);
glGetDoublev(GL_MODELVIEW_MATRIX, gl_model);
glGetDoublev(GL_PROJECTION_MATRIX, gl_proj);
// mult proj * modelview
glLoadMatrixd(gl_proj);
glMultMatrixd(gl_model);
glGetDoublev(GL_MODELVIEW_MATRIX, gl_screen);
// homogenous division
for(int i=0;i<16;i++)
46
3. Implementierung
47
gl_screen[i] = gl_screen[i]/gl_screen[15];
pixpos tpos;
tpos.x = gl_screen[12];
tpos.y = gl_screen[13];
//Viewport Transformation
pixpos middle = viewport(tpos);
glLoadMatrixd(gl_model);
return middle;
}
Mit den beiden auf diese Weise erhaltenen Texturen lassen sich die Objekte
wie bereits in Kapitel 2.7 beschrieben texturieren. Dazu werden die Texturen
initialisiert und in einer Display Liste gespeichert. Das folgende Beispiel zeigt
die Texturierung, die sich dem Beleuchtungsmodell von OpenGL annähert. Die
Funktion weightT ext() gewichtet dabei die jeweilige Textur:
weightText(textureRefl, ambient);
weightText(textureSpec, specular);
weightText(textureDiff, diffuse);
weightText(textImage, emission);
init4Text( textureRefl, textureSpec, textImage, textureDiff);
textures = glGenLists(1);
glNewList(textures, GL_COMPILE);
setUpMultLightOpenGL(textImage, textureDiff,
textureRefl, textureSpec);
glEndList();
Um sich den Overhead zu sparen, der immer entsteht wenn man eine neue Textur
anlegt, werden die Texturen während der Initialisierung der Applikation erstellt.
Im laufenden Programm werden die Texturen dann nur per glT exSubImage2D()
aktualisiert, anstatt sie jedesmal neu anzulegen und später zu löschen.
Nachdem die Texturen ausgeschnitten sind und zur Verfügung stehen, wird der
Schatten berechnet, noch bevor das Objekt gerendert wird. Dazu wird zuerst
47
3. Implementierung
48
die Transfomationsmatrix des Markers geladen, zu dem man das Objekt in Relativität darstellen will.
glLoadMatrixd( gl_paraRefl );
Anschließend erzeugt man sich sein Schattenvolumen,
ShadowVolume volume(polys);
wobei man dem Konstruktor der Klasse ShadowVolumes einen V ector der Struktur P oly übergibt.
struct Poly {
Point p1;
Point p2;
Point p3;
Vektor n1;
Vektor n2;
Vektor n3;
bool facesLight;
Vektor faceNormal;
};
Im Zusammenhang dieses Projekts ist eine Klasse entstanden um VRML Objekte zu laden. In dieser Klasse wird der V ector erzeugt, der alle Polygone des
Objektes mit ihren Normalen pro Vertex und pro Fläche enthält. Diese Polygone werden später zur Berechnung des Schattenvolumens benötigt. Als nächstes
wird der Lichtvektor gesetzt, der die Position der Lichtquelle angibt und es
wird mittels setF acesLight() für jedes Polygon des Objekts errechnet, ob es
der Lichtquelle zu-, oder abgewandt ist. Die von der Lichtquelle abgewandten
Polygone werden bei der Berechnung des Schattenvolumens nicht berücksichtigt.
Vektor light(lx,ly,lz);
volume.setLightPos(light);
48
3. Implementierung
49
void ShadowVolume::setFacesLight(){
for (int i = 0 ; i < polys.size() ; i++) {
Vektor lightVec = lightPos - polys[i].p1.getPosition();
if (lightVec.dot(lightVec, polys[i].faceNormal) > 0){
polys[i].facesLight = true;
}
else {
polys[i].facesLight = false;
}
}
}
Nun kann der Schatten gezeichnet werden:
createShadow(int x, int y, int xend, int yend){
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glDepthMask( GL_FALSE );
glDepthFunc( GL_LEQUAL );
glEnable( GL_STENCIL_TEST );
glDisable( GL_BLEND );
glStencilFunc( GL_ALWAYS, 1, 0xffffffff );newline
//erhoehe, bei dem Betrachter zugewandten Flaechen
glCullFace(GL_BACK);
glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
drawShadowVolume();
// erniedrige, bei dem Betrachter abgewandten Flaechen
glCullFace(GL_FRONT);
glStencilOp( GL_KEEP, GL_KEEP, GL_DECR );
drawShadowVolume();
// Culling ausschalten
glDisable(GL_CULL_FACE);
49
3. Implementierung
50
// Zeichne wieder in den Colorbuffer
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
//Zeichne den Schatten
drawShadow(x,y,xend,yend);
glDepthMask( GL_TRUE );
glDisable( GL_STENCIL_TEST );
}
In der Methode drawShadowV olume() wird das Schattenvolumen gezeichnet:
void ShadowVolume::drawShadowVolume(){
int i,j;
glColor4f(0,0,0,0.2);
for (i = 0 ; i < polys.size() ; i++) {
VrmlBuilder::Poly poly = polys[i];
if (poly.facesLight == true) {
// Dreieck zeigt zur Lichtquelle
//Skalierungsfaktor damit der Vektor
//sich dem Unendlichen annaehert
float scale = 10000;
// Vektor von der Lichtquelle zum Vertex bestimmen
Vektor lightVec1 = poly.p1.getPosition() - lightPos;
Vektor lightVec2 = poly.p2.getPosition() - lightPos;
Vektor lightVec3 = poly.p3.getPosition() - lightPos;
// den Vektor ins Unendliche verlaengern
Vektor v1End = poly.p1.getPosition() + (lightVec1 * scale);
Vektor v2End = poly.p2.getPosition() + (lightVec2 * scale);
Vektor v3End = poly.p3.getPosition() + (lightVec3 * scale);
// Die Polygone des Schattenvolumens zeichnen
//p1,end1,end2,p2
glBegin(GL_QUADS);
glVertex3f(poly.p1.getX(),poly.p1.getY(),poly.p1.getZ());
50
3. Implementierung
51
glVertex3f(v1End.getX(), v1End.getY(), v1End.getZ());
glVertex3f(v2End.getX(), v2End.getY(),v2End.getZ());
glVertex3f(poly.p2.getX(),poly.p2.getY(),poly.p2.getZ());
glEnd();
//p2,end2,end3,p3
glBegin(GL_QUADS);
glVertex3f(poly.p2.getX(),poly.p2.getY(),poly.p2.getZ());
glVertex3f(v2End.getX(), v2End.getY(), v2End.getZ());
glVertex3f(v3End.getX(), v3End.getY(),v3End.getZ());
glVertex3f(poly.p3.getX(),poly.p3.getY(),poly.p3.getZ());
glEnd();
//p3,end3,end1,p1
glBegin(GL_QUADS);
glVertex3f(poly.p3.getX(),poly.p3.getY(),poly.p3.getZ());
glVertex3f(v3End.getX(), v3End.getY(), v3End.getZ());
glVertex3f(v1End.getX(), v1End.getY(),v1End.getZ());
glVertex3f(poly.p1.getX(),poly.p1.getY(),poly.p1.getZ());
glEnd();
}
}
}
Jetzt hat man den Bereich des Schattens im Stencilbuffer ausmaskiert und kann
diese Maske nutzen, um das Videobild zu überblenden und damit den Schatten
zu zeichnen:
void ShadowVolume::drawShadow(int x, int y, int xend, int yend) {
glDisable( GL_LIGHTING );
// Stencil Test zum ausmaskieren aktivieren
glEnable( GL_STENCIL_TEST );
// Tiefentest ausschalten damit die Tiefenwerte
// nicht ueberzeichnet werden
51
3. Implementierung
52
glDisable( GL_DEPTH_TEST );
glColor4f( 0, 0, 0, 0.3);
// Zeichne alles was != 0 ist
glStencilFunc( GL_NOTEQUAL, 0, 0xffffffff );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
// Polygon "uber den gesamten Schirm zeichnen
glBegin(GL_QUADS);
glVertex2i(x, y);
glVertex2i(xend, y);
glVertex2i(xend, yend);
glVertex2i(x,
yend);
glEnd();
glPopMatrix();
glEnable( GL_DEPTH_TEST );
glDisable( GL_STENCIL_TEST );
}
Da wir zu diesem Zeitpunkt bereits die Texturen zur Beleuchtung und den
Schatten des Objekts berechnet haben, können wir das Objekt nun zeichnen.
Dazu wird das Schreiben in den Tiefenbuffer nochmals explizit erlaubt, um die
alten Tiefenwerte durch die des neuen Objekts zu überschreiben, insofern das
Objekt den Tiefentest besteht.
glDepthMask(GL_TRUE);
Nun kann die Display Liste mit den Texturen und dem zu zeichnenden Objekt
geladen werden:
glCallList(textures);
//Display Liste des zu rendernden Objekts
52
4. Ergebnisse
53
glCallList(list[0]);
4
Ergebnisse
In diesem Kapitel werden die Ergebnisse des Verfahrens beschrieben und bzgl.
der Performanz analysiert.
4.1
Bewertung und Performanz
Abschließend lässt sich feststellen, daß der in dieser Arbeit verfolgte Ansatz
vielversprechend ist. Es ging in der Arbeit prinzipiell um die Entwicklung eines Prototyps und um eine Studie darüber, ob der gedachte Ansatz in Echtzeit
zu verwirklichen ist. Diese Anforderungen wurden von der Applikation erfüllt,
wobei darauf hingeweisen werden muß, daß die Applikation ihr volles Potential
noch nicht ausgeschöpft hat, denn es sind noch einige Stellen offen, an denen
optimiert und somit nochmal ein Mehr an Geschwindigkeit herausgeholt werden
kann. Leider war es nicht möglich in der Kürze der Implementierungsphase, alle
diese Optimierungsaspekte zu berücksichtigen. Ein großer Nachteil war die Verwendung der Funktion gluScaleImage(), die am teuersten in der Berechnung
war, vor allem bei der Skalierung von Bildern mit großer Auflösung auf Bilder
mit kleiner Auflösung, z.B. von 1024x768 auf 320x240. In beiden Versionen der
Applikation müssen die Texturen auf 2er Potenzen skaliert werden, in der Version mit der Stereokamera muß jedoch zusätzlich das aufgenommene Bild von
1024x768 auf 320x240 herunterskaliert werden, damit das ARToolkit mit den
Bildern arbeiten kann. Während die Applikation mit normalen Farbbildern der
Stereokamera bei 6-8 fps lief, so lief sie mit der Webcam, die auf die teure Skalierung verzichten konnte, stabil mit 16 fps. Mit einer eigenen Skalierungsfunktion
könnte man dort nochmal einen enormen Geschwindigkeitszuwachs herausholen,
was ein Vergleich mit der Skalierungsfunktion einer speziellen Bibliothek zur
Bildverarbeitung erahnen ließ. Eine weitere Optimierung besteht in der Ausnutzung der menschlichen Wahrnehmungsfähigkeit. Die Ausschnitte der beiden
53
4.1
Bewertung und Performanz
54
Kugeln müssen für einen realistischen Eindruck nicht in jedem Videobild berechnet werden. Im Gegensatz zu rein virtuellen Umgebungen, in denen sich eine
niedrige Framerate durch Bildruckeln usw. ausdrückt, fiel es den Betrachtern in
der Evaluation der Applikation keineswegs auf, daß die Texturen nur alle 4 oder
8 Bilder aktualisiert wurden. Hat man sogar eine Applikation, die auf begrenztem Raum arbeitet, d.h. der Marker auf dem das virtuelle Objekt dargestellt
werden soll, ist nicht sehr weit von den beiden die Lichtsituation des Raumes
festhaltenden Kugeln entfernt, so kann man mit statischen Environment Maps
arbeiten, die zu Beginn der Applikation aufgenommen werden. Hierbei gilt aber,
daß die Beleuchtung um so ungenauer wird, je mehr sich der Betrachter von der
Position entfernt, an der die beiden Environmentmaps der Kugeln aufgenommen wurden. Wird ferner der Arbeitsfluß nicht durch eine Neuaufnahme der
Environmentmaps gestört, so könnte der Benutzer bei einem Positionswechsel
auch wiederholend die Environmentmaps aufnehmen, die dann wieder für diesen
lokalen Kontext Gültigkeit besäßen. Dies hängt allerdings immer mit den von
einer möglichen Anwendung gestellten Anforderungen zusammen, d.h. ob sie
im lokalen Kontext mit statischen Environmentmaps arbeiten kann oder ob sie
dynamische Environmentmaps mit der jeweils für die aktuelle Position gültigen
Map benötigt.
Bezüglich der Stereokamera lässt sich festhalten, daß in dieser Arbeit mit der
verwendeten Kamera und Software die rein optische Verfahren zur Berechnung
der Tiefenwerte der Szene verwenden, keine korrekten flächendeckenden Tiefenwerte für die gesamte Szene ermitteln ließen. Um Tiefenwerte für jeden Pixel
des Bildes zu erhalten, musste die Kamera so parametriert werden, daß sie keine
validierten Tiefenwerte mehr geliefert hat und somit die Tiefenwerte zum groen Teil zu sehr fehlerhaft waren (Vgl. Abb.4). Parametrierte man die Kamera
hingegen so, daß sie nur validierte Tiefenwerte lieferte, so waren in dem Tiefenbild zu viele Bereiche ohne eine Tiefeninformation vorhanden. Leider fehlte
in dieser Arbeit die Zeit, um die validierten Tiefenbilder zu verbessern, oder
mit einem Aufbearbeitungsverfahren die Löcher in den Tiefenbildern zu schließen. Eine Idee, die nicht der Verbesserung der Erfassung der Tiefeninformation,
54
4.1
Bewertung und Performanz
55
sondern lediglich der Korrektur des Ergebnisses dient, wäre möglicherweise ein
Verfahren, daß sich die Beziehung zwischen Kanten-, und Tiefenbild zunutze
macht, denn die Stereokamera ist auch in der Lage, ein Kantenbild des aktuellen Bildes zurückzugeben. Mit dieser zusätzlichen Information wäre es evtl.
möglich, die Löcher in den Bilder zu schließen. Da die optischen Verfahren zur
Ermittlung eines Tiefenbildes meistens dort scheitern, wo sie keine Punktkorrespondenzen zwischen den beiden aufgenommenen Bildern finden können, könnte
man sich die Kanteninformationen zu nutze machen und zwischen den Kanten
die Tiefenwerte z.B. linear interpolieren, denn an den Kanten von Objekten werden meistens Tiefenwerte von den optischen Verfahren gefunden. Ein weiterer
Nachteil der Stereokamera war, da sie nur 4 Tiefenbilder pro Sekunde liefern
konnte, aufgrund der Rechenaufwändigkeit des optischen Verfahrens. Dadurch
war die Applikation bereits auf 4 fps beschränkt und lief am Ende nur noch mit
ca 1,5 fps. Dies stellte leider den Flaschenhals des Verfahrens dar, denn ohne
die Stereokamera und mit Simulation von Tiefenwerten realer Objekte lief die
Applikation stabil mit 16 fps. Eine bessere Alternative wäre der Einsatz eines
physikalischen Verfahrens, wie der Einsatz einer Laser-, oder Infrarotkamera,
um die Tiefenwerte zu bestimmen. Diese Verfahren sind vor allem in der Lage, für jeden Pixel des Bildes eine korrekte Tiefeninformation zu liefern, sofern
die Objekte nicht allzuweit von der Kamera entfernt sind und sich in einem
geschlossenen Raum befinden. Würden diese Kameras dazu noch höhere Frameraten bei der Erzeugung der Tiefenbilder liefern, so wäre die Verschattung
der realen Objekte durch das virtuelle Objekt in Echtzeit berechenbar. Ferner
war die Anpassung der Tiefenwerte der Stereokamera an die Tiefenwerte von
OpenGL ein großes Problem, denn zum einen lieferte die Stereokamera falsche
Tiefenwerte des Referenzpunkts durch Rauschen und durch die Ungenauigkeit
des Verfahrens zur Gewinnung der Tiefenwerte aufgrund der Parametrierung,
und zum anderen lieferte das ARToolkit für den Referenzpunkt nicht immer stabile Werte aufgrund des im ARToolkit verwendeten Trackingverfahrens. Somit
war es recht schwierig die Angleichung der beiden Wertebereiche vorzunehmen,
was den größten Nachteil darstellte. Auch die ungenügende Auflösung der Tie55
4.1
Bewertung und Performanz
56
Abbildung 20: Ergebnis
fenwerte der Stereokamera durch die Beschränkung auf ein Grauwertbild mit
255 Grauwerten verstärkte dieses Problem.
Die Applikation läuft auf einem Mobile Athlon Prozessor 3000+, mit einer ATI
Mobility Radeon 9700 Pro/128 MB Graphikkarte, und 1 GB RAM bei einer
stabilen Framerate von 16 fps, wobei die Environmentmaps nur alle 4 Frames
geändert werden und die 3D Tiefenwerte durch direktes Zeichnen von Objekten
in den Tiefenbuffer simuliert werden. Das zu zeichnende Objekt, daß für den Test
verwendet wurde, besteht aus 12888 Vertices und 4296 Polygonen. Abbildung
20 zeigt das Ergebnis des Tests als Screenshot, wobei sowohl der Boden als auch
die Box in den OpenGL-Tiefenbuffer geschrieben wurden. Hierbei ist nochmals
anzumerken, daß bei der für die Entwicklung der Applikation zur Verfügung
stehenden Zeit kein besonderes Augenmerk auf die Optimierung gelegt wurde. Beispielsweise wurden nicht die Möglichkeiten moderner Graphikhardware
durch Vertex oder Pixelshader genutzt, die nochmals einen Geschwindigkeitszuwachs verbuchen könnten.
56
5. Fazit
5
5.1
57
Fazit
Schlußfolgerungen
Kombiniert man den vorgestellten Ansatz mit Verfahren und Geräten zur Gewinnung der 3D Tiefeninformation, die korrekte, validierte Tiefenwerte für jeden
Pixel des aktuellen Bildes liefern, so sollte man in der Lage sein, virtuelle Objekte entsprechend der aktuellen Beleuchtunssituation in einem Raum durch
Kombination von Environmentmaps korrekt zu beleuchten, und die virtuellen
Objekte die reale Szene verschatten zu lassen. Die Qualität des Ergebnisses lässt
sich dabei noch durch Verwendung einer höheren Auflösung des Bildes und der
Environmentmaps, sowie durch Verwendung eines Schattenverfahrens erzielen,
welches nicht die oben genannten Nachteile aufweist.
5.2
Ausblick
Der verwendete Ansatz ist in vielerlei Hinsicht erweiterbar. Eine mögliche Erweiterung wäre die Berechnung der Position der Lichtquellen, wie sie bereits
von Kanbara und Yokoya in einem Verfahren verwendet wurde28 , das aus einer
statischen Aufnahme einer verspiegelten Kugel die Position der Lichtquellen berechnet, um in OpenGL an den entsprechenden Stellen Lichtquellen zu setzen.
Ferner könnte man auch versuchen die Position der Lichtquellen in Echtzeit dynamisch aus der verspiegelten Kugel zu berechnen und diese in OpenGL setzen,
um weiche Schattierungen zu ermöglichen und den Schatten korrekt zu werfen.
Eine andere Erweiterung bestände darin, High Dynamic Range Kameras zur
Aufnahme der Szene zu verwenden, um vor allem auch grelles Licht, welches
außerhalb des durch den Monitor darstellbaren Bereichs liegt, durch Angleichung der darzustellenden Farbwerte an den darstellbaren Bereich des Monitors
darstellen zu können. Wenn man diesen Ansatz weiterverfolgt, kann man sich
auch die Kamerakurve, über die Pixelwerte und die Belichtungszeit, für die
28 Kanbara,
Yokoya: Geometric and Photometric Registration for Real-time Augmented Rea-
lity, http://csdl2.computer.org/comp/proceedings/ismar/2002/1781/00/17810279.pdf,
[Stand: 20.11.2005]
57
5.2
Ausblick
58
verwendete Kamera bestimmen und die Kamera somit als Lichtmessgerät einsetzen29 . Allerdings sind heutige Graphikkarten noch nicht in der Lage mit 32
bit pro Farbkanal umzugehen, wie sie von High Dynamic Range(HDR) gefordert werden30 . Stattdessen arbeiten modernste Graphikkarten mit 16 bit pro
Farbkanal und können somit echtes HDR lediglich simulieren.
Ein weiterer interessanter Ansatz wäre das vorgestellte Verfahren mit einer
Fischaugenkamera durchzuführen, so daß es überflüssig wäre, bei dynamischen
Umgebungsmaps ständig die beiden Kugel aufnehmen zu müssen. Man könnte
stattdessen einfach das anzuzeigende Bild aus dem Fischaugenbild zurückrechnen und die reflektierende als auch die diffuse Map aus dem Fischaugenbild
gewinnen. Die vorgestellte Technik kann in vielen Anwendungsfeldern eingesetzt werden. Vor allem im Bereich des Films und der Beleuchtungstechnik, wie
z.B. der Innenausstattung würden sich gute Einsatzmöglichkeiten finden, wenn
der Kunde in Echtzeit durch seinen Rohbau laufen und seine bereits möblierte,
korrekt beleuchtete Wohnung betrachten könnte.
29 Debevec:
Paul Debevec Home Page, www.debevec.org, [Stand:03.01.2006]
High Dynamic Range Rendering,
30 Wikipedia:
http://de.wikipedia.org/wiki/High Dynamic Range Rendering, [Stand: 02.01.2006]
58
LITERATUR
59
Literatur
[1] Möller, Tomas Akenine; Haines, Eric: Real-Time Rendering, 2nd edition,
A K Peters, Ltd., Natick, 2002
[2] Shreiner, Dave; Woo, Mason; Neider, Jackie; Davis, Tom: OpenGL Programming Guide, 4th edition, Addison-Wesley, Boston, 2004
[3] Watt, Alan: 3D-Computergraphik, 3.Auflage, Pearson Studium, München,
2002
[4] Billinghurst, Mark: ARToolkit,
http://www.hitl.washington.edu/artoolkit/, [Stand: 22.12.2005]
[5] Müller,
Stefan:
Licht
und
Materialien,
http://geri.uni-
koblenz.de/ws0203/cg2folien/9 lichtmat 6.pdf, [Stand: 04.01.2006]
[6] Müller, Stefan: Photorealistische Computergraphik, http://www.unikoblenz.de/FB4/Institutes/ICV/AGMueller/Teaching/SS05/PCG,
[Stand: 04.01.2006]
[7] Schmalstieg, Dieter: Studierstube, http://studierstube.org/, [Stand:
02.01.2006]
[8] Blythe, David: Generating a Sphere Map for Specular Reflection,
http://www.opengl.org/resources/tutorials/sig99/advanced99/
notes/node179.html, [Stand: 16.12.2005]
[9] Ramamoorthi,
cient
Ravi;
Representation
Hanrahan,
for
Irradiance
Pat:
An
Effi-
Environment
Maps,
http://graphics.stanford.edu/papers/envmap/, [Stand: 10.12.2005]
[10] Kanbara, Masayuki; Yokoya, Naokazu: Geometric and Photometric Registration for Real-time Augmented Reality,
http://csdl2.computer.org/comp/proceedings/ismar/
2002/1781/00/17810279.pdf, [Stand: 20.11.2005]
59
ABBILDUNGSVERZEICHNIS
[11] Debevec,
Paul:
Paul
60
Debevec
Home
Page,
www.debevec.org,
[Stand:03.01.2006]
[12] Wikipedia:
High
Dynamic
Range
http://de.wikipedia.org/wiki/High Dynamic Range Rendering,
Rendering,
[Stand:
02.01.2006]
Abbildungsverzeichnis
1
Marker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
2
Head Mounted Display, Vgl. Billinghurst: ARToolkit . . . . . . .
5
3
Diagramm ARToolkit, Vgl. Billinghurst: ARToolkit . . . . . . . .
6
4
Szene mit Tiefenbild . . . . . . . . . . . . . . . . . . . . . . . . .
15
5
Prinzip der Umgebungsmap . . . . . . . . . . . . . . . . . . . . .
17
6
Kugel Koordinatenverlauf, Vgl. Möller/Haines, 2002:155 . . . . .
18
7
Schaubild Umgebungsmap, Vgl. Möller/Haines, 2002:160 . . . . .
21
8
Multitexturing, Vgl. Shreiner [et al.], 2002:432
. . . . . . . . . .
23
9
Beleuchtung, Vgl.Müller: Licht und Materialien . . . . . . . . . .
27
10
Aufbau
28
11
Diffuse und reflektierende Kugel
. . . . . . . . . . . . . . . . . .
29
12
Texturierungsverfahren . . . . . . . . . . . . . . . . . . . . . . . .
29
13
Beleuchtungstexturen . . . . . . . . . . . . . . . . . . . . . . . .
30
14
Konkrete Beleuchtungen . . . . . . . . . . . . . . . . . . . . . . .
32
15
Prinzip des Schattenvolumen . . . . . . . . . . . . . . . . . . . .
34
16
Berechnung des Schattenvolumen . . . . . . . . . . . . . . . . . .
35
17
Problem mit dem Schattenvolumen . . . . . . . . . . . . . . . . .
36
18
Lösung des Problems mit dem Schattenvolumen . . . . . . . . . .
37
19
Übersicht über das Verfahren . . . . . . . . . . . . . . . . . . . .
38
20
Ergebnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60

Documentos relacionados