Registriert: Di Mär 21, 2006 20:03 Beiträge: 21
Programmiersprache: Delphi, C++
Hi,
ich arbeite derzeit mit Freunden an einem kleinen Jump 'n Run a lá Mario etc. Da wir das Spiel derzeit mit 1280x720 laufen lassen und das im Software modus doch recht langsam wird, dachte ich mir, versuche ich mich an OpenGL. Das ist auch kein allzu großes Problem, da sowohl das 2D Tutorial als auch das Forum mir einige Fragen beantworten. Nun gibt es aber das Problem, dass die Texturen einen unschönen schwarzen Rahmen bekommen.
Zum Vergleich zeige ich einmal wie das aussieht und auch wie es aussehen sollte ...
Um Fragen nach Source Code vorzubeugen (bin zwar ein noob in OpenGL, aber nicht unbedingt in Foren ), poste ich hier mal die Function, die ein SDL_Surface in eine OpenGL Textur umwandelt.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Das Problem liegt viel wahrscheinlicher im Rendering. Du musst OpenGL sagen, dass es den Alphakanal nutzen soll, um eine Transparenz hübsch darzustellen.
Die Funktion glBlendFunc ist auch im Wiki dokumentiert.
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Das Problem liegt viel wahrscheinlicher im Rendering.
Jein, ich vermute es liegt auch an der Textur. Ich vermute du verwendest da eine Textur mit roter Schrift auf schwarzem Grund. Dein Alphakanal beschreibt die Schrift einfach mit 0 bzw. 1, also einem hartem Übergang. Da du GL_LINEAR als Min/Mag-Filter gewählt hast wird zwischen den Pixeln (*) interpoliert: Diese Pixel sind dann halt irgendwie dunkel rot mit einem Alpha von 0.5 oder so.
Mögliche Lösungen: 1. Textur enthält einfach nur eine rote Fläche, die Schrift wird einzig durch den Alphakanal realisiert. Das dürfte für dich die beste Lösung sein. 2. Textur bekommt dieses Gelb als Hintergrundfarbe....dann ist der unschöne Rand eben Gelb => sieht keiner 3. Textur mit GL_NEAREST Filter rendern. Könnte möglicherweise pixelig werden. 4. Textur ohne Skalierung (also 1:1) mit GL_NEAREST Filter rendern. Da hier nicht skaliert wird kann auch nichts pixelig werden.
(*) in diesem Zusammenhang eigentlich "Texel", aber lassen wir das im Einsteigerforum
Registriert: Di Mär 21, 2006 20:03 Beiträge: 21
Programmiersprache: Delphi, C++
Lord Horazont hat geschrieben:
Das Problem liegt viel wahrscheinlicher im Rendering. Du musst OpenGL sagen, dass es den Alphakanal nutzen soll, um eine Transparenz hübsch darzustellen.
Die Funktion glBlendFunc ist auch im Wiki dokumentiert.
greetings
Ich fürchte, ich muss dich enttäuschen. Das nutze ich nämlich bereits. Aber danke für den Tipp. =)
Coolcat hat geschrieben:
1. Textur enthält einfach nur eine rote Fläche, die Schrift wird einzig durch den Alphakanal realisiert. Das dürfte für dich die beste Lösung sein. 2. Textur bekommt dieses Gelb als Hintergrundfarbe....dann ist der unschöne Rand eben Gelb => sieht keiner 3. Textur mit GL_NEAREST Filter rendern. Könnte möglicherweise pixelig werden. 4. Textur ohne Skalierung (also 1:1) mit GL_NEAREST Filter rendern. Da hier nicht skaliert wird kann auch nichts pixelig werden.
1.) Es ist egal welche Schriftfrarbe ich nehme. Es geht ja auch nicht nur um die Schrift. Auch der Charakter wird mit diesem Rahmen "verschönert" 2.) Da dieses Problem nicht nur die Schrift betrifft, sondern alle Texturen, ist das leider ein No-Go. 3.) Danke für den Hinweis. Hab ich gleich ausprobiert. Das Ergebniss ist dennoch noch nicht so ganz wie gewünscht:
Uploaded with ImageShack.us 4.) Also eigentlich strecke ich nichts ...
Code:
bool RendererGL::RenderImage(Uint32 X, Uint32 Y, Uint8 Z, TImage &Image) { if (&Image == NULL) { return false; }; glBindTexture(GL_TEXTURE_2D, Image.GL);
Ich strecke sie auch nicht im SDL-Modus. Von der Texturqualität einmal abgesehen sind beide Renderer in der Ausgabe identisch. (Okay, OpenGL ist meistens schneller. )
Ach, bevor ich es vergesse ... Ich habe die Graphiken im 8-Bit Modus abgespeichert, damit SDL im Software Modus nicht ins schwitzen kommt. (8 Bit : ~400 FPS; 32 Bit : ~40 FPS) Die Laderoutine wandelt es aber im Vorraus in ein 32 Bit Surface um und stellt sicher, dass das Bild den Alpha Kanal hat.
Könnte es vielleich daran liegen? Also an der Umwandlung? Der Source des RenderText sieht so aus:
Code:
bool RendererGL::RenderText(Uint32 X, Uint32 Y, Uint8 Z, string Text, SDL_Color TextColor, TTF_Font *Font) { if (Font == NULL) { Log.Log(0, LOG_FATAL_ERROR, "Failed to render text."); return false; }
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Eh ja. Ohne 32Bit Surface hast du keine Chance, einen passenden Alphakanal für OpenGL zu haben. Zumindest keinen, der schöne Ergebnisse erzielt.
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Zudem habe ich bereits ein Programm, welches im groben auf die Techniken dieser Dateien Zugreift und blendend funktioniert.
Coolcat hat geschrieben:
Wird bei dir eigentlich jedes Frame die Textur / das Surface neu erzeugt? Ich würde sagen dann musst du dich nicht über 40 fps wundern.
1.) Ja, das Font wird derzti bei jedem Rendering Vorgang neu erstellt. Darunter leidet aber vor allem OpenGL und nicht der SDL Modus. 2.) Selbst wenn ich NUR einen komplett LEEREN Hintergrund anzeige und dieser Hintergrund eine 32 Bit Graphik gewesen ist, krachen die FPS im SDL Modus auf die 40 runter. Das hat nichts mit der Schrift zu tun.
Und ja, ich optimiere das noch auf Geschwindigkeit. Also das die Texte nicht bei jedem Rendering neu erstellt werden müssen.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Naja, aber wo nur 8 bit sind kann nicht plötzlich mehr herkommen. Informationen aus dem Nichts geht nur in unrealistischen, meist kriminalistisch angehauchten, Fernsehsendungen.
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Di Mär 21, 2006 20:03 Beiträge: 21
Programmiersprache: Delphi, C++
Warum denn "Informationen aus dem Nichts"? Die Farbpalette hat ja auch einen RGB Farbwert. Und es gibt ja nur eine Transparentz von 0 oder 1 (Im 8 bit Modus).
Durch die Umandlung wird auf dem 32 Bit Surface nun nicht mehr der Farbindex, sondern die RGB Farben dahinter gespeichert. Und der Alpha-Kanal erhält nun einen Wert von 0 oder 255.
Es ist also kein "Aus dem Nichts", sondern "Umwandeln von Vorhandenem".
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Schon, aber um einen sanften Übergang von voller Abdeckung zu Hintergrund zu bekommen, reicht 0 oder 1 respektive 0 oder 255 nicht. Du brauchst auch die Zwischenwerte, und damit die stimmen müssten "Informationen aus dem Nichts" kommen.
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Registriert: Di Mär 21, 2006 20:03 Beiträge: 21
Programmiersprache: Delphi, C++
Ich möchte ja aber gar keine weichen Übergänge haben. Weder im SDL noch im OpenGL Modus. Ich möchte einfach nur, dass die Darstellung im OpenGL Modus exakt dem SDL Modus entspricht. Und sowohl SDL, als auch OpenGL bekommen die gleichen Graphiken. Beide sind 8-Bit. Der einzige Unterschied ist: OpenGL sieht unschön aus, während SDL absolut perfekt läuft.
Hierbei ist es egal, ob ich 8-Bit Bilder lade und sie dann in 32 Bit umwandel, oder ob ich ein Bild dynamisch erstelle. Und ich bezweifel sehr stark, dass es am Bildformat liegt. Der Grund ist einfach, dass ich die gleiche Optik auch mit 32 Bit Graphiken habe. Es ändert sich nichts.
Registriert: Do Sep 02, 2004 19:42 Beiträge: 4158
Programmiersprache: FreePascal, C++
Ist der Text auf den Screenshots gerendert mit SDL oder ein geladenes Bild? Wenn letzteres, vergiss diesen Post. Zeichnest du mit den Textzeichenfunktionen von SDL direkt auf deine Surface und wenn ja, welche verwendest du dafür?
greetings
_________________ If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung. current projects: ManiacLab; aioxmpp zombofant network • my photostream „Writing code is like writing poetry“ - source unknown
„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb
Ich kenn' mich mit SDL nicht so aus, aber mit OpenGL einigermaßen.
Erstmal (wie bereits gesagt) Textur in jedem Frame neu erzeugen ist sehr schlecht.
Dann hab' ich auch noch eine Frage: Hat "Image" vom Typ "TImage", was an verschiedenen Stellen verwendet wird, Zweierpotenzen als Abmessung? Bzw. hat "RenderedText" in der Funktion "RenderText" ebensolche? Wenn nein, könnte das den schwarzen Rand erklären. Nur wenige Grafikkarten unterstützen npot-Texturen, weshalb man immer solche mit Höhe und Breite entsprechend den Zweierpotenzen benutzen sollte. Wenn SDL nun deshalb automatisch deine Textur streckt um die Abmessungen auf die nächste Potenz zu bringen, wird logischerweise interpoliert. Dann entstehen wieder solche Probleme mit halbtransparenten Teilen wie sie bereits beschrieben wurden. Da hilft dann auch kein GL_NEAREST weil der Fehler quasi schon in der Textur vorhanden ist. Eine mögliche Lösung ist die überschüssigen Texel mit Transparenz zu füllen und die Texturkoordinaten anzupassen. Falls dann noch die Ränder kommen nochmal GL_NEAREST probieren (was sowieso schneller als GL_LINEAR sein sollte). Und falls dann noch die Ränder kommen, hab' ich mich geirrt und es liegt an etwas gänzlich anderem.
Registriert: Di Mär 21, 2006 20:03 Beiträge: 21
Programmiersprache: Delphi, C++
Ich habe es ausprobiert und du hast recht. Nachdem ich die Maße des Characters auf eine Potenz von zwei vergörßert hatte, funktionierte alles einwandfrei. Ich ändere noch die Text-Funktion damit es auf eine Potenz von zwei erweitert. Danke nochmal. =)
Mitglieder in diesem Forum: 0 Mitglieder und 6 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.