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

Aktuelle Zeit: Fr Mär 29, 2024 11:45

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



Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Sa Jul 11, 2015 15:53 
Offline
DGL Member

Registriert: Di Aug 23, 2005 09:15
Beiträge: 31
Programmiersprache: FPC/Delphi XE3
(teilweise follow up zu viewtopic.php?f=2&t=11330 )

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?).

Weiß aber jemand eine bessere Lösung?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Sa Jul 11, 2015 16:43 
Offline
DGL Member
Benutzeravatar

Registriert: Di Apr 29, 2008 18:56
Beiträge: 1213
Programmiersprache: Delphi/FPC
Hey,

schonma die TextSuite2.0 angesehen? Die ist was die Textausgabe angeht wie dafür gemacht.

MfG Bergmann

_________________
Aktuelle Projekte: BumpMapGenerator, Massive Universe Online
Auf meiner Homepage gibt auch noch paar Projekte und Infos von mir.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Jul 12, 2015 18:15 
Offline
DGL Member
Benutzeravatar

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.
Code:
  1. float yoffset=abs(Index*GlyphWidth*0.5)*GlyphHeight;
  2. float xoffset=frac(Index*GlyphWidth*0.5)*2.0-1.0;

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
Code:
  1. float Seitenverhältnis = Breite / Höhe; float Reziproke = 1.0f/Seitenverhältnis;
  2. ...// Shader Konstante aktualisieren

Shader
Code:
  1. vec2 screenSpacePos = vec2(vertex.x*Reziproke,vertex.y);


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

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: So Jul 12, 2015 21:45 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Zitat:
Keine Matrix im Shader verwenden.

Wen man alles horizontal schreibt, so wie dieser Text hier wird das gehen, aber wen man im 3D-Raum schreiben will, wird dies wohl nicht mehr gehen.

Ich habe auch schon mit Text-Ausgabe gebastelt, es ging auch ohne Geo-Shader.

Code:
  1. #version 330  // Vertex-Shader
  2.  
  3. in vec3 inPos;
  4. in vec2 vertexUV0;
  5.  
  6. uniform mat4 Matrix;
  7. uniform float offset;
  8.  
  9. out vec2 UV;
  10.  
  11. void main(void)
  12. {
  13.   gl_Position = Matrix * vec4(inPos, 1.0);
  14.   UV = vertexUV0;
  15.   UV.x = UV.x + offset;
  16. }

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Jul 13, 2015 12:13 
Offline
DGL Member

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.


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


Wer ist online?

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.

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