Was ist die beste Vorgehensweise für einen Fortschrittsbalken in OpenGL ES 2.0?

7

Mein Versuch: Ich mache eine Textur (kann eine einzelne Farbe oder eine andere sein) und strecke diese Textur dann von einem minimalen 0bis zu einem maximalen maxWert. Das funktioniert, macht mich aber aus mehreren Gründen ziemlich unzufrieden, darunter:

  • Wenn ich im Verlauf des Balkens abgerundete Ecken haben möchte, werden die Kanten gequetscht oder gedehnt.

Meine Frage: Was ist die beste Vorgehensweise, um ein Fortschrittsbalkenergebnis zu erzielen?

Gedanken: Gibt es eine Möglichkeit, openGL daran zu hindern, ab einem bestimmten xWert einer Textur etwas zu zeichnen ? Auf diese Weise konnte ich die Textur so zeichnen, wie sie erscheinen sollte, aber den Wert von angeben x.

Ich habe diesen potenziell nützlichen Link gefunden.

Aktualisieren

Ich habe den Eindruck, dass die Verwendung des Schablonenpuffers der richtige Weg sein könnte. Mit dem Schablonenpuffer können Sie einen beliebigen Bereich definieren, durch den andere gerenderte Geometrien abgeschnitten werden können. Anscheinend gibt es viele andere Verwendungszwecke für den Schablonenpuffer, z. B. Reflexionen.

Mögliche Lösung

Mit dem Schablonenpuffer in Kombination mit meinem eigenen Shader habe ich letztendlich das erreicht, was ich wollte, da OpenGL ES 2.0 glAplhaTestund verwandte Funktionen nicht unterstützt . Hier ist ein Bild des Ergebnisses:

Fortschrittsbalken

Die zum Schablonenpuffer gezeichnete Textur war ein längliches Rechteck mit abgerundeten Ecken. Die in den Bildpuffer gezeichnete Textur war nur ein gestrecktes rotes Rechteck, das, wie Sie sehen können, am Schabloneninhalt abgeschnitten ist. Sie müssen Ihren eigenen Shader schreiben, um mit dem Alpha-Kanal fertig zu werden, da OpenGL ES 2.0 die glAplhaTestund verwandte Funktionen nicht unterstützt .

Hinweis - Vielleicht ist dies nicht das beste Bildbeispiel. Tatsächlich können Sie mit der vorgestellten Lösung die linken und rechten Kappen schrittweise anzeigen, was ich im obigen Bild leider nicht demonstriert habe.

Pixel
quelle
Meinten Sie u in Textur oder x in Weltkoordinaten?
Wondra
Ich bin mir nicht sicher, ob ich ehrlich bin - es war nur eine Idee, aber ich bin mir noch nicht sicher, wie ich das erreichen soll.
Pixel
Sie möchten wahrscheinlich eine separate Maskentextur und eine Uniform an Ihren Shader übergeben, damit die Maske nicht gedehnt werden kann. Oder noch einfacher wäre es, Quads für beide Enden und den Körper separat zu erstellen.
Wondra
Warum können Sie nicht einfach nur einen Teil des Fortschrittsbalkens rendern, den Sie rendern möchten? Wenn es bei 50% liegt, rendern Sie die linke Hälfte mit der linken Hälfte der Textur.
user253751
@immibis danke ... Zu der Zeit hatte ich keine Ahnung, dass Sie einen Teil einer Textur auf Scheitelpunkte abbilden können, und ich habe jedes Sprite einzeln mit seiner eigenen Textur gerendert. Nachdem ich seit einiger Zeit Sprite-Atlanten verwende, verstehe ich, wie ich Ihren Vorschlag umsetzen würde. Es ist viel effizienter als meine ursprüngliche Idee! Vielen Dank.
Pixel

Antworten:

5

Keine Notwendigkeit, zusätzliche Einheiten einzubeziehen, KISS

Rendern Sie einfach den Fortschrittsbalken aus drei Teilen - der linken Kappe, der rechten Kappe und dem Körper. Schema:

 {left cap] [body] [right cap}

Linke und rechte Kappe sind normalerweise immer gleich - Halbkreise mit Transparenz. Die Körpertextur muss ohne erkennbare Auswirkungen dehnbar sein.

Linke und rechte Kappen werden normalerweise unabhängig davon gerendert, und der erforderliche Prozentsatz wird mit der Körperbreite angezeigt. So könnte zB 0% ein leerer Balken sein, 1% sind Kappen mit einem Körper von 0 Breite.

