[III] 3D-Grundlagen
05.07.05

Die Berechnung von 3D-Grafik ist wahrscheinlich das Spektakulärste, was ein PC heute vollbringen kann. Computer-generierte Bilder haben immer etwas Mysteriöses und Faszinierendes an sich und wenn noch dazukommt, dass sie z.B. in Spielen in Echtzeit gerendert werden und man so auf bewegte Bilder blickt, dann verstärkt sich dieses Gefühl noch ungemein. Fakt ist, dass 3D-Grafik erst da ihre große Popularität erlangen konnte, nachdem Computerhardware immer leistungsstärker wurden (insbesondere Grafikkarten) auch für den Otto-Normal-Verbraucher halbwegs erschwinglich wurde.

Die rasante Entwicklung der Hardware im Hinblick auf die Geschwindigkeit ist schon beinahe beängstigend: ständig werden neue Features eingeführt und an der Performance-Schraube gedreht, sodass man sich dauernd durch PC-Magazine o.ä. auf dem Laufenden halten muss, um den Überblick über den aktuellen Stand der Dinge nicht komplett zu verlieren. Die Steigerung der Rechenleistung von Grafikkarten korrespondiert im Übrigen mit dem Bestreben vieler Entwickler dem Benutzer immer realistischere Welten auf dem Monitor zu präsentieren.


