Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Mai 16, 2024 18:10

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: GUI mittels VBO rendern
BeitragVerfasst: Mo Feb 03, 2014 20:51 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
Ich brüte nun schon einige Tage über diesem Thema und habe das Netz mehrfach durchsucht.

Die meisten Beiträge, die ich zu dem Thema gefunden habe, stellen die gleiche Frage und bekommen häufig die Gleiche, wenig konstruktive, Antwort: Benutz doch den Immediate Mode...was einem natürlich kein Stück hilft, wenn man den deprecated Kram nicht mehr möchte.

Aber nun zu meinen Überlegungen:

1. Möglichkeit:
Für jedes GUI Element ein eigenes VBO. Im schlimmsten Fall also nur 4 Vertices, die irgendeine Textur irgendwohin malen.
Diese Lösung finde ich nicht sonderlich effizient. Ausserdem muss man sich noch darum kümmern, dass jedes Element ja variabel irgendwo gezeichnet werden kann und macht dadurch die Anwendung einer Matrix oder zumindest des Setzen eines Offsets mittels spezialisiertem Shader notwendig, sofern man für z.B. ein Button Element immer auf den gleich VBO zugreift.

2. Möglichkeit:
Alle Elemente (z.B. beschränkt auf ein Fenster, dass Buttons, Text, etc enthält) in ein VBO packen. Das reduziert zumindest die Drawcalls. Und das Fenster ließe sich sogar noch ohne großen Aufwand verschieben. Ist allerdings nicht sehr flexibel. Eine Änderung innerhalb der GUI, z.B. ein MouseHover-Effekt, führt natürlich dazu, dass das gesamte VBO aktualisiert werden muss.

3. Möglichkeit:
Alle Elemente wie beim Immediate Mode jeden Frame neu erstellen und zeichnen. Sehr flexibel. Evtl langsam. Zugegeben: Wahrscheinlich nicht langsamer als der Immediate Mode.

4. Möglichkeit:
Eine Mischung aus 2+3. Elemente in Gruppen zusammenfassen und eine clevere Update-Mechanik nutzen um nur die VBOs zu aktualisieren deren Elemente/Gruppen sich geändert haben.

Falls noch jemandem eine 5. Möglichkeit einfällt....:)

PS: zur Zeit nutze ich zum Rendern des Textes ein VBO, das groß genug ist um die Vertexdaten aller Buchstaben aufzunehmen. Dies wird in jedem Frame neu erstellt (GL_STREAM_DRAW). Da ich verhindern möchte, in jedem Frame ein neues Array zu erstellen, dass die Daten aufnimmt habe ich es größer gewählt. Hintergrund ist, dass ich dem Garbage Collector weniger Arbeit aufbrummen will.

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Mo Feb 03, 2014 21:46 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Ich arbeite auch seit einiger Zeit an einer GUI und möchte mit einer Kombination aus 1 & 2 arbeiten.
Erstmal nur 1 und wenn ich erste Analysen zur Performance in der Praxis gemacht habe, möchte ich GUI-Elemente in VBOs gruppieren. Entweder nur vollautomatisch, auf Basis von Heuristiken, oder mit Hinweisen in der GUI-Definition.
Extreme Lösungen wie 1 oder 2 isoliert sind zwar einfacher zu implementieren aber automatisch ineffizient.

Zitat:
Im schlimmsten Fall also nur 4 Vertices

Naja, idealerweise sollte man eine GUI heutzutage Vektor-basiert aufbauen.
Also deutlich mehr als 4 Vertices. Die Geometriebelastung der Grafikkarte bei der GUI wird vorraussichtlich eh verschwindend gering.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Di Feb 04, 2014 10:13 
Offline
Compliance Officer
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 460
Programmiersprache: C / C++ / Lua
Du kannst dir doch einen Pointer auf das VBO mappen lassen (glMapBuffer) und so wirklich nur Teile des VBO's ändern. Somit wäre meiner Meinung nach die zweite Methode die Beste.