Weitere Informationen zum Strecken ohne Verzerrungen in beiden Achsen: Google für "Neun-Patch-Button".

Kromster
quelle
Ich mag das Prinzip. Ich möchte jedoch einen fließenden Blick auf diese Balken werfen, und die beschriebene Methode erlaubt es nicht, dass sich die (linke Kappe] oder [rechte Kappe) allmählich offenbart. Meine aktuelle Implementierung macht :-D Außerdem kann ich jetzt aufgrund meiner Kenntnisse über Schablonenpufferung viele andere Effekte erzielen. Ich werde KISS auf jeden Fall im Auge behalten!
Pixel
Schablone konnte oft durch eine Texturmaske ersetzt werden. Nur für den Fall, dass es nicht verfügbar ist oder ein Overkill für einen einzelnen Fortschrittsbalken)
Kromster
Ich werde einen Blick darauf werfen. Ich weiß nichts über Texturmasken!
Pixel
1

Es gibt einige Möglichkeiten, dies zu tun.

Dies ist die von poirot beschriebene Lösung:

Letztendlich habe ich mit dem Schablonenpuffer in Kombination mit meinem eigenen Shader das erreicht, was ich wollte ... Die zum Schablonenpuffer gezeichnete Textur war ein längliches Rechteck mit abgerundeten Ecken. Die in den Bildpuffer gezeichnete Textur war nur ein gestrecktes rotes Rechteck, das, wie Sie sehen können, am Schabloneninhalt abgeschnitten ist.

Sie können stattdessen drei Instanzen von Geometrie verwenden. ein Halbkreis für jedes Ende und ein dazwischen gesticktes Rechteck. Beachten Sie, dass hierfür kein benutzerdefinierter Shader oder keine Schablone erforderlich ist. (Diese Lösung scheint die gleiche zu sein, wie sie in den Kommentaren von wondra vorgeschlagen wurde.) Diese Lösung ist aus mehreren Gründen mein Favorit.

Ein Hinweis zum Schablonenpuffer, der mehrfach abgetastet werden kann und ein Anti-Aliasing für einen vollständigen Frame ohne Anwendungseingriff ergibt. Alpha-Tests (Shader oder nicht) sind jedoch eine Fragmentoperation, die nicht mehrfach abgetastet wird. Wenn Sie die beiden Schablonenpuffer kombinieren, werden niemals wirklich mehrere Stichproben erstellt. Alle Proben werden gleich behandelt, daher kein Anti-Aliasing.

Andreas
quelle
Aber wie zeigt man mit einem Halbkreis, einem Rechteck und einem letzten Halbkreis den Fortschritt der Halbkreise? Angenommen, die Halbkreise repräsentieren jeweils 10% und das Rechteck verbleibende 80%. Wie würde ich schön 5% ziehen? Der Schablonenansatz ermöglicht es, den Fortschritt vor oder nach dem Anfang / Ende des Rechtecks ​​anzuzeigen, dh irgendwo zwischen der Breite eines Halbkreises.
Pixel
@poirot Ja ich weiß. Aus Ihrem Beispiel ging nicht hervor, wie es aussehen soll, wenn die Leiste leer oder fast leer ist. Eine Variante wäre, die Balkenform in Schablonen zu rendern (solche zu schreiben) und dann den maskierten Bereich (wo es solche gibt) mit einem Rechteck mit einer Länge basierend auf% zu füllen. Wenn der Balken fast leer ist, bedeckt das Rechteck den maskierten Bereich nicht vollständig. Macht das für Sie Sinn? Es ist ähnlich, erfordert jedoch keine zusätzliche Shader-Programmierung, und Multisampling funktioniert möglicherweise weiterhin.
Andreas
0

Am Ende habe ich nur die Tatsache genutzt, dass Sie mit OpenGL einen beliebigen Teil einer Textur Ihren Scheitelpunkten zuordnen können. Angenommen, Sie haben eine Textur mit drei Herzen in einer Reihe, etwa 300 und 80, und möchten nur zwei Drittel auf dem Bildschirm anzeigen. Dann würden Sie Ihren Scheitelpunkten eine Textur (0, 0, 200, 80) zuordnen, aber stellen Sie sicher, dass auch Ihre Scheitelpunkte entsprechend reduziert werden. Spart das Herumspielen mit dem Schablonenpuffer und ist viel schneller und eleganter. Scheint offensichtlich, aber als ich dachte, dass jedes Sprite eine separate Textur verwenden muss, konnte ich es nicht sehen!

Pixel
quelle