Ich möchte gerne Text auf eine TMetaFile ähnliches Overlay über ein (Kamera-)Bild darstellen. Es kann sehr viel Kurztexte betreffen (Tausenden, je 10 Zeichnen oder so).
Heute verwende ich wglusebitmap Font, aber man muss da beliebig viel calllists generieren wenn man mehrere Groesse möchtet.
Es hat aber eine Eigenschaft der ich gern behalten möchte: beim Zoom bleibt das Font seine Große halten, also die bleiben lesbar.
Ich habe mich mit Signed Distance Fonts (SDF) beschäftigt auf Basis der Cinder Bibliotheken, und das fängt an zu funktionieren, und jetzt muss ich mehrere Texten, und die Zoom Eigenschaften implementieren. Einfache Texte funktionieren, aber noch nicht sehr schnell (700us reine Drawelements, alles zusammen 4ms, also alle Calls um gl_blend depthtest usw einzuschalten)
Das letzte ist auch der Frage, ich suche nach Ideen um mehrere Texten mit einen Array Renderen zu können (dürfen auch mehrere Arrays sein, nur nicht einer per Text) kann, und dann mit uniform anrufe Schalen
Auf Vertex ebenen s bestehen SDF' aus 4 vertices die mit 6 Indexen ein Rechtecke bilden (und dann noch Vertices mit die Koordinaten des Fonts im Font Bitmap enthalten).
Das Problem ist wenn ich zb ABCDEF habe, dann muss jede Vertex skaliert werden mit eine Factor relativ zum obere linker Ecke des A's.
Wenn ich aber im Array ABCDEFHIJKLMNOPQRST habe, aber ABCD und EFGH usw sind unterschiedliche Texte, muss zb von G jedes Punkt den Distance bis obere linken Ecke von E mit den Skalierungsfaktor
In Theorie konnte ich für Jedes Zeichen ein zweiten array mit Vertexen Hochladen die die Koordinaten des Erste Zeichnen jede Text enthält. Implementierung davon ist aber nicht einfach (wie wurde man so etwas machen?).
Registriert: Di Mai 18, 2004 16:45 Beiträge: 2621 Wohnort: Berlin
Programmiersprache: Go, C/C++
OpenGL 3(extension)-4 kann man z.B. Geometry Shader verwenden, man gibt dann einen 2D Punkt, 2Dskalierung und Textur Offset für ein Buchstaben an. 2D Skalierung und Offset sind statisch und können in ein ReadOnly Buffer gepackt werden und der 2D Punkt und ein Index sind dynamisch und können in ein Read/Write Buffer. Was also über den Bus läuft sind Updates auf den Index und Position. Der Shader generiert Quads mit entsprechender UV Coord an der richtigen Position.
SDF sollte man ohne blending rendern und discard im shader benutzen, damit fällt die teuerste Shader Unit Operation weg.
Monoblock Schriftarten haben auch Vorteile, da höhe und breite immer gleich sind braucht man keine Position mehr sondern kann die Geometry Shader ID benutzen, die für das erste Element 0 ist und dann hoch zählt. Dafür muss man dann aber einzelne Drawcalls für jeden Text Zeilenumbruch machen und ein y-offset halten. Normale Umbrüche innerhalb eines Satzes kann man ziemlich einfach im Shader layouten. Folgender Code funktioniert als auto layouting, wenn man ohne Matrix im -1 bis 1 Bereich arbeitet und bricht automatisch um, wenn es nicht mehr auf die aktuelle Zeile passt.
Sollte man Text irgendwo starten wollen, dann braucht man noch ein vec2 für den Offset im Screenspace für den Geometry Shader. Der Drawcall passiert auf ein Buffer, der die Buchstaben Indices enthält, da der rest über die Geometry Shader Instance ID geregelt wird.
Keine Matrix im Shader verwenden. Man kann UI ohne Matrix multiplikation machen, einfach auf der CPU das Seitenverhältnis ausrechnen und den reziproke an den shader geben. Dann kann man die entsprechende Seite, mit der Konstante multiplizieren und somit immer im -1 bis 1 Bereich sein UI positionieren. Dabei entfällt die Matrix multiplikation, alles ist Auflösungsunabhängig und Layouting wird einfacher, weil man nicht auf bestimmten Auflösungen arbeitet. C++ bei Resize Event
Speicher deine Font file als DXT3 oder equivalenten Kompressions Format, dass hilft bei Mobile und den schwachen Karten stark, weil der Cache besser ausgenutzt wird und deutlich weniger Zugriffe auf den Speicher passieren. Auf normalen PC Grakas bringt das eher nur Benchmark Technisch ein Unterschied, da der GDR5 RAM extrem Schnell ist und nicht wegen Akku runter Taktet.
Ich hab schon diverse Games gesehen, die die UI komplett von der Renderloop entkoppeln und mit eigener Frequenz und Rendertarget laufen lassen. Dabei haben z.B. die neuen DX12 Demos immer Native Auflösung und nur die normale Renderloop wird auf die vom User eingestellte Auflösung reduziert. Das geht auch ohne Swapchain Feature prima und da viele Games schon auf Middlewares wie Scaleform, Berilium, Iggy und ähnliches zurück greifen sind seperate rendertargets besser. Die laufen dann auch mit eigenen Update Zyklen und je nach UI wird da lange Zeit garnichts geupadted, weil keine Änderung passiert ist. Bei Scaleform geben default die abgespielten Flashszenen die Updatefrequenz an(5-24Hz).
Eine einfache Lösung wäre ein VBO mit Quads zu erstellen(z.B. mit (Auflösung.Breite/DurchschnittGlyphe.Breite)*(Auflösung.Höhe/DurchschnittGlyphe.Höhe) Quads) und dann die Positionen und UVs entsprechend des Textes zu updaten und das Update hoch zu laden. Die Draw Anweisung zeichnet dann nicht den ganzen Buffer sondern nur die Anzahl an Buchstaben. Die Wahrscheinlichkeit, dass der VBO nicht ausreicht ist gering und dann kannst ein OnDemand erstellen oder austauschen. So liegt das ganze Layouting auf CPU Seite, der VertexShader reicht ledeglich x,y,u und v weiter ohne irgendwelche Berechnungen und der FragmentShader macht das übliche bei SDF. Wenn möglich benutze die nicht blockierende Update Funktion, siehe Zero Driver Overhead Slides.
Benutze auf gar keine Fall Indices, das macht kein Sinn, weil nix geshared wird und benutze möglichst dicke Schriftarten, also möglichst Serifen meiden.
_________________ "Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren" Benjamin Franklin
Registriert: Di Aug 23, 2005 09:15 Beiträge: 31
Programmiersprache: FPC/Delphi XE3
TAK2004 hat geschrieben:
OpenGL 3(extension)-4 kann man z.B. Geometry Shader verwenden, man gibt dann einen 2D Punkt, 2Dskalierung und Textur Offset für ein Buchstaben an. 2D Skalierung und Offset sind statisch und können in ein ReadOnly Buffer gepackt werden und der 2D Punkt und ein Index sind dynamisch und können in ein Read/Write Buffer. Was also über den Bus läuft sind Updates auf den Index und Position.
Ich dachte schon an ein geometry shader, und etwas wie dies: - jede buchstabe hat zwei vertices und einen extra zahl/flag - vertices sind linksoben+rechtsunter. - zahl ist null fuer den ersten Buchstabe in ein Text, Vertex sind dann absoluter Koordinate. - zahl ist nicht null für spätere Buchstaben, und ihre Vertices sind dann relativ usw.
Das ist aber nicht sehr parallel zu verwalten, also man muss wahrscheinlich zwei Vertices (linksoben, rechtsunter heutige Buchstabe) + zwei Abstanden (bis linker obere Ecke der erster Buchstabe) in einen (Abstand) Vertex. zu packen.
Die Größe von den Buchstabe ist dann (rechts-links)*uniform und (unter-oben)*uniform, und Position x und y sind (linksoben+(Abstandsvertex-defaultschalung)*uniform)
Zitat:
SDF sollte man ohne blending rendern und discard im shader benutzen, damit fällt die teuerste Shader Unit Operation weg.
Wenn es dafür (SDF ohne Blend) ein Vorbild oder so gibt, dann mochte ich das gerne haben.
Zitat:
Monoblock Schriftarten haben auch Vorteile, da höhe und breite immer gleich sind braucht man keine Position mehr sondern kann die Geometry Shader ID benutzen, die für das erste Element 0 ist und dann hoch zählt.
Dafür muss man dann aber einzelne Drawcalls für jeden Text Zeilenumbruch machen und ein y-offset halten.
Das (mehrere Draw Calls) will ich unbedingt nicht. Wie gesagt, es konnte mehrere hunderte und eben tausende Texte geben, und ich möchte gern Pan und Zoom billig halten.
Zeilenbruch ist gar nicht nötig, und wird nicht implementiert. Es ist nur für Beischriften bei Objekte.
Zitat:
Keine Matrix im Shader verwenden. Man kann UI ohne Matrix multiplikation machen, einfach auf der CPU das Seitenverhältnis ausrechnen und den reziproke an den shader geben.
Ich habe kein UI in opengl, und es ist auch kein Spiel. Nur ein (Kamera-) Image mit ein Overlay in einer Industrie Applikation. (meistens gefüllte Rechtecke (bis hunderttausenden, siehe alter Thread), zehntausende kurze Linien, und vielleicht paar tausend andere Objekten. (Linie, offene Rechtecke, Zirkel ). Die Overlay ist Output des Vision analyse Algorithmus.
Die Bemerkung über Matrixen sind aber doch notiert, weil ich auch eine Bedürfnis an ein Image mit mehrere Subimages (mit eigene Zoom usw). Ist aber heute nicht der haupt Ziel.
Zitat:
Speicher deine Font file als DXT3 oder equivalenten Kompressions Format, dass hilft bei Mobile und den schwachen Karten stark, weil der Cache besser ausgenutzt wird und deutlich weniger Zugriffe auf den Speicher passieren. Auf normalen PC Grakas bringt das eher nur Benchmark Technisch ein Unterschied, da der GDR5 RAM extrem Schnell ist und nicht wegen Akku runter Taktet.
Mobile ist irrelevant fuer dieser Anwendung. Typisch Haswell oder AMD HD5450 (billigsten passive Karte) oder besser.
Zitat:
Eine einfache Lösung wäre ein VBO mit Quads zu erstellen(z.B. mit (Auflösung.Breite/DurchschnittGlyphe.Breite)*(Auflösung.Höhe/DurchschnittGlyphe.Höhe) Quads) und dann die Positionen und UVs entsprechend des Textes zu updaten und das Update hoch zu laden.
Texte werden nicht geupdate, es gibt nur pan und zoom, und ein Detail system womit man unterschiedliche Ebenen des Overlays ein und ausschalten kann.
Mitglieder in diesem Forum: 0 Mitglieder und 35 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.