Billboard
(Mehr Informationen/weitere Artikel) {{{1}}} |
Ein Billboard zu rendern ist eine Methode eine 2D Grafik in eine 3D Szene einzufügen. Wenn man eine einfache 2D Grafik hat, so möchte man diese meistens nicht irgendwo als 2 Dimensionale Plakatwand in eine 3D Szene pflanzen. Stattdessen möchte man, das diese 2D Grafik ähnlich wie ein Sprite in 2D immer zum Betrachter schaut, jedoch dieses Sprite in eine 3D Szene mit Tiefe, Tiefentest, 3D-Position, eventuell Beleuchtung und dergleichen gezeichnet wird.
Inhaltsverzeichnis
Allgemeine Probleme
Jede Billboard-Art hat eine Gemeinsamkeit: alle zielen darauf ab die Rotation (oder Teile der Rotation) der Szene rückgängig zu machen um das Rechteck komfortabel (wie in 2D) zeichnen zu können. Jedoch soll soll im Gegensatz zur Ausrichtung des Rechtecks die Position in der 3D-Szene sehr wohl von der Rotation der Szene abhängig sein. Um beides zu erreichen, können unterschiedliche Techniken mit Vor- und natürlich auch Nachteilen verwendet werden. Diese sollen hier vorgestellt werden.
Spherische Billboards
Bei spherischen Billboards geht es darum, eine Rechteck (meist ein Quadrat) immer zum Betrachter auszurichten, egal ob er von oben, unten, vorne oder von wo auch immer auf dieses Rechteck blickt. Die Haupt-Anwendungsgebiete sind:
- Partikelsysteme
- Illusion von Objekten mit der Form einer Kugel (Himmelskörper, Billiardkugeln, ...)
- Können bei der Baumdarstellung für die Blätterbüschel verwendet werden
Mittels Matrix manipulation
Die Matrix manipulation ist die einfacheste Form, jedoch für große Mengen von Billboards eher ungeeignet, da es mehr Aufwand bedeutet. Es gibt jedoch einen Spezialfall, bei dem diese Methode um einiges schneller sein kann als alle anderen Methoden. Man nehme an bei dem Billboard handelt es sich nicht um ein einfaches Rechteck sondern (aus welchen Gründen auch immer) um ein recht komplexes Objekt mit 100erten Punken welches man immer zum Betrachter ausrichten möchte. Bei allen anderen Methoden ist eine Software-Transformation der Punkte in der ein oder anderen Form notwendig. Bei dieser Methode hingegen können die statischen Vertexdaten 1:1 an OpenGL geschickt werden. Aber nun zur Theorie:
Betrachten wir vorest die Matrix etwas genauer:
r | r | r | p |
r | r | r | p |
r | r | r | p |
0 | 0 | 0 | 1 |
- r ... Rotationsmatrix
- p ... Position
Wenn die Rotationsmatrix der Itentitäts-Matrix entspricht, so können wir das Rechteck wie in 2D behandeln. Bleibt noch die Frage der Position. Wenn die Modelview Matrix dem lokalen Koordinatensystem des Billboards entspricht (sodass die Billboardposition (0|0|0) ist), so spielt die Rotationsmatrix bei der Position keine Rolle mehr. Denn
0 | r | r | r | p | p | ||
0 | * | r | r | r | p | = | p |
0 | r | r | r | p | p | ||
1 | 0 | 0 | 0 | 1 | 1 |
Da jedoch eher selten mehrere Billboards an der selben Position sein sollen, muss für jedes Billboard erneut die Matrix erstellt werden. Das setzen der Position muss hier über eine Translation erfolgen, also:
glVertex( 10, 20, 30 ); <=> glTranslate( 10, 20, 30 ); glVertex( 0, 0, 0 );
Dadurch lässt sich folgender Pseudocode für das Zeichnen von Billboards mit dieser Methode ableiten:
Für jedes Billboard: glPushMatrix() glTranslate( BillboardPos.x, BillboardPos.y, BillboardPos.z ) glGet( GL_MODELVIEW_MATRIX, Matrix ) Setze Rotationsteil von Matrix auf Identitätsmatrix glLoadMatrix( Matrix ) glVertex2( + 1, + 1 ) glVertex2( - 1, + 1 ) glVertex2( - 1, - 1 ) glVertex2( + 1, - 1 ) glPopMatrix()
Da hier für jedes Billboard erneut die Matrix berechnet werden muss, ist diese Methode sehr aufwändig für eine große Anzahl von Billboards. Jedoch ist diese Methode verhältnismäßig einfach zu verstehen. Die Skalierung der Matrix wird hier verworfen und müsste nach dem setzen der Billboard-Matrix erneut erfolgen.
Mittels Software transformation
Die Software transformation ist ebenfalls eine eher einfach zu verstehende Methode. Obwohl sie bereits um einiges schneller als die Matrix Manipulation ist, ist sie dennoch nicht die schnellste Methode. Wie in der vorigen Methode können wir wenn die Rotationsmatrix der Itentitäts-Matrix entspricht, das Rechteck wie in 2D behandeln. Bleibt wiederum das Problem mit der Position. Dieses wird in dieser Methode so gelöst, das wir die Arbeit von OpenGL übernehmen, und die Billboardposition manuell (in Software) mit der Modelview Matrix multiplizieren. Dadurch kann die Modelview Matrix von OpenGL auf die Identitäts-Matrix gesetzt werden (was ein einfaches Zeichnen des Billboards ermöglicht) und wir können dennoch die richtige Position eines Billboards bestimmen. Im Unterschied zur vorigen Methode, wird hier nicht nur der Rotationsteil der Matrix auf die Identitätsmatrix gesetzt, sondern die gesamte Matrix. Und zwar weil wir ja auch die Position des Betrachters (also die Position der ursprünglichen Modelview Matrix) in die berechnete Position mit einfließen lassen. In Pseudocode sieht das etwa so aus:
glPushMatrix() glGet( GL_MODELVIEW_MATRIX, Matrix ) glLoadIdentity() Für jedes Billboard: BPos = Billboard_Position * Matrix glVertex( BPos.x + 1, BPos.y + 1, BPos.z ) glVertex( BPos.x - 1, BPos.y + 1, BPos.z ) glVertex( BPos.x - 1, BPos.y - 1, BPos.z ) glVertex( BPos.x + 1, BPos.y - 1, BPos.z ) glPopMatrix()
Dies erfordert also für jedes gezeichnete Billboard eine Multiplikation eines Vektors mit einer Matrix in Software. Wie in der ersten Methode wird auch hier die Skalierung der Matrix bei der Größe des Billboards nicht beachtet, die Position des Billboards wird allerdings auch für skalierte Matrizen korrekt berechnet.
Mit Right- und Up- Vektor
Um das ganze etwas zu beschleunigen, kann man sich auch Right- und Up-Vektor arbeiten, die die aktuelle Rotation der Szene rückgängig machen, und statt einer einfachen 2D-Darstellung des Rechtecks diese beiden Vektor zum spannen des Rechtecks verwenden. Das herausfinden dieser beiden Vektoren erfordert eine noch detailiertere Betrachtung der Modelview Matrix. Üblicherweise ist der Rotationsteil der Modelview Matrix orthogonal. Bei einer orthogonalen Matrix ist die inverse Matrix gleich der transponierten Matrix. Unter dieser Annahmen können wir die Rotationsmatrix weiter aufteilen:
r | u | v | p |
r | u | v | p |
r | u | v | p |
0 | 0 | 0 | 1 |
- r ... Right-(Rechts-)Vektor
- u ... Up-(Nach oben-)Vektor
- v ... View-(Blickrichtungs-)Vektor
- p ... Position
Und obwohl die Mathematik dahinter vielleicht nicht ganz trivial ist, ist die Praxis dafür umso einfacher. Was jetzt noch fehlt ist das aufspannen des Rechtecks mit dem so heraus gefundenen Right- und Up- Vektor. In Pseudocode sieht das so aus:
glGet( GL_MODELVIEW_MATRIX, Matrix ) Right = Vektor( Matrix[0], Matrix[4], Matrix[8] ) Up = Vektor( Matrix[1], Matrix[5], Matrix[9] ) Für jedes Billboard: glVertex( BPos.x + Right.x + Up.x, BPos.y + Right.y + Up.y, BPos.y + Right.y + Up.y ) glVertex( BPos.x - Right.x + Up.x, BPos.y - Right.y + Up.y, BPos.y - Right.y + Up.y ) glVertex( BPos.x - Right.x - Up.x, BPos.y - Right.y - Up.y, BPos.y - Right.y - Up.y ) glVertex( BPos.x + Right.x - Up.x, BPos.y + Right.y - Up.y, BPos.y + Right.y - Up.y )
Wobei BPos wiederum die Billboard-Position ist. Wie unschwer zu erkennen wird hier (gleich wie bei der vorigen Methode) nur einmal je Frame die Modelview Matrix benötigt. Hier fällt jedoch zusätzlich noch die Matrixmultiplikation weg und da die Modelview Matrix nicht verändert wird, müssen auch nicht alle Billboards hintereinander gezeichnet werden, sondern können zu einem beliebigen Zeitpunkt (sofern es sich noch um die selbe Modelview Matrix handelt) an OpenGL gesendet werden. Der einzige Aufwand besteht in ein paar Additionen die sogar noch auf nur 12 (statt 24) Additionen reduziert werden können, wenn man sich die Right- und Up- Vektoren in 4 Vektoren für den 1., 2., 3. und 4. Punkt vorberechnet. In Software ist dies üblicherweise die schnellste Methode Billboards darzustellen.