Zuletzt aktualisiert: 09.04.2023
Aquaristik
Modellbau
Software
3D-Druck
Garten
Radreisen
Kontakt
Impressum

Beschleunigung von 3D - Grafik (speziell OpenGL)

Man ist relativ stark erstaunt, wieviele Dreiecke heutige Grafikkarten über Software wie zB OpenGL, Grafiktreiber und Bildschirmspeicher bis auf den Bildschirm schleudern können. Macht man sich jedoch selbst daran, kommt man schnell auf den Geschmack, große 3D - Modelle mit mehreren tausend Dreiecken zu produzieren. Das einfache Programm, dass die errechneten Daten hernimmt und direkt durch die Grafikschnittstelle auf den Bildschirm zaubert, muss um eine weitere Schicht erweitert werden, und zwar um diejenige, die im Voraus in noch kürzerer Zeit jene Dreiecke aussortiert, die bei der Darstellung eigentlich entfallen könnten. Das Problem dabei ist, dass diese Entscheidung in einer noch kürzeren Zeit getroffen werden muss, als die Darstellung selbst an Zeit in Anspruch nimmt.

Um das gewährleisten zu können, müssen Hierarchien geschaffen werden, die dazu dienen, eine Entscheidung für mehrere gleichzeitig fällen zu können, da mehrere Objekte in einer Schicht liegen, aber für die darüberliegende wichtigere Schicht schon die Entscheidung getroffen wurde, sie nicht anzeigen zu müssen.

Folgende zum Teil auch einfach umzusetzende Optimierungen können jede 3D - Engine zu wesentlich höherer Leistung verhelfen:

  • Trigonometrische Tabellen: Die einfachste Optimierungsart ist das gezielte Vorberechnen und Ablegen von trigonometrischen Berechnungen. Geht man in seinem Programm davon aus, immer nur sin((int)winkel) berechnen zu müssen, so kann man sich eine Funktion schreiben, die auf ein vorher berechnetes Array zugreift, bei dem an der Position winkel der dazugehörige sin(winkel) steht.

    #ifndef MathH
    #define MathH
    
    #include 
    #include 
    #include 
    
    #define PI 3.14159265
    
    class Math {
    	private:
    		GLfloat sintable[360];
    		GLfloat costable[360];
    	public:
    		GLfloat mcos(int angle);
    		GLfloat msin(int angle);
    		Math();
    };
    
    GLfloat Math::mcos(int angle) {
    	return this->costable[(angle % 360 + 360) % 360];
    }
    
    GLfloat Math::msin(int angle) {
    	return this->sintable[(angle % 360 + 360) % 360];
    }
    
    Math::Math() {
    	printf("\nCreated sin/cos - tables.");
    
    	for(int i = 0; i < 360; i++) {
    		(this->sintable[i]) = sin((float)(i)*PI/180.0f);
    		(this->costable[i]) = cos((float)(i)*PI/180.0f);
    	}
    }
    
    #endif
    
  • Einschränken der Sichtweite: Viele Dreiecke lassen sich bereits dadurch ausblenden, indem man vorher abfragt, wie weit entfernt eine Ecke vom Standpunkt ist. Geht man davon aus, dass man hier grob eine Ecke als ausreichend annehmen kann, kann man diese Entscheidung anhand einer einzigen Vektorsubtraktion und einer Längenbrechnung treffen. Diese Berechnung macht jedoch nur im Falle von Dreiecksgruppen sind, nicht unbedingt für jedes einzelne Dreieck. Zwar hat OpenGL schon eine Viewport - Weitenbeschränkung, das jedoch selbst vorzubereiten ist schneller.
  • Quadtree / Octree: Das ähnliche vorangehende und mittlerweile veraltete Binary Space Partitioning (BSP) bildet die Basisidee von Octrees und Quadtrees. Dabei wird beim Quadtree eine quadratische Grundfläche der Szene baumartig in weitere 4 kleinere Quadrate unterteilt, äquivalent dazu wird ein Würfel in 8 kleinere Würfel zerteilt. Jeder Baumknoten enthält dabei alle Koordinaten, die dafür nötig sind, zu entscheiden, ob ein Punkt x in den Sichtbarkeitsbereich dieses Baumknotens fällt. Ebenfalls eine Liste aller Objekte, die in diesen Szenenunterbereich fallen, und eine Liste aller Zeiger auf die 4 bzw. 8 Kindbereiche. Ein Objekt wird nun bei der Erzeugung in diesen Baum einsortiert, wobei die Höhe des Baumes davon abhängt, wieviele Objekte ein Kindknoten maximal enthalten darf. Ein Objekt sortiert sich dann in den kleinstmöglichen Knoten ein. Beim Darstellen der Szene wird nun von der Wurzel des Baumes hinab nachgefragt, ob der jeweilige Kindknoten überhaupt sichtbar ist, wenn nicht, kann der komplette Teilbaum unterhalb dieses Knotens entfallen.









  • Viewport einschränken: Etwas aufwendiger, aber nur eine Erweiterung des Einschränkens der Sichtweite, ist natürlich auch seitlich und im "Rücken" befindliche Dreiecke auszuschließen.
  • Backface - Culling: OpenGL sieht hierfür schon eine Funktion vor, diese ist aber meist deaktiviert. Diese Entscheidung selbst vor dem Senden der Daten an OpenGL zu treffen kann jedoch mehr Performance bringen. Für diese Berechnung wird das Kreuzprodukt zweier Vektoren benötigt.
  • Mipmapping: Für diese Art der Beschleunigung wird speziell das Verwenden von Texturen beschleunigt, indem ein Bild, dass als Textur verwendet wird, in mehreren LODs vorliegt, sogenannten "levels of detail". Ein Bild wird also vorbereitet, indem es in der Größe immer halbiert wird, und somit die Skalierung des Bildes vorberechnet wird. Ist ein Objekt mit einer Textur also ganz nah am Betrachter, so wird die am höchsten aufgelöste Variante benutzt, in weiter Ferne das vorher berechnete sehr viel kleinere Abbild des Originals.
  • Billboards: Bei einer 3D - Szene sollte man sich immer vor Augen halten, wie gross ein nahes hoch aufgelöstes Objekt aussieht, und wieviele Details man vom selben Objekt sehen möchte, wenn es weit entfernt ist. Zu diesem Zweck hat man früher erfolgreich sogenannte Billboards eingeführt. Das sind meistens 1 bis 3 gekreuzte Grafikprimitive, die mit einer teilweise transparenten und detailierten Textur belegt sind. Mit diesem Konstrukt werden beispielsweise weit entfernte Bäume dargestellt, wobei man sich das Zusammensetzen des Baumes aus Einzeldreiecken inklusive Textur spart. Dies macht jedoch nur bei weit entfernten Objekten Sinn. Ein Billboard hat jedoch eine weitere Eigenschaft, nämlich, dass es sich immer relativ zur Kamera mitdreht, man sieht also immer diesselbe Seite des Billboards und hat somit beim Vorbeigehen einen erstaunlich einfachen 3D - Effekt und einen massiven Spareffekt.
  • Bounding Box: Eine Bounding - Box ist kurz gesagt eine Box, in dem sich der Betrachter und die Szene befindet. Diese Box ist mit Texturen so versehen, dass der Betrachter den Eindruck erhält, am Horizont sei die Szene nicht zuende und beschränkt. Somit muss die Szene nicht mit Wolken oder bis zum Horizont mit 3D - Modellen gestaltet werden, sondern geht von 3D - Objekten in der Szene in eine Textur der Bounding - Box über.
Copyright © 2023 Evolutec Alle Rechte vorbehalten.