Douba/Raytracer

Stand vom 07.07.2013


Douba.de

Universität

Reisen

Projekte

Hobbies

Freunde

Links

Valid HTML 4.01 Strict CSS ist valide!

Projektion einer Kugel

In einem Mathematik-Kompendium meiner Mutter sah ich einmal eine Abbildung, in der illustriert wurde, wie das dreidimensionale Gittermodell einer Kirche auf drei zueinander orthogonale Ebenen projiziert wurde. Dort wurde auch beschrieben, daß man aus den drei Projektionen das 3D-Modell rekonstruieren könne. Ich versuchte mir ein Netz vorzustellen, bei dem das nicht funktioniert, und fand schnell mehrere. Insbesondere war darunter eine Kugel, deren Projektion auf eine beliebige Ebene stets ein Kreis ist.

Seitdem habe ich oft versucht, mir das Gebilde vorzustellen, das man erhält, wenn man die "Rückprojektion" der drei Kreise in den Raum durchführt. Ich suchte also die Schnittmenge dreier identischer massiver Zylinder, deren Achsen zueinander senkrecht stehen, deren Durchmesser kleiner als ihre Länge ist und deren Mittelpunkte sich decken.

Der Schnitt aus zweien solcher Zylinder ist im Kopf noch relativ einfach zu vollziehen, wenn man sich vorstellt, mit einer hinreichend tiefen Lochsäge einen Holzklotz zu bearbeiten. Beim dritten Schnitt mußte ich mir mit einem Trick behelfen: Zunächst stellte ich mir vor, eine zu große Lochsäge zu verwenden, die gerade eben die "Ecken" des Quadrates kappt, das man erhält, wenn man die nach zwei Schnitten entstandene Figur auf die dritte Ebene projiziert. An diesen Ecken entstehen so vier neue Flächen, die sich durch Schrumpfen des "Sägedurchmessers" schließlich berühren und so die zuvor bestehenden vier Flächen in je zwei neue trennen. So hat die Figur letztlich zwölf Flächen (vier nach dem zweiten Schnitt, die durch vier neue in je zwei geteilt werden).

Später, als ich POV-Ray hatte, kam ich auf die Idee, diese Figur vom Computer bildlich darstellen zu lassen. Dank der CSG-Operationen in POV-Ray ging dies sehr schnell. Am 3. Oktober 2009 kam mir auf der Brockenwanderung beim Gespräch mit Tobias die Idee, das Ganze zu animieren, und da ich mich vor einigen Tagen mit Anaglyphen beschäftigt hatte, wollte ich am besten auch gleich ein Video, das mit der Schieltechnik dreidimensional zu sehen ist.

Das Ergebnis und der Quellcode sind hier verfügbar.
Figur für rechtes Auge
Figur für linkes Auge

Raytracer

