Ich bin gerade auf der Suche einer passenden Library für ein Projekt von mir. Kurz gesagt es soll ein reines 2D-Spiel werden, das so in etwa folgendes benötigt:
- Anzeigen großer Grafiken (z.B. eine Karte die wesentlich größer als der Bildschirm ist), also Scrolling
- Schnelle Alphakanäle für so allerhand (von Buttons bis Sprites)
- Anti-Aliasing für Linien, Kreise etc.
Mit dem ganzen Projekt habe ich letztes Jahr auf DelphiX angefangen. Dann sind wir hängengeblieben, weil u.a. das Alphablending katastrophal langsam ist (ein selbstgeschriebener simpler Pascal-Code war etwa 10mal schneller als die eingebauten Routinen). In den letzten Wochen habe ich mich dann auf die Suche nach einer Alternative begeben. Jetzt stehe ich gerade vor drei Alternativen:
- Graphics32. Schöne Library, aber für GDI was dann doch etwas bremst
- SDL ("native" 2D-Routinen): Ganz nett, aber die Rakete ist es auch nicht. DirectDraw unterstützt nunmal kein Alphablending.... Tatsächlich ist Graphics32 sogar schneller wenn richtig viel mit Alphablending gearbeitet wird - GDI hin oder her.
- OpenGL... und deshalb bin ich hier.
Wie OpenGL grundsätzlich funktioniert und die ganzen Basiskonzepte weiß ich, da ich damit schon seit geraumer Zeit an der Uni arbeite (für 3D-Anwendungen). Mit dem Hintergedanken, mit OpenGL eine 2D-Library zu "simulieren" (orthographische Projektion und Quads mit Texturen statt Sprites / Grafiken), sieht das ganze aber schon etwas anders aus. Folgendes beschäftigt mich:
- Meine Grafiken haben in der Regel keine Größe in Zweierpotenz. Klar könnte ich nur einen Teil der Textur verwenden, aber bei den großen Grafiken ist das Mist. Aufteilen in kleinere Blöcke geht natürlich, aber wie vermeide ich dann Artefakte an den Kanten? Hat da jemand Erfahrung? Die Grafik vom Hauptspeicher direkt in den Framebuffer zu schreiben ist auch nix - die Karte wird ja gescrollt (also zeitkritisch) und soll ruhig im Grafikspeicher bleiben.
- Macht es Sinn, ggfs. auf die OpenGL-Erweiterungen (sofern vorhanden) zu setzen die Texturen ohne Zweierpotenzgröße erlauben (da gibt's eine ARB, die von niemandem unterstützt wird und eine NVidia-Erweiterung, die halt nur von NVidia unterstützt wird) - oder soll ich mich von dem Gedanken am besten gleich verabschieden?
- Die ganze Sache mit Weltkoordinaten, Bildschirmkoordinaten usw. ist ja ganz nett, aber ich hätte gerne wenigstens eine Auflösung in der mein Programm einen Pixel aus der Grafik auch als genau einen Pixel auf dem Bildschirm darstellt (so wie eine 2D-Library eben zeichnen würde). Texturkoordinaten gehen immer von 0..1 - da wird doch nie im Leben exakt das gleiche auf dem Bildschirm ankommen wie in der Grafik ist (höchstens etwas das fast das gleiche ist), oder?
Sehr angenehm finde ich schonmal, dass ich z.B. auf den Komfort von Graphics32 nicht zwangsweise verzichten muss - in nicht wirklich geschwindigkeitskritischen Bereichen kann ich immer noch ein TBitmap32 verwenden und dann dessen Bits-Pointer mit GL_GBRA an OpenGL übergeben - das ist immer noch sehr fix (im Rahmen des möglichen angesichts des "langsamen" AGP-Busses natürlich). So wäre dann z.B. auch Rendering von TrueTypes möglich - tolle Sache!
Übrigens vielen Dank für das DGL-SDK - das ist wirklich klasse! Hätte ich sowas für C++ an der Uni gehabt, wäre mir viel Arbeit erspart geblieben.
Registriert: Mo Sep 23, 2002 19:27 Beiträge: 5812
Programmiersprache: C++
Arno hat geschrieben:
- Meine Grafiken haben in der Regel keine Größe in Zweierpotenz. Klar könnte ich nur einen Teil der Textur verwenden, aber bei den großen Grafiken ist das Mist. Aufteilen in kleinere Blöcke geht natürlich, aber wie vermeide ich dann Artefakte an den Kanten? Hat da jemand Erfahrung? Die Grafik vom Hauptspeicher direkt in den Framebuffer zu schreiben ist auch nix - die Karte wird ja gescrollt (also zeitkritisch) und soll ruhig im Grafikspeicher bleiben.
Dazu hab ich hier schon mehrfach was gesagt : Entweder du verwendest gluBuildMipMaps, dass deine Texturen automatischa auf die nächste 2^n-Größe stretcht; oder du machst es so wie ich : Grafiken ganz normal erstellen (also z.B. nen 1,3-Ratio) und dann im Bildbearbeitungsprogramm auf 2^n-Stretchen bzw. schrumpfen. Durch das Filtering von OpenGL fällts dann später kaum auf wenn deine Grafiken in der Anwendung wieder mit dem original Ratio dargestellt werden.
Arno hat geschrieben:
- Macht es Sinn, ggfs. auf die OpenGL-Erweiterungen (sofern vorhanden) zu setzen die Texturen ohne Zweierpotenzgröße erlauben (da gibt's eine ARB, die von niemandem unterstützt wird und eine NVidia-Erweiterung, die halt nur von NVidia unterstützt wird) - oder soll ich mich von dem Gedanken am besten gleich verabschieden?
An deiner Stelle würde ich noch ein wenig warten, denn ARB_NPTT ist ja ein GL1.5-Corefeature und dürfte daher demnächst sowohl von ATI als auch von NV unterstützt werden. Herstellerspezifische Extensions kann man zwar als Alternative verweden, diese jedoch vorausszusetzen ist sehr schlecht, denn dann würdest du jede Menge Anwender ausgrenzen. Besonders jetzt, wo NV keine Marktdominanz mehr hat (ATI hatte im letzten Quartal zum ersten Mal einen höheren Marktanteil) wäre das fatal.
Arno hat geschrieben:
Die ganze Sache mit Weltkoordinaten, Bildschirmkoordinaten usw. ist ja ganz nett, aber ich hätte gerne wenigstens eine Auflösung in der mein Programm einen Pixel aus der Grafik auch als genau einen Pixel auf dem Bildschirm darstellt (so wie eine 2D-Library eben zeichnen würde). Texturkoordinaten gehen immer von 0..1 - da wird doch nie im Leben exakt das gleiche auf dem Bildschirm ankommen wie in der Grafik ist (höchstens etwas das fast das gleiche ist), oder?
Das geht im Orthomodus. Dem übergibst du dann halt als Größe deine Fensterdimensionen und schon hast du eine Weltkoordinate = ein Pixel. Zu den Texturkoordinaten : Das geht recht gut und habe das selbst auch schon gemacht. Ob du jetzt z.B. für T 0 bis 256 oder 0 bis 0,5 übergibst sollte im Endeffekt auf das gleiche Rauskommen. Zumindest hatte ich damit bisher keinerlei Probleme. Wenns dann trotzdem nicht klappt packst du die Grafiken halt alle in eine eigene Textur. Alternativ kannst du auch noch (je nach Hardware die du vorraussetzt) über einen Pixelshader eigene Umrechnungen für die Texturkoordinaten benutzen. Da gibst du dann halt bei glTexCoord2f statt 0..1 z.B. 0...512 an und lässt den Shader umrechnen.
Registriert: Do Dez 05, 2002 10:35 Beiträge: 4234 Wohnort: Dortmund
Also zu den Texturen kann ich nur eines sagen. Alles andere wurde schon gesagt. Vergiss das mit den "non Power of Two" Texturen! Ich würde auf keinen Fall auf ein Feature setzen was gerade erst Released wurde und noch in keinem Treiber richtig implementiert worden ist. Eben aus dem Grund was SOS auch schon sagte. Es birgt zu viele Risiken.
In diesem Fall könntest du es zum Beispiel so machen, dass du deine Objekte nicht nur auf eine Textur beschränkst sondern sie zum Beispiel auch auf mehrere Texturen verteilst und dann mit mehreren Flächen zeichnest. Oder die Objekte zwecks besserer Passform zerschneidest und in einer Textur so anordnest, dass sie genau passt. Verschnitt hat man immer. Es ist halt nur die Frage wie groß er ist und ob das überhaupt ins gewicht fällt. Wenn du mit 10 MB Texturen daher kommst musst du dir darüber auch keinen Kopf machen. Heutzutage sind 64 MB auf ner Karte normal.
Es spielt für die Grafikkarte keine Rolle ob du eine Fläche mit einer Textur oder 20 Flächen mit 5 Texturen zeichnest.
PS: Schau dir mal Sacred an. Die beutzen für ihre isometrische Darstellung Direct3D. Und wenn man dort FSAA aktiviert kann man (leider) sehr gut sehen wo die Flächen verlaufen. Die haben ihre Texturen so weit zerschnitten, dass man mit Sicherheit sehr viel Platz sparen kann. Und das läuft dennoch ohne Probleme auf ner TNT2. Auch aus dem Grund weil es nicht so extrem viele Flächen zum Darstellen gibt.
Also erst mal vielen Dank für die Antworten!
Gut, die Sache mit dem Verschnitt ist eine Frage der Vorbereitung und ein gewisser Programmieraufwand, sollte kein allzu großes Problem sein.
Zu den sichtbaren Kanten bei FSAA: Wenn ich das FSAA selber steuere (ARB_MULTISAMPLE), dann kann ich das mit glDisable für solche Flächen gezielt ausschalten (sofern die Einstellung nicht im Grafikkartentreiber festgesetzt ist), oder habe ich das im "Antialiasing"-Thread falsch verstanden? Anti-Aliasing brauche ich - wie oben angedeutet - nämlich dringend für einige Primitive (Linien, Kreise und Co) - aber an der Hintergrundgrafik die möglicherweise gestückelt wird, soll natürlich nichts verändert werden. In gewissen Fällen sollte das Stretchen im Bildbearbeitungsprogramm auch kein Problem darstellen, aber eine Routine, die beim Einladen automatisch stückelt und sich dann beim Zeichnen drum kümmert, dass alles richtig auf dem Bildschirm ankommt, ist auch kein Hexenwerk. Auf den Pixelshader verlasse ich mich lieber nicht, das Spiel soll nach Möglichkeit auch auf Karten der GeForce 2 MX-Generation laufen. Entsprechend lasse ich auch das Warten auf GL 1.5, denn dann ist das Feature wieder nur in den aller-neuesten Treibern aktiv.
Registriert: Mo Sep 23, 2002 19:27 Beiträge: 5812
Programmiersprache: C++
Nein, du verwechselst was. Das was man während der Laufzeit umschalten kann ist das Primitiven-Antialiasing von OpenGL selbst, auf das man heute aber aus diversen Gründen (Bledingprobleme) verzichten sollte. Multisample ist für FSAA und ist Teil des Pixelformates, lässt sich also nicht während der Laufzeit einfach umschalten.
@SOS: Gut - wie komme ich dann trotzdem an Anti-Aliasing für meine Primitive (also wie gesagt Linien, Kreise etc.)? Für meine "Sprites" (also Quads mit Texturen drauf) will ich ja kein FSAA - das lässt die Sache ja nur schlechter, sprich unschärfer aussehen (Spezialfälle ausgenommen). Oder würde es in diesem Fall doch Sinn machen, OpenGLs Primitiven-AA zu nehmen? Meinst du damit GL_POINT_SMOOTH und GL_LINE_SMOOTH wie im Redbook auf Seite 235 beschrieben?
@Flash: Das Warten auf OpenGL 1.5 bezog sich auf die Non-Power-Of-Two Extension. Die gibt es zwar schon als ARB wird aber laut delphi3d.net aber von keiner einzigen Grafikkarte unterstützt. Nicht so prickelnd... Eine rein NVidia-spezifische Extension ist logischerweise auch nix.
Registriert: Mo Sep 23, 2002 19:27 Beiträge: 5812
Programmiersprache: C++
Ich würde innerhalb der Anwendung komplett auf AA verzichten und die Wahl dem User überlassen, der dann per Treiber wählen kann was er will. Problematisch beim AA ist nämlich an sich schon die Tatsache das besonders Linienprimitiven je nach Grafikkarte (sogar innerhalb eines Herstellers je nach Chip unterschiedliche) anders AAd werden und du nur selten auf verschiedenen Konfigurationen ein vergleichbares Bild bekommen wirst.
Ich hab da vor recht langer Zeit nämlich mal eine Seite gesehen (den Link hab ich leider nicht mehr), auf der sehr detailliert anhand eines OpenGL-Testbildes mit diversen Primitiven und Farbverläufen drauf, das AA auf verschiedenen Karten gezeigt wurde. Die Unterschiede waren da mehr als frapierend.
Wie frappierend? Ganz auf AA verzichten will ich keinesfalls - das sieht einfach nicht gut aus und dann kann ich's auch gleich ganz lassen mit OpenGL und eine "echte" 2D-Anwendung schreiben, die alles mit der CPU macht (gut, Alphablending ist ein Argument, aber auch das ist loesbar).
Wenn ich dem User sage: Schalt halt FSAA in den Treibereinstellungen ein, komme ich in Probleme sobald ich anfange Texturen zu stueckeln (Artefakte an den Kanten, siehe oben) - also auch kein guter Ansatz. Ob das Primitiven-AA etwas unterschiedlich aussieht, ist mir eigentlich wurscht - solange dann nicht ploetzlich in gewissen Konfigurationen totaler Muell rauskommt (sprich: dem ganzen Gewurschtel eine Nicht-AAte Linie deutlich vorzuziehen waere). Insofern wuerde mich die Seite wirklich interessieren. Eine Linie selber Pixel fuer Pixel zu zeichnen ist sicher auch nicht gerade toll und das ganze im Speicher vorher zu generieren und dann als Textur auf den Screen zu klatschen ist auch nicht gerade der Hit, da entweder voellig unflexibel und relativ schnell oder aber sehr langsam ist (da dann jedesmal vom RAM in den Grafikspeicher kopiert werden muss - und das auch noch samt Alphachannel).
Versteht mich richtig: Ich versuche gerade herauszufinden, welche Library / Grafikloesung fuer meinen speziellen Fall am besten ist und deshalb versuche ich gleich im Vorfeld soviel wie moeglich klarzustellen um zu vermeiden, dass ich mich voll motiviert in die Programmierung stuerze und dann ernuechtert feststellen muss, dass irgend etwas was ich brauche nicht geht.
Registriert: Mo Sep 23, 2002 19:27 Beiträge: 5812
Programmiersprache: C++
Das mit den Artefakten an den Kantetn löse ich immer recht einfach, indem ich die Textur einfach von einem 1-2 Pixel breitem Platz umgeben lassen, und diesen dann auch von der Alphamaske ausschliesse. So hat man dann nicht die Probleme, die dann durch Filtering entstehen wenn die Textur an allen Kanten "anstösst". (Hoffe das war jetzt verständlich, lässt sich aber auch nicht so einfach ausdrücken)
Aber in Sachen 2D ist OpenGL (jetzt mal ganz ohne parteiisch zu werden) doch das Optimum. Kostenloses Filtering, Hardwarebeschleunigung und dank Pixelshader & Co. kannst du sogar die tollsten Filter in 2D anwenden, ganz auf der GPU. Wenn du wissen willst wie gut sich die OpenGL für 2D eignet, dann schau dir mal das MacOS X an, denn das wird komplett über OpenGL dargestellt. So spontan fällt mir da für die 2D-Darstellung (und nur diese) nichts besseres/vergleichbares ein.
Genau. Auch ein 2D Spiel kann man bestimmt mit Shadern aufwerten: Wassereffekte, Unschärfe,Überblendungen, Bumpmapping in 2D. Alles was man in Bildbearbeitungsprogrammen machen kann, kann man heutzutage über Shader in HW machen.
Gut, mit Shadern habe ich mich jetzt noch gar nicht beschaeftigt. Vermutlich sollte ich mir das mal genauer anschauen...
Ich denke aber ich weiss du (SOS) meinst mit dem 2 Pixel-Rand. Ich beschreib's mal in eigenen Worten um sicher zu gehen:
Anstatt 512x512 voll auszunutzen, mache ich die Grafik nur 508x508 gross und setze sie mittig in die 512x512-Textur (also 2 Pixel Rand ringsrum). Diesen 2 Pixel Rand setze ich im Alphakanal auf voellig durchsichtig. Beim Malen setze ich dann die Texturen so, dass dieser durchsichtige Rand ueber die Textur daneben gemalt wird. Also die erste Textur startet bei -2,-2 die naechste bei 508,-2 usw. Passt das so?
Das mit MacOS X weiss ich auch und das war auch einer der Gruende, warum ich mich dann doch fuer OpenGL entschieden habe. Anfangs hatte ich das fuer mich voellig ausgeschlossen, weil ich mir dachte, dass das voellig ueberfluessiger Overhead ist und ich mit einer reinen 2D-Library auch gluecklich werde. Inzwischen weiss ich mehr...
Die naechste Frage zum Thema FSAA: Ich erinnere mich, dass die Texturen tendenziell unscharf werden (dafuer gibt's auch den Haken "Sharpen Textures' in den NVidia-Treibereinstellungen). Wenn FSAA also aktiviert ist, kann ich mich wiederum von dem Gedanken "1 Pixel in der Grafik entspricht 1 Pixel auf dem Bildschirm ohne dass daran was geaendert wird") verabschieden und tendenziell werden alle Grafiken im Spiel etwas unscharf. Oder bringe ich wieder was durcheinander?
Registriert: Mo Sep 23, 2002 19:27 Beiträge: 5812
Programmiersprache: C++
Das mit dem Rand hab ich genauso gemeint, weil dann das Filtering die Texturenränder nicht ineinander "bluten" lässt.
Zum Thema FSAA : Ja, herkömmliches FSAA zeichnet alles weich, denn es arbeitet ja nicht im 3D-Raum, sondern wird nach dem Rendern der Szene auf den Framepuffer angewendet. Es gibt zwar noch andere AA-Techniken, die nur Ränder von Objekten weichzeichnen (Matrox hat das auf der Parhelia, funzt dort aber mehr schlecht als recht), aber sowohl ATI als auch NVidia nutzen da normales FSAA. Qualitativ ist ATI da besser, gefolgt von NV und den Rest der Meute (Matrox, XGI, S3, usw.) kann man getrost aufgrund ihrere ineffizienten FSAA-Implementationen vergessen.
Allerdings kann man ganz einfach einen negativen LOD-Bias nutzen, um Texturen ohne Aufwand schärfer zu machen :
Dabei wird im Endeffekt nix anderes gemacht als die MipMap-Berechnung anzupassen. Positiver Wert ist quasi gleich einem Blur-Filter, negativer Wert gleich einem Scharfzeichnungsfilter. Letzteres ist genau das was die "Sharpen Textures"-Option im NVIdia-Treiber macht : Sie ändert den LOD-Bias ins Negative.
Hrm. Fuer 3D-Anwendungen mag das ja alles ganz nett sein, da ist eine Textur ohnehin nie in ihrer "echten" Aufloesung auf dem Bildschirm. Bei 2D sieht das aber anders aus. Da haette ich eben gerne exakt das aus der Grafik auf dem Schirm.
Jetzt hab ich mal noch bei NVidia vorbeigeschaut und das Dokument zur WGL_ARB_multisample durchgelesen (nennt sich "OpenGL Multisampling"). Dort findet sich folgender Hinweis in den Vorteilen: "Explicit control of the what should or shouldn’t be antialiased" (und auch "Much nicer than a Display Driver control panel toggle" ) sowie der Hinweis:
Enabling/Disabling multisample rasterization:
glEnable(GL_MULTISAMPLE_ARB)
glDisable(GL_MULTISAMPLE_ARB)
Du sagtest, dass man FSAA nicht pro Objekt an und ausschalten kann. Bei NVidia klingt das anders. Verstehe ich wieder etwas falsch?
Registriert: Mo Sep 23, 2002 19:27 Beiträge: 5812
Programmiersprache: C++
Aufgrund der Natur von FSAA (da es ja auf den Framebuffer angewendet wird), kann ich mir nicht vorstellen das man so einfach über MultisampleARB auf Primitivenbasis AA an- bzw. ausschalten kann, zumal das für eine reine 3D-Szene auch unpraktikabel ist. Da wird man dann wohl allerhöchstens festlegen können ob der aktuelle Frame AAd wird oder nicht.
Da ich aber bisher immernoch der Meinung bin man sollte solche Sachen wie AA/AF dem User überlassen (via Treibermenü) hab ich auch noch nicht mit MultisampleARB gearbeitet, also lasse ich mich gerne eines besseren belehren.
Mitglieder in diesem Forum: 0 Mitglieder und 20 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.