Tutorial 2D

Aus DGL Wiki
Version vom 22. September 2005, 14:20 Uhr von Flash (Diskussion | Beiträge) (Erster Teil bis Grundlagen)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

2D mit OpenGL - „Nicht jeder benötigt 3 Dimensionen“

Einleitung

Bei der Erwähnung einer API wie OpenGL denken die meisten eigentlich eher an 3D, und sind der festen (aber sehr wohl falschen) Überzeugung eine solche API sei für reine 2D-Anwendung überdimensioniert oder gar ungeeignet. Das dies nicht der Fall ist möchte ich mit diesem (vor allem an Einsteiger gerichtet, denn die Könner wissen wohl was man mit der GL so alles machen kann) Tutorial zeigen und auch gleich mit mehreren praktischen Beispielen aufweisen das 2D mit OpenGL nicht nur möglich ist, sondern auch noch sehr viel einfacher (selbst mit der GDI ist 2D komplizierter) ist und dabei jede Menge Vorteile mit sich bringt.

Welche Vorteile bringt mir die GL für eine 2D-Anwendung?

Dies ist wohl das wichtigste Kapitel und sollte zugleich auch mit diversen Vorurteilen und Missverständnissen aufräumen. Denn gerade der 3D-Bereich ist es in dem seit Jahren fast monatlich neue Techniken entworfen werden und der dafür sorgt das v.a. Grafikkarten immer leistungsstärker werden, während der 2D-Bereich seit seligen VLB-Zeiten (=Vesa-Local-Bus, alte Haudegen kennen diese Grafikkartengeneration sicherlich noch) keine Innovationen mehr erlebt hat (und warum auch? Im 2D-Bereich reicht ein gutes Bild zusammen mit passabler Darstellungsgeschwindigkeit).

