Billboard

Aus DGL Wiki
Wechseln zu: Navigation, Suche
Hinweis: Dieser Artikel ist noch unvollständig.
(Mehr Informationen/weitere Artikel)

{{{1}}}

Incomplete.jpg

Bilboards

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.

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 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, ein 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 Matrixmanipulation

Die Matrixmanipulation 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 Identitä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 Softwaretransformation

Die Softwaretransformation ist ebenfalls eine eher einfach zu verstehende Methode. Obwohl sie bereits um einiges schneller als die Matrixmanipulation ist, ist sie dennoch nicht die schnellste Methode. Wie in der vorigen Methode können wir wenn die Rotationsmatrix der Identitä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.

Mittels Point-Sprites (Hardware)

Mit der NV_Point_Sprite-Extension hat NVidia vor einigen Jahren sog. Point-Sprites eingeführt, die, vor allem für die Darstellung von Partikelsystemen, Vorteile bringen. Während man ansonsten für jeden Partikel vier Eckpunkte (wenn als Quad gerendert) über den Bus schieben musste und jeden Partikel auch noch am Bildschirm ausrichten musste, muss man unter Nutzung dieses Hardwarefeatures nur noch einen einzigen Punkt (Zentrum des Billboards) an die Grafikkarte senden und der Rest wird von der Hardware übernommen. Also müssen dann sehr viel weniger Daten (1 Eckpunkt statt 4, Texturkoordinaten müssen gar keine gesendet werden, das wird automatisch erledigt) über den Bus geschoben werden und es muss auch nicht mehr manuell am Bildschirm ausgerichtet werden. Vor kurzem hat diese Funktionalität übrigens Einzug in den GL-Kern gefunden, unter der Bezeichnung ARB_point_sprite (Original Spezifikation (engl.). Natürlich eignet sich diese Methode primär nur für Partikelsysteme, denn hier wird automatisch an allen drei Achsen ausgerichtet, was besonders bei größeren Billboards (z.B. Bäumen, bei Gräsern kann man das machen) unerwünscht ist.

Mittels Vertexprogramm

Zylindrische Billboards