_________________
offizieller DGL Compliance Beauftragter
Never run a changing system! (oder so)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Di Feb 04, 2014 13:45 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Das kann man zwar, ist aber trotzdem alleine keine gute Idee. Es kann zur Laufzeit die Geometriemenge variieren und beim entfernen von Geometrie werden "Löcher" in den effektiven Daten frei. Der Speicher fragmentiert also.
Außerdem skaliert es schlecht, weil zum Beispiel beim Vergrößern des VBOs immer mehr Daten kopiert werden müssen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Di Feb 04, 2014 17:06 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
damadmax hat geschrieben:
Falls noch jemandem eine 5. Möglichkeit einfällt....

Ja, meine Methode:

Die 2D-GUI-Formen in einer "Standard-Version" in ein VBO packen.
z.B für ein Viereck (Vertex/Normal/Tangent/Texcoord):

BuildVertex(-0.5,+0.5,0, 0,0,1, 1,0,0, 0,0); // Left Upper
BuildVertex(+0.5,+0.5,0, 0,0,1, 1,0,0, 1,0); // Right Upper
BuildVertex(+0.5,-0.5,0, 0,0,1, 1,0,0, 1,1); // Right Lower
BuildVertex(-0.5,-0.5,0, 0,0,1, 1,0,0, 0,1); // Left Lower

Die Y-Werte des Vertex sind verkehrt wegen der inversen Ortho-Projektion.

Dazu bräuchte man dann noch ein Indexfile, weil es ja zwei Dreiecke sein müssen.

Dieses VBO muss man nie wieder anrühren, wird auf die Grafikkarte geschickt und gut ist. Man kann natürlich auch noch mehrere Dinge dazupacken, z.b. ein paar wiederverwendbare Objekte wie Kugel und Zylinder. Sozusagen ein System-VBO :wink:


Für die 2D-Darstellung braucht man dann noch eine Matrix, die dafür sorgt, dass diese 2D-Formen an den vorgesehehen Platz verschoben werden. Diese Matrix kann man sich z.B. ganz einfach aus einer BoundingBox (Left/Top/Width/Height) basteln:

Code:
  1.    FillChar(LocalModelMatrix[0],SizeOf(TMatrix16F),0);
  2.  
  3.    With ABoundingBox Do
  4.    Begin
  5.       LocalModelMatrix[0,0].X:= Width;
  6.       LocalModelMatrix[0,1].Y:= Height;
  7.       LocalModelMatrix[0,2].Z:= 1;
  8.       LocalModelMatrix[0,3]:= Vector4F(Left+Width/2,Top+Height/2,0,1);
  9.    End;
  10.  
  11.  


Fehlen bloss noch Farben und Texturen.
Das war's schon.

Viele Grüße,
Traude


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Di Feb 04, 2014 18:17 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Dann hat man aber garantiert die maximale Anzahl Drawcalls.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Di Feb 04, 2014 19:17 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
Nicht unbedingt.

Stakkato-artiges auf die Tasten hauen passiert während des Spiels eher als beim Herumgustieren in der GUI, weil man sich hier (normalerweise) in Ruhe etwas aussuchen will, während das Spiel auf Pause geschaltet ist. Dadurch sind viel weniger Graphic-Updates nötig.

Zweitens kann man sich hier auch ein paar Optimierungen ausdenken; z.B.muss man nicht die ganze GUI neu zeichnen, wenn bloß ein Knopf gedrückt wurde. Da genügt es eben, nur diesen einen Knopf neu zu zeichnen.

Während der Spieler mit der GUI beschäftigt ist, langweilt sich die Grafikkarte meistens.


Noch einen Vorteil gibt es: Wenn man ein neues Projekt anfangen will, dann sind die GUI-Zeichenobjekte vom vorigen Objekt schon da. Es muss nur noch auf das neue "Look And Feel" angepasst werden, und das dauert nicht so lange und hat außerdem einen saftigen Spassfaktor.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Di Feb 04, 2014 19:56 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Die GUI ist aber normalerweise auch während des Spiels aktiv und frisst damit auch dann Performance.
Statische Optimierungen sehe ich auch nicht sinnvoll an. Eine moderne GUIs soll animiert sein können und grafische Effekte ermöglichen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Mi Feb 05, 2014 09:08 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Möglichkeit fünf: Die GUI nicht mit OpenGL, sondern mit einer spezialisierten Library rendern, das in eine Textur packen und die dann zeichnen. Braucht nur vier vertices :).