Deshalb gibt es jetzt gleich mal die wichtigsten Punkte warum man denn gerade OpenGL (D3D würde hier auch zählen, aber das haben wir GL'ler ja nicht so gerne) für die 2D-Darstellung nutzen sollte :

  • Hardwarebeschleunigung
Moderne Grafikkarten können inzwischen über 200 Millionen Dreiecke pro Sekunde rendern und besitzen brachiale Füllraten jenseits der 2.000 M(Texel/Pixel)/s. Das bedeutet also das man selbst auf älteren Grafikkarten sehr komplexe 2D-Szenen mit Geschwindigkeiten jenseits der 100 FpS (=Frames per Seconds ~ Bilder pro Sekunde) darstellen kann, während man mit der GDI schon bei einfachen 2D-Grafiken Geschwindigkeitsprobleme bekommen würde.
  • „Kostenlose“ Objektsortierung
Eine 3D-API braucht einen Tiefenpuffer um zu erkennen ob Fragmente verdeckt sind oder nicht und damit Overdraw zu vermeiden. Eine 2D-Anwendung kann diesen Tiefenpuffer aber auch nutzen, nämlich um Objekte zu sortieren. Man nutzt dann die Z-Koordinate der Objekte (=Tiefenkoordinate) quasi als Layer um zu kennzeichnen welches Objekt auf welcher „Höhe“ liegt. Wenn man also z.B. einen 2D-Topdown-Shooter entwickelt bei dem der Spieler mit seinem Flugzeug über den Boden fliegt, dann nutzt man den Z-Puffer um die API (die das dann der Hardware überlässt) seine Objekte sortieren zu lassen. Das Flugzeug bekommt dann einen niedrigen Z-Wert (=oben) und Objekte auf dem Boden einen hohen Tiefenwert (=unten/hinten). Die Sortierung übernimmt dann die Grafikkarte und wir müssen uns darum keine Gedanken machen. Würden wir die Anwendung z.B. über die GDI realisieren, müssten wir diese Objekte selbst entsprechend ihrer Höhe sortieren.
  • Jede Menge hardwarebeschleunigte Spezialeffekt
Wie schon oben erwähnt haben im 3D-Bereich innerhalb der letzten Jahre sehr viele Innovationen stattgefunden. Warum sollte man diese also nicht auch für seine 2D-Anwendung nutzen? Klingt logisch und macht auch Sinn! So bietet OpenGL alle Arten von Effekten die auch in einer 2D-Anwendung nützlich sein können. Darunter solche Sachen wie den Alphatest (der dafür sorgt das maskierte Teile eines Objektes transparent sind), Blending und natürlich (auch wenn das jetzt für erfahrene GL'ler sehr trivial klingt) hardwarebeschleunigte Rotation und Skalierung; was zur Folge hat das man seine Objekte nicht für verschiedene Auflösungen in verschiedenen Größen erstellen muss. Für Fortgeschrittene gibt es dann natürlich noch solche Sachen wie Shader, mit denen man Teile der OpenGL-Pipeline durch eigene (kleine) Programme ersetzen kann (entweder in Assemblerform oder aber in der neuen GL-HLSL). Dadurch bietet sich dann ein quasi unendlich großes Spektrum an möglichen Effekten, und das wohlgemerkt alles hardwarebeschleunigt!
  • Plattformübergreifend
Auch ein großer Vorteil von OpenGL. Die Tatsache das die GL unter diversen Betriebssystemen verfügbar ist (im Gegensatz zu GDI oder gar DirectX) macht die eigenen Programme recht portabel (einschränkend ist hier halt nur die Verfügbarkeit der genutzten Programmiersprache auf dem passenden OS). Unterstützt werden alle größeren Betriebssysteme wie Windows, Linux, MacOS und Solaris.
Ganz nebenbei wurde vor kurzem mit OpenGL ES ein mobiler Standard für OpenGL geschaffen, wodurch es dann auch möglich ist auf mobilen Geräten (Handys, PDAs, Handhelds) OpenGL zu nutzen. Und gerade dort sind 2D-Spiele (aufgrund der oft mangelnden Leistung der Geräte) ja noch stark verbreitet.

So viel also zu den wichtigsten Vorteilen zur OpenGL unter 2D. Natürlich gibt es noch weiter Dinge die OpenGL für 2D-Anwendungen attraktiv machen, aber allein die oben genannten Gründe sollten jedermann überzeugt haben. Und alle die wirklich mal wissen wollen wie gut OpenGL denn für solche Anwendungen geeignet ist, sollten sich unbedingt eine neuere Version des MacOS ansehen, denn das benutzt OpenGL zur Darstellung seiner GUI.


Und welche Nachteile gibt es?

Nichts was der Mensch bisher erfunden hat (mal abgesehen von der Spaltung des Atoms ;) ) hat nur Vorteile. Genauso sieht es auch aus wenn man die OpenGL für seine 2D-Anwendung nutzen will. Welche genau das sind will ich hier grob auflisten.

  • Ohne 3D-Beschleuniger mit passenden Treibern geht nichts
Klingt logisch, oder? OpenGL ist eine 3D-API und da 2D nichts weiter als die (fast vollständige) Vernachlässigung der Z-Koordinate ist, kommen wir um einen 3D-Beschleuniger nicht herum, der dazu auch noch einen Treiber mitbringen muss der OpenGL unterstützt. Allerdings schritt der Fortschritt auf diesem Gebiet der IT-Technik in den letzten Jahren so rasant voran wie sonst nirgendwo, und wir werden nur sehr selten auf Rechner stoßen in denen Hardware agiert die keine 3D-Beschleunigung bietet. Ergänzend dazu sollte allerdings trotzdem immer der neuste Treiber installiert sein, denn besonders die in WindowsXP integrierten Grafikkartentreiber wurden ihrer OpenGL-Funktionalität entraubt (Man riecht hier förmlich die Konkurrenz zwischen D3D und der GL). Also ist dies im Endeffekt ein Nachteil der inzwischen kaum noch halt findet und in Zukunft total vernachlässigt werden kann.
  • Hardwarelimitationen
Einer der größten Nachteile einer jeden 3D-API die auf Hardwarebasis arbeitet sind die Limitationen die die Hardware mitbringt. Jeder Grafikkartentyp hat andere, was mitunter dazu führen kann das die selbstverfassten OpenGL-Anwendungen nicht auf allen Rechnern laufen. Da wir uns in diesem Tutorial (2D ist ja recht anspruchslos) allerdings in den Niederungen der OpenGL-Funktionalität bewegen, dürfte es hier kaum Probleme geben. Einzig die Tatsache das vor allem ältere 3D-Beschleuniger mit großen Texturen Probleme haben könnte hier und da Schwierigkeiten machen. Wer aber keine Texturen größer 1024x1024 Pixel nutzt und dazu noch sparend mit dem Speicher der Grafikkarte umgeht (nicht jede Grafikkarte hat 128 Mbyte Grafikspeicher oder gar mehr). Einige Leute werden sich übrigens evtl. dadurch verunsichert fühlen das ihnen jemand gesagt hat, man könnte unter OpenGL nur Texturen nutzen die der Dimension 2^n*2^n entsprechen. Das ist grundlegend korrekt, aber wir nutzen hier einen Texturenloader der gluBuildMipMaps benutzt um MipMaps (verschiedene Detailstufen) für unsere Texturen zu erstellen. Diese Funktion schluckt jede Größe (sofern diese kleiner oder gleich dem Hardwarelimit ist) und passt die Texturen dann entsprechend an eben genanntes Limit an, also müssen wir uns um diese so oft erwähnte Limitation keine Sorgen machen. Wer zu dem Thema Hardwarelimitation mehr wissen will, der sollte unbedingt mal auf Tom Nuydens Seite vorbei schauen. Dort gibt es eine riesige Datenbank in der fast alle Grafikkarten mit ihren entsprechenden OpenGL-Fähigkeiten vertreten sind.
  • Filtering
Zugleich ein großer Vorteil, aber je nach Situation auch ein Nachteil. OpenGL filtert Texturen (sofern man das via GL_LINEAR so will) bilinear, was man auch tunlichst aktiviert lassen sollte (GL_NEAREST filtert nicht, sieht dann aber auch scheußlich blockig aus). Dadurch wirken Texturn meist etwas verschwommen. Ich für meinen Teil umgehe dies aber ganz einfach, denn in fast jedem Bildbearbeitungsprogramm gibt es eine Funktion mit der man ein Bild scharfzeichnen kann. Das sieht auf den ersten Blick dann zwar überzeichnet aus, aber wenn OpenGL das Bild dann als Textur bilinear filtert, heben sich Filtering und Scharfzeichnung gegenseitig fast auf. Das hat sich in meinen Anwendungen bisher bewährt und ist nicht wirklich viel Aufwand.

Um dieses Kapitel hier abzuschließen sei noch gesagt das man ohne 3D-Beschleuniger nicht unbedingt auf OpenGL verzichten muss. Brian Paul hat mit Mesa3D nämlich ein Projekt am laufen das OpenGL-DLLs zur Verfügung stellen die komplett über die CPU ablaufen. So kann man dann OpenGL-Anwendungen mit einer etwas schnelleren CPU trotz fehlendem 3D-Beschleuniger nutzen, oder auf Funktionen ausprobieren die von der (zu alten) Grafikkarte nicht unterstützt werden.

Die Grundlagen

Sollte sich der geneigte Leser nun also doch für die GL entschieden haben, so widmen wir uns dann jetzt den Grundlagen der 2D-Darstellung unter OpenGL. Viele Sachen die man bei einer 3D-Anwendung beachten muss, sind hier eigentlich zu vernachlässigen. Wer also schon mal eine kleine 3D-Anwendung unter OpenGL geschrieben hat wird hier sicherlich keine Problem bekommen. Da sich dieses Tutorial aber an blutige (mhh, lecker) Einsteiger richtet, versuche ich so genau und einfach wie möglich zu erklären was man machen muss und v.a. warum. Genau deshalb habe ich auch für einen Großteil der hier erwähnten Techniken im Download zu diesem Tutorial (siehe unsere Files-Sektion und dort unter VCL-Source) jeweils ein eigenes Beispielprogramm + Quellcode (und natürlich ausgiebigen Kommentaren) geschrieben. Wenn zu dem jeweiligen Kapitel ein solches im Download enthalten ist, dann steht das kursiv unter der Überschrift des Kapitels.