Zum Jahreswechsel 2008/2009 besechäftigte mich einmal wieder das Thema Raytracing. Schon mit meinem C64 versuchte ich begeistert, echte 3D-Bilder rechnerisch zu erstellen, damals jedoch mit nur mäßigem Erfolg. Als ich mich 1996 das erste mal mit dem Raytracer POV-Ray (Zur Homepage geht's unter http://www.povray.org/) beschäftigte, fing ich an, viele geometrische Zusammenhänge zu verstehen. Dies ist vor allem auf die gute Online-Hilfe zurückzuführen.

Raytracing ist ein Verfahren zur Abbildung von in Form einer Beschreibung gegebenen, dreidimensionalen Szenen auf ein zweidimensionales Matrixbild. Dabei werden vom Blickpunkt eines hypothetischen Beobachters aus virtuelle Sehstrahlen durch jeden der Bildpunkte des ebenfalls in der 3D-Szene repräsentierten Bildes "geschossen", um dann zu berechnen, wie diese Sehstrahlen verlaufen, wo sie auftreffen und welche Konsequenzen dies für die Farbe des Bildpunktes hat, durch den der Strahl geschossen wurde. Beispielsweise wird ein Sehstrahl, der in der folgenden Kugelszene in der Mitte und halb links gelegen ist, in der 3D-Szene zuerst auf die kleine rote Kugel treffen. Der Strahl wird wie ein Lichtstrahl zum Teil gefärbt und zum Teil reflektiert. Hinzukommen können noch Anteile aus Glanzlichtern, die auf der Kugeloberfläche entstehen. So werden Strahl fü Strahl, Bildpunkt um Bildpunkt, auf Grund geometrischen Berechnungen aufgebaut, und heraus kommt ein sichtbares Abbild der zuvor nur durch abstrakte Beschreibung gegebenen 3D-Szene.

POV-Ray nimmt als Eingabe Textdateien entgegen, die in einer speziellen scene definition language (SDL) geschrieben sind. In dieser Sprache, die von der Struktur mit HTML zu vergleichen ist, jedoch in der Syntax eher C ähnelt, werden Objekte (Kugel, Fläche, Licht, Kamera...) in der zu definierenden Szene durch Textabschnitte beschrieben, die auch deren Eigenschaften (Ort, Oberfläche etc.) festlegen.

Diese Sprache nun ist so mächtig, daß es möglich ist, in ihr einen Raytracer zu programmieren, also einen Raytracer im Raytracer. Zwar ist offensichtlich, daß man diesen nicht benötigt, da man ja schon POV-Ray hat, jedoch ist dies eine eindrucksvolle Demonstration der Universalität der SDL. Der Quelltext zu diesem Raytracer ist Teil der Hilfe von POV-Ray. Die Arbeitsweise besteht darin, im übergeordneten Raytracer eine orthographische Kamera einer Fläche gegenüberzusetzen, und dann diese Fläche mit Hilfe von Berechnungen zu bemalen. Der Betrachter sitzt also vergleichsweise vor einem statischen Fernseher und fotografiert diesen, Hierbei wählt er den Ausschnitt so, daß schließlich dasselbe Bild wieder herauskommt. Das Entscheidende dabei ist, daß die Farbe der Bildpunkte auf dem "Fernseher" durch Berechnungen zustandekommen, die nicht auf die Raytracer-Funktionen der SDL zurückgreifen, sondern diese Mechanismen ihrerseits nachbilden.

Das Ergebnis der POV-Ray-Berechnung sieht dann so aus: Fünf Kugeln verschiedener Farbe sind hinter- und übereinander vor einem schwarzen Hintergrund angeordnet und werden von drei verschiedenfarbigen Lichtquellen beleuchtet, die unterschiedliche Glanzlichter und Schatten auf den Kugeln hervorrufen.

Kugeln vom SDL-Raytracer berechnet

Mein eigener Raytracer

In der Hilfe zu POV-Ray wird jeder Aspekt des SDL-Raytracers genau durchleuchtet. Genau genug, um mich zu versuchen, das Ganze auf C++ zu übertragen. C++ hatte ich 2008 an der Universität unterrichtet, obwohl ich vorher selbst noch keine Erfahrungen sammeln konnte. Dank hochkonzentrierter Literatur, die ich nur weiterempfehlen kann, gelang es mir damals, alle wesentlichen Aspekte der objektorientierten Programmierung zu verstehen und weiterzuvermitteln. Daher fühlte ich mich gewappnet für ein solches Projekt.

Die Schwierigkeiten bei der Umsetzung des Raytracers bestanden weniger darin, den gegebenen Code eins zu eins zu übersetzen, sondern eher in der Definition eigener Klassen, die geometrische Strukturen möglichst gut wiedergeben können. Besondere Mühe gab ich mir mit der Vektorklasse, die auch viele Operatoren zur Verfügung stellt. Ich machte intensiven Gebrauch von den schon oben angeführten RRZN-Handbüchern zu den Themen C und C++. Das Gelernte ließ sich in der Tat in die Tat umsetzen, und ich lernte die Sprache C++ und ihre Feinheiten zu schätzen.

Als der Raytracer fertig war, war ich unzufrieden mit der geringen Bildgröße. Dies ließ sich zwar unschwer ändern, jedoch packte mich der Ehrgeiz, und ich wollte alle Treppenstufeneffekte, also Aliasing, beseitigen. Ich versuchte mich also an verschiedenen Supersampling-Methoden – zunächst dem konstanten Multisampling, und als das funktionierte, dem adaptiven Multisampling. Schließlich konnte ich das Bild in voller Qualität berechnen.

Das Ergebnis kann man hier herunterladen (460KB).

Der Quellcode ist hier zusammen mit dem Microsoft-Visual-C++-Projekt verfügbar.

Besondere Aspekte der Programmierung, bei denen ich viel gelernt habe, sind:

—Ingo Schalk-Schupp — alle Rechte vorbehalten