OpenGL in Visual Basic - Displaylisten
von Hans Henning Klein
Grundlagen
Willkommen im Kapitel mit dem eingebauten Turbo. Bisher haben wir uns bei der Erarbeitung der Grundlagen wenig um Laufzeit oder gar deren Optimierung gekümmert. Das wird sich jetzt ändern. OpenGL bietet uns dazu ein schönes Werkzeug, genannt Displaylisten. Was sind nun Displaylisten?
Displaylisten sind eine Möglichkeit, eine Szene vorab zu berechnen und später einfach nur darzustellen.
In der Praxis läuft das so ab: Mit dem Erstellen einer Displayliste wird diese direkt an die Grafikkarte gesendet, dort vom Treiber so weit wie möglich optimiert und dann im lokalen Grafikkartenspeicher abgelegt. Wollen wir diese Informationen nun darstellen können diese einfach aus dem lokalen Speicher entnommen und gerendert werden. Mit der bisher von uns praktizierten Methode werden die Daten erst vom Hauptspeicher des Computers über den langsamen Bus zur Grafikkarte gesendet.
Ein kleines (theoretisches) Rechenbeispiel soll das verdeutlichen:
Der AGP-Bus zur Grafikkarte schafft im 8fach Modus etwa 2 GByte Daten je Sekunde. Moderne Grafikkarten haben ein Speicherinterface mit dem mehr als 20 GByte Daten je Sekunde aus dem lokalen Grafikkartenspeicher gelesen werden können. Das ergibt eine (theoretische) Steigerung auf die 10fache Geschwindigkeit. Diese Werte sind natürlich in der Realität nicht zu erreichen, aber Steigerungen von bis zu 100% sind durchaus möglich.
Gerade bei der Entwicklung von OpenGL-Anwendungen mit Visual Basic, welches selbst eher mäßig schnell ist, können Displaylisten zu einem enormen Zuwachs an Geschwindigkeit führen.
Natürlich hat das Ganze einen Pferdefuß - wär ja sonst zu schön gewesen. Displaylisten belegen relativ viel Platz und das auf dem internen Speicher der Grafikkarte. Sobald dieser nicht mehr ausreicht werden die Listen eben dennoch wieder im Hauptspeicher abgelegt und dann ist Schluss mit Tempo. Daher sollten Sie bei umfangreichen Projekten die Verwendung von Displaylisten genau planen und keinesfalls alles darin unterbringen.
Anmerkung: Bitte beachten Sie, dass dieser Code unter Umständen Probleme mit bestimmten Versionen von ATI-Grafikkartentreibern verursachen kann. Sollten Sie ebenfalls ein Problem feststellen, bitten wir um eine entsprechende Mitteilung mit Fehlermeldung, Grafikkarte und Treiberversion.
Abbildung 1: Mit Displaylisten lässt sich das Programm beschleunigen.
Inhalt
Praxis
Dieses Beispiel basiert auf Kapitel 7 - Dynamische 3D-Welten und liest die Daten einer Kugel ein.
Public Function CreateGLWindow(frm As Form, Width As Integer, Height As Integer, Bits As Integer) As Boolean '... LoadWorld App.Path & "\Kugel.txt" 'einlesen der Welt-Daten Call GenerateLists 'Displaylisten erstellen '... End Function
Listing 1: CreateGLWindow
Die Verwendung von Displaylisten ist denkbar einfach und benötigt nur wenige Anweisungen:
Public Sub GenerateLists() DisplayLists(0) = glGenLists(1) 'Zeiger auf eine neue Displayliste glNewList DisplayLists(0), lstCompile 'Neue Displayliste beginnen. 'Der Parameter lstCompile weist OpenGL an, die Liste sofort zu kompilieren. Call DrawScene 'Zeichnen der Szene glEndList 'fertig End Sub
Listing 2: Erzeugung der Displayliste
Die Prozedur DrawScene zeichnet die mittels LoadWorld eingelesenen Daten für eine Kugel die in unserem Fall aus 4511 Dreiecken besteht.
Public Sub DrawScene() 'Darstellung der eingelesenen Daten in einer Schleife For I = 0 To Sektor(0).Sct_NummTriangle - 1 'alle Dreiecke abarbeiten 'Auswahl der gewünschten Textur If Sektor(0).Triangle(I).T > 0 Then glBindTexture GL_TEXTURE_2D, Texture(Sektor(0).Triangle(I).T) glBegin bmTriangles For J = 0 To 2 '3 Punkte je Dreieck With Sektor(0).Triangle(I).Vertex(J) glTexCoord2f .U, .V: glVertex3f .X, .Y, .Z End With Next glEnd Next End Sub
Listing 3: DrawScene
Dann müssen wir das Ganze nur noch testen. Damit der Unterschied deutlich wird, zeigen wir im Titel der Form die gezeichneten Frames je Sekunde an. Der entsprechende Code sollte verständlich sein. Um zwischen direktem Zeichnen und Displayliste hin- und her zu schalten, legen wir die Darstellung über die Taste D fest.
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) '... If KeyCode = vbKeyD Then Disp = Not Disp End If End Sub Public Sub Main() '... T1 = Timer 'Zeitpunkt Beginn der Darstellung glClear clrColorBufferBit Or clrDepthBufferBit ' löscht das Fenster und den Tiefenpuffer glLoadIdentity 'setzt die aktuelle Modell-Matrix zurück glTranslatef 0#, 0#, -8# glRotatef r4eckY, 0#, 1#, 0# 'Drehen des Würfels um die Y Achse If Disp Then glCallList DisplayLists(0) 'Darstellung über Displayliste Else Call DrawScene 'direktes Zeichnen End If SwapBuffers (frm.hDC) 'Puffer tauschen (Double Buffering) DoEvents r4eckY = r4eckY + 0.4 'Winkel für Drehung hochzählen T2 = Timer 'Zeitpunkt Ende der Darstellung Ct = Ct + 1 'Zähler für Frames Fps = Fps + (T2 - T1) 'Verbrauchte Zeit hochzählen If Fps > 1 Then 'nach einer Sekunde ausgeben If Disp Then frm.Caption = Ct & " Frames/Sec mit Displayliste" Else frm.Caption = Ct & " Frames/Sec bei direktem Zeichnen" End If Fps = Fps - 1 Ct = 0 End If '... End Sub
Listing 4: KeyDown-Ereignis und Sub Main
Es geht weiter
So, das war schon alles.
Bei sehr schnellen Rechnern mit einfacher Grafikkarte kann es bei diesem Beispiel vorkommen, dass direktes Zeichnen schneller ist als die Displayliste. Je besser aber die Grafikkarte um so mehr werden die Unterschiede sichtbar. Für ältere Rechner und/oder einfache Grafikkarten ist dem Beispielprojekt eine weitere Kugel mit nur 1983 Dreiecken beigefügt. Mein eigener Testrechner mit einem Dual Core 1 Prozessor und einer einfachen Intel Graphics Media Accelerator Grafikkarte mit 128 MByte Shared Memory bring es bei direktem Zeichnen gerade noch auf 18 Frames/Sekunde. Das zeigt die Grenzen von VB in der 3D-Welt auf. Für rund 4500 Dreiecke werden in der inneren Schleife von DrawScene ca. 13500 Vertices (Punkte) gesetzt. Da Animationen unterhalb von 24 Frames/Sekunde häufig ruckeln, sollte dieser Wert eigentlich nicht unterschritten werden.
Wenn wir das jetzt weiter durchdenken würde das bedeuten, wir könnten nur ca. 10000 Vertices rendern. Dem ist tatsächlich so. Doch OpenGL bietet Möglichkeiten, diese Einschränkung zu relativieren. Das Geheimnis heißt Quadriken und hat in Kapitel 9 (Noch nicht veröffentlicht) sein kurzes, aber eindrucksvolles Debüt.
Ihre Meinung
Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.