Auf diesen Seiten sollen zunächst einige grundlegende Begriffe von 3D geklärt werden, bevor es dann in den nächsten Kapiteln um die konkrete Programmierung geht.


  1. Die 3D-Welt
  2. Ein 3-Dimensionaler Raum besitzt eine Breite X, ein Höhe Y und eine Tiefe Z. Unsere 3D-Welt entsteht dadurch, dass wir Objekte in diesem Raum, der durch ein Kartesisches Koordinatensystem beschrieben wird, verteilen. Zunächst ist sie als Abbild im Speicher durch unzählige XYZ-Koordinaten und andere Daten dargestellt. Der anspruchsvollere Teil ist aber ihre Projektion auf den 2D-Bildschrim, der ja nur die Breite X und die Höhe Y besitzt, also die sinnvolle Umwandlung der Tiefeninformationen. Daneben sollten z.B. verdeckte Objekte vom Rendering ausgeschlossen werden, um Rechenzeit zu sparen. Die Mathematik hinter diesen ganzen anfallenden Berechnungen kann extrem kompliziert werden. Doch muss man glücklicherweise kein Mathematikstudium abgeschlossen haben, um mit Direct3D programmieren zu können. Die meiste Arbeit nimmt uns DX ab. Trotzdem kommt der Programmierer nicht drum herum komplizierte Algorithmen zu implementieren, wenn er eine realistische Welt darstellen will, die aber auch auf HomePC’s flüssig darstellbar sein soll. Man sollte noch wissen, dass einheitslose Längenangaben zur Beschreibung der Objektsgrößen verwendet werden. Metrische Längeneinheiten (m, cm, usw.) sind möglich, aber zumindest im Bereich der Spielprogrammierung unüblich.


  3. Geometrie
  4. Die einfachste geometrische Form, die in Direct3D Verwendung findet, ist der Punkt, Vertex in der Fachsprache genannt. Im einfachsten Fall beschreibt ein Vertex einfach eine Position im Raum. Durch ihn werden jedoch auch Informationen für Texturen, Farben und viele andere Sachen dargestellt, was ihm eine immense Bedeutung verleiht.

    Werden 2 Vertices zusammengefasst, so erhält man eine Linie, bei 3 die Beschreibung eines Dreiecks, das sich im Raum befindet (= Polygon). Mehr als diese 3 Primitive gibt es nicht, denn alle anderen komplexeren geometrischen Formen, wie zum Beispiel ein Quader, können und werden einzig und alleine auf zusammenhängende Polygone zurückgeführt. Auch solch komplizierte Modelle, wie z.B. das eines Menschen, können durch lauter kleine Dreiecke beschrieben werden. Dabei wirkt das Endergebnis umso plastischer und echter, je mehr Polygone man dafür „verbaut“. Selbstredend braucht die Grafikkarte für die Berechnung dann auch immer mehr Zeit. Die Kantigkeit kann aber nicht nur durch eine Erhöhung der Polygonanzahl minimiert werden, sondern auch durch geschickten und forcierten Einsatz von diversen fortgeschrittenen Techniken (z.B. durch Bump Mapping, nur um eines genannt zu haben).


  5. Transformationen
  6. Transformationen sind ein ziemlich wichtiges Kapitel in Direct3D. Mit ihnen kann man die kreierte 3D-Welt manipulieren und ihr Erscheinungsbild auf dem Bildschirm verändern. Das Ganze wird mit Hilfe von 4x4-Matrizen bewerkstelligt. Es gibt 3 Arten von Transformationen:


    • Welt-Transformation
    • Wenn wir z.B. 4, absolut identische, Würfel rendern wollen, die sich jeweils in den Ecken des Bildausschnitts befinden sollen, dann haben wir dafür 2 Möglichkeiten: Entweder man kreiert alle 4 Würfel „per Hand“, indem man ihnen individuelle Koordinaten für ihre Vertices (insgesamt 32 an der Zahl) vergibt, oder man benutzt die Welt-Transformation. Mit deren Hilfe brauchen wir selber nur einen Würfel zu erstellen, die restlichen 3 werden einfach von Direct3D für uns von diesem Ursprungswürfel kopiert und an die angegebenen Positionen verschoben. Dieser zweite Weg ist weit weniger arbeitsaufwändig und zudem auch noch ressourcenschonender, da weniger Arbeitsspeicher gebraucht wird, und sollte deshalb immer eingeschlagen werden.

      Dieses Verfahren nennt man Translation. Und es ist bei weitem nicht das Einzigste, was man mit der Welt-Transformation anstellen kann. Ebenso können nämlich Objekte einer Rotation oder Skalierung unterzogen werden. Und damit ist die Liste noch lang nicht abgeschlossen.


    • Kamera-Transformation
    • Die Kamera-Transformation bestimmt, welchen Ausschnitt wir von der Welt sehen werden. Mit Hilfe der Matrix entscheiden wir also, wo die virtuelle Kamera positioniert werden soll, um die Bilder einzufangen.


    • Projektions-Transformation
    • Die Projektions-Transformation führt das angesprochene Umwandeln der Tiefeninformationen durch – sie ist also letztendlich dafür verantwortlich, dass am Bildschirm die übersetzte 3D-Welt korrekt angezeigt wird. Sie bestimmt auch wie die Kamera das sieht, worauf sie zeigt. Diesen Vorgang kann man mit der Wahl des optischen Apparates bei einer reellen Kamera vergleichen. Durch Veränderung der Matrixwerte kann man das Größenverhältnis der gerenderten Bilder oder die Blickweite/den Blickwinkel ändern, um beim Letzteren z.B. ein Panoramabild zu erhalten.


    Es ist im Übrigen von großer Bedeutung in welcher Reihenfolge man die einzelnen Transformationen tätigt.


  7. Texturen
  8. Bis hierhin würde unsere Welt nur aus farbigen Dreiecksflächen bestehen. Um ihr „Leben“ einzuhauchen bedarf es einer ausgiebigen Texturierung.

    Texturen sind zunächst nichts anders als einfache Bilder, die auf der Festplatte liegen. Bei größeren Projekten, die auf große Mengen von Texturen angewiesen sind, sollten diese am besten in ein möglichst verlustfreies Format wie tga komprimiert werden. Aktuelle Spiele können nämlich schon mal bei der Installation über ein Gigabyte an gepackten Texturen auf die Festplatte kopieren; wären es unkomprimierte Bitmaps, so würden sie noch ein Vielfaches mehr an Platz beanspruchen - und nicht jeder hat in seinem Computer einen Terrabyte an Festplattenkapazität.

    Startet eine DX-Anwendung, so werden die 2-dimensionalen Bilder früher oder später zunächst in ein DX-kompatibles Format umgewandelt und anschließend in den Grafikkartenspeicher und den Arbeitsspeicher geladen, damit ein schneller Zugriff erfolgen kann. Reichen diese Speicher nicht aus, so erfolgt eine Auslagerung der Daten auf die Festplatte, was sich durch Ruckler bei der Darstellung negativ bemerkbar macht.

    Beim darauffolgenden Rendering werden die präformatierten Bilder dann auf unsere Dreiecksoberflächen „geklebt“ (Textur Mapping). Darin sind aktuelle Grafikkarten erstaunlich schnell.


    Eine wichtige Eigenschaft von Texturen ist, dass sie praktisch eine unendliche Ausdehnung haben können. Man muss sich das so vorstellen, dass die Textur immer wieder in X- und Y-Richtung erweitert werden kann, indem das Ursprungsbild wiederholt an den vorhandenen „Teppich“ gelegt wird. So könnte ein Texturausschnitt aussehen (Ursprungsbild rot umrandet):


    Man kann mit den Texturen einige Operationen durchführen, um ihr Erscheinungsbild an die Geometrie anpassen zu können. Neben der Skalierung, also Streckung, der Textur, kann man ihre Position auf der Fläche, auf der sie draufliegt, bestimmen. Dazu wird ein zweidimensionales Koordinatensystem verwendet. Die Achsen in diesem System werden mit den Buchstaben u und v bezeichnet. Der Ursprung/Nullpunkt (0,0) dieses Koordinatensystems liegt in der linken oberen Ecke. Die rechte untere Ecke der Textur hat die Koordinaten (1,1).

    So könnte man eine Textur auf ein Quadrat mappen:


    Wie bereits erwähnt, werden die Texturkoordinaten als Vertices gespeichert.


    Da man immer größere Texturen verwendet, um die 3D-Welt detailreicher darzustellen, wächst auch der Speicherbedarf kontinuierlich. Es ist deshalb nicht verwunderlich, dass die allerneusten Spiele bei höchster Detailstufe mittlerweile erst bei 1 Gigabyte Arbeitsspeicher und 256MB Grafikkartenspeicher flüssig laufen.


    Bei vielen großen Produktionen ist es mittlerweile Brauch die Texturen nicht von Grund auf mit einer Software selber zu malen. Stattdessen werden zunächst hochauflösende Bilder von Motiven aus der Natur geschossen und diese dann digital nachbearbeitet. Im Endeffekt erhält dadurch man deutlich realistischere Texturen.


  9. Meshes und Modelle
  10. Mit den Grundbausteinen, die uns DX anbietet, kann man wunderbar einfache Objekte, wie Räume, Treppen und Ähnliches, kreieren. Hat aber ein Objekt zu viele Polygone bzw. eine zu komplizierte Polygonstruktur, dann muss man auf eine andere Technik ausweichen. Das Objekt wird in diesem Fall in einem 3D-Modellier-Programm (3D Max oder Maya z.B.) erstellt und als Datei abgespeichert, die man dann später per DirectX-Befehl in sein Programm importieren kann.

    Das reine Polygonnetz eines Objekts wird dabei als Mesh bezeichnet. Kommen zusätzlich Texturen hinzu, so spricht man von einem Model.