Das klingt vielleicht unperformant, ich fahre damit aber ziemlich gut. Ich nutze Cairo, und Cairo wird schon genau dafür verwendet. Der ganze GTK-Desktop wird mit Cairo gemalt. Dementsprechend brauchbar ist die lib auch. Cairo kann auch in einen rohen Buffer rendern, den man dann per glTex(Sub)Image2D an OpenGL weiterreichen kann. Der extrem große Vorteil ist, dass du damit auch libs wie Pango vor die Füße gelegt bekommst, und Pango ist genau das, was du willst, wenn du in irgendeiner Form mit Texteingaben zu tun hast. Pango kann den Text nicht nur zeichnen, sondern dich auch über die einzelnen Zeichen iterieren lassen¹, was für das editieren von Text gewissermaßen wichtig ist.

Bei dem VBO Ansatz mit einem oder wenigen Drawcalls möchte ich noch zu bedenken geben, dass die Z-Order von GUI-Elementen nicht-trivialen Einfluss auf die Zeichenreihenfolge hat. Besonders bei Scroll-Views gibts dann doch einigen Statechange der passieren muss (clipping mit scissors). Also alles in ein VBO packen und mit einem gl*Draw* zu rendern halte ich für unpraktikabel².

Mit Cairo ist es trivial, nur einen bestimmten Bereich des Puffers (Post zum Video) neu zu rendern (Rechteckige, pixel-alignte Clippingzonen beschleunigen das Rendern sogar, weil Cairo das wie glScissors optimiert). Das Rechteck lädt man dann noch neu auf die GPU hoch und zeichnet ein Fullscreen-Quad ⇒ done.

Natürlich unterstützt Cairo transparenz, sodass man teile der GUI transparent lassen kann (in dem Video ist der Hintergrund hinter dem Menü nicht mit cairo, sondern mit OpenGL gerendert (ja, dieser stumpfe blauton ;) ).

my three cents,
Horazont

1: wenn jemand denkt, Zeichen == Unicode-Codepoint oder noch viel schlimmer, Zeichen == element eines Strings, dann bitte ich Nachhilfe in Unicode zu nehmen, besonders bei Combining Characters.

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy 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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Mi Feb 05, 2014 14:13 
Offline
DGL Member
Benutzeravatar

Registriert: Di Okt 03, 2006 14:07
Beiträge: 1277
Wohnort: Wien
In Deinem Post über ManiacLab steht:
Lord Horazont hat geschrieben:
ps.: Hab mal nachgemessen: Die meiste Zeit verbringt ManiacLab tatsächlich damit, die Cairo-Surface in die Grafikkarte zu kippen. Das ist natürlich unschön, mal sehen ob's schneller wird, wenn ich nur die aktualisierten Teile neu übertrage.
Ich glaube schon. Du musst das Ding ja einmal rendern, dann zusammensetzen und anschließend nochmal als Textur zeichnen.



Ich habe jetzt bei mir Folgendes ausprobiert:

Ich habe ein Test-Fenster mit einem OpenGL-GUI-Stringgrid, welches 2 Scrollbalken hat. Das Fenster ist 768 x 512, mein Bildschirm ist 1280 x 800, und das Fenster bedeckt daher rd. 38% meines Bildschirms.

Damit Belastung entsteht, habe ich einen der beiden Scrollbalken rasch hin- und herbewegt, so stark, dass die Zahlen in Stringgrid kaum mehr zu lesen waren.

1. Die CPU-Belastung ging nicht über 14% hinaus. Einfach linear interpoliert auf meinen vollen Bildschirm wäre das 14/38*100 = rd. 40% CPU. Ist sicherlich nicht ganz wenig, aber eine solche (unsinnige) Überbelastung kommt unter normalen Umständen nicht vor.

2. Für die Grafikkarte habe ich nur das Nvidia-Settings-Programm mit der Thermo-Überwachung. Die Temperatur der Grafikkarte stieg durch das heftige Bewegen des Scrollbalkens von 32° auf 49°. Hier habe ich nicht viele Vergleichsmöglichkeiten, aber mir erscheint das ganz schön viel. Auf der Grafikkarte geht jedenfalls viel mehr ab als im Hauptspeicher.

Zuletzt habe ich in Gedit (der Ubuntu Text-Editor) das Experiment mit einem ähnlich großen Fenster wiederholt, und er bewirkt bei der CPU ungefähr den gleichen Effekt wie ich, hat aber eindeutig einen geringeren Temperaturanstieg bei der Grafikkarte, aber es war völlig unterschiedlich, mal kam er bis 49°, dann wieder nur bis 42°, da optimiert er offenbar was.


Irgendwie ist das natürlich auch Geschmacksache: ich versuche immer, möglichst keine Fremdbibliotheken zu nehmen. Für das Textrendering wäre eine spezialisierte Bibliothek natürlich besser. Andererseits sag ich dann immer: Sorry, Chinesen, so ist das nun mal. :wink:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Mi Feb 05, 2014 17:38 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Traude hat geschrieben:
In Deinem Post über ManiacLab steht:
Lord Horazont hat geschrieben:
ps.: Hab mal nachgemessen: Die meiste Zeit verbringt ManiacLab tatsächlich damit, die Cairo-Surface in die Grafikkarte zu kippen. Das ist natürlich unschön, mal sehen ob's schneller wird, wenn ich nur die aktualisierten Teile neu übertrage.
Ich glaube schon. Du musst das Ding ja einmal rendern, dann zusammensetzen und anschließend nochmal als Textur zeichnen.

Jupp, nach der Optimierung war das Bottleneck woanders (Python).

Traude hat geschrieben:
Irgendwie ist das natürlich auch Geschmacksache: ich versuche immer, möglichst keine Fremdbibliotheken zu nehmen. Für das Textrendering wäre eine spezialisierte Bibliothek natürlich besser. Andererseits sag ich dann immer: Sorry, Chinesen, so ist das nun mal. :wink:

Leider hat man das Problem schon viel früher, nämlich wenn man nicht-kanonische Darstellungen von è z.B. hat. Das kann man in Unicode als einen oder als zwei Codepoints darstellen. Ein primitiver Textrenderer wird es in der zwei-Codepoint-Form als `e oder e` darstellen, was natürlich blöd ist.

Aber ich kann das gut nachvollziehen, Textrendering wollte ich auch eine ganze Zeit lang selber machen … dann hat mich mein Perfektionismus und die doch limitierte Zeit dazu gezwungen, eine Lib zu nehmen ;)

grüße

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy 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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: GUI mittels VBO rendern
BeitragVerfasst: Mi Feb 05, 2014 22:52 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Aug 18, 2007 18:47
Beiträge: 694
Wohnort: Köln
Programmiersprache: Java
Das mit dem Text war jetzt nur ein Beispiel, wie ich den gerade rendere. Eben indem ich einfach das VBO komplett neu befülle.

Mir geht es vor allem um die GUI Elemente wie Buttons, Checkboxen oder ähnliches. Natürlich auch spezialisiertere Elemente wie eine Healthbar oder eine Minimap.

Ich habe mich jetzt für eine Container-Struktur (kann man das so nennen?) entschieden. Über dem Container gibt es Screens. z.b. Hauptmenü, IngameGUI, etc. Jeder Container managed einen VBO und reicht diesen weiter an alle ihm untergeordneten Elemente. Diese hauen ihre Vertexdaten da rein. Der Container macht das aber nur wenn sich an irgendeinem Element etwas geändert hat. Dann kann ich die Container gut skalieren. Elemente die sich kaum ändern werden in einen eigenen Container gepackt und gut. z.b. Alle Hintergründe für ein Menü in einen Container und alle Buttons in einen anderen.

Ich denke das wird erst mal reichen und sollte immer noch performanter als der Immediate Mode sein. Zur Not könnte ich später immer noch ein FBO in jeden Container einbauen.

fast offtopic: Wobei ich mich manchmal echt frage, wie Spiele wie z.B. SimCity ihre GUI zusammenbauen. Die ist ja schon teilweise recht massiv. Manchmal kann man aber merken, dass es irgendeine Art Cache gibt. Beim ersten öffnen eines Menüs dauert es meistens etwas länger bis dieses erscheint. Vielleicht nutzen die auch FBOs und rendern später nur noch die Elemente neu, die sich geändert haben? Wäre ja auch ein Ansatz...

_________________
Es werde Licht.
glEnable(GL_LIGHTING);
Und es ward Licht.


Zitat aus einem Java Buch: "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off"

on error goto next


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 12 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 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.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.050s | 17 Queries | GZIP : On ]