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

Aktuelle Zeit: Mi Sep 19, 2018 11:41

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



Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: TextSuite [2.0] Bugs
BeitragVerfasst: Di Jan 17, 2017 15:20 
Offline
DGL Member

Registriert: Mo Jul 17, 2006 13:16
Beiträge: 60
Hallihallo!

Zunächst vielenvielen Dank an LossyEx und Bergmann89 für das Erstellen bzw. Pflegen der TextSuite für OpenGL. Saubere Arbeit!

Beim konkreten Arbeiten damit sind mit einige wenige Bugs aufgefallen, wovon zumindest einer Stark störend ist. Siehe Anhang:

Generell:
Die "Unterstreichen"-Linie ist bei großen Schriftarten zu dünn, bzw. wächst in der Breite nicht mit der Größe der Schriftart.

1.png, Unkritisch:
TtsPostProcessorShadow verschiebt bei großen Offset-Werten die Buchstaben und Schatten außerhalb ihrer Boxen und schneidet sie ab. Die Unterstrich-Linie wird unterbrochen. Da sooo große Werte unwahrscheinlich sind, ist dieser Punkt eigentlich zu vernachlässigen.

2.png, "Kritisch"
TtsPostProcessorBorder: Die "Unterstreichen"-Linie wird nach jedem Buchstaben unterbrochen (senkrechter Strich).

3.png, Unkritisch:
TtsPostProcessorBorder: Die halbtransparente Rahmenlinien werden bei Überlappung im Alphawert addiert; sieht komisch aus. Die Rahmen-Farbe ist additiv(?), was falsch ist, wenn man z.B. schwarzen Text weiß umranden möchte. Das geht nicht!
Außerdem: Das Alpha des TtsPostProcessorBorder wirkt sich auf das gesamte Objekt aus, also auch die Schrift, Schatten, etc.


Speziell zu 2.:
Mir ist klar, dass die Wörter buchstabenweise gerendert werden, und es deshalb besonders schwer ist, den Rahmen-PostProcessor so anzupassen, dass er das ganze Wort (bzw. es muss ja die ganze Zeile sein!) auf einmal verarbeitet.

Ich habe schon überlegt, mit dem "Fill"-PostProcessor nach dem Zeichnen des Rahmens und des Schattens den eigentlichen Text noch einmal einfach drauf zu Zeichnen, leider ist der Rahmen innerhalb der Buchstaben gezeichnet (also nicht außerhalb) und wird beim erneuten Zeichnen also komplett weggelöscht.

Hat hierzu jemand eine Idee?


Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: TextSuite [2.0] Bugs
BeitragVerfasst: Di Jan 17, 2017 18:22 
Offline
DGL Member
Benutzeravatar

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

1 ist ein Bug, den hab ich auch schon gefixt. Aktueller Stand liegt bei uns im Repo.

2 und 3 sind nicht ganz so einfach zu lösen. Das PostProcessing wird immer genau für ein Glyph angewendet. Wenn du also eine Border um das Glyph ziehst und dann mehere Glyphen renderst, dann überlagern sich natürlich auch die Borders.
3 kommt durch einfaches Blending zu stande. Zwei halbtransparente Objekte, die aufeinander geblendet werden verhalten sich immer so. Das lässt sich beheben indem du den Text ohne Blending in ein FBO zeichnest und dann das FBO mit Blending dahin wo der Text stehen soll.
2 liegt wie schon gesagt am PostProcessing der einzelnen Glypen. Das könntest du umgehen indem du wieder dein Text (ohne Border) in ein FBO renderst, dann im FBO durch PostProcessing die Border wieder ran zeichnest und dann wieder den Inhalt des FBOs ausgibst.

Das kann ich dir auch nich so ohne weiteres in der TextSuite fixen, weil die TextSuite da durch ihren Aufbau und ihre Umsetzung keine Möglichkeit offen lässt das Problem anzugehen. Die TextSuite hat nur einen Blink auf einzelne Glyphen, dein Problem lässt sich aber nur lösen wenn man den Text kennt...

LG

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


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: TextSuite [2.0] Bugs
BeitragVerfasst: Fr Jan 20, 2017 11:45 
Offline
DGL Member

Registriert: Mo Jul 17, 2006 13:16
Beiträge: 60
Danke schonmal für die Antworte und den schnellen Patch.

Ich hätte auch konkrete Patches für dich. Ich hab Git nicht installiert und k.a. wie das geht, deshalb hier "manuell":

utsImage, Zeile 64+65: Delphi braucht unbedingt "overload", weil der Prozedurname doppelt ist.
Code:
  1.     procedure Blend(const aImage: TtsImage; const X, Y: Integer; const aFunc: TtsBlendColorFunc); overload;
  2.     procedure Blend(const aImage: TtsImage; const X, Y: Integer; const aFunc: TtsImageBlendFunc; const aArgs: Pointer); overload;
  3.  


Fehler: Wenn der Textschatten (größere) negative X werte hat (Y = 0), wandert der komplette Text nach Oben
utsPostProcessor, Zeile 586: Sicherlich sollte hier "+ tmpY" gemeint sein?
Code:
  1.  
  2.     m.GlyphOrigin.y    := m.GlyphOrigin.y + tmpX;
  3.  




Ich habe hier aktuell das Problem, dass mir
Code:
  1. block := tsRenderer.BeginBlock(Left, Top, Self.Width, Self.Height, [tsBlockFlagWordWrap]);
  2.       block.TextOutW(PWidechar(Self.Text));
  3.  

um die Ohren fliegt, wenn ich [zu viele] Schriften erzeugt habe. Bei den "neueren" Schriften können dann nicht für alle Zeichen die Bitmaps zwischengespeichert werden. Interessanterweise variiert die Anzahl der möglichen Schriften zwischen 20 und ~100, je nachdem, wie "oft" ich diverse Komponenten erstelle (dazu komme ich gleich). Leider hast Du für die Objektorientierung der Textsuite auch noch andere Teile von OpenGL als Objektorientiert vorausgesetzt, was sich ggf. mit meiner bisherigen prozeduralen Programmierung mit der dglOpenGL beißt. Dort habe ich zwar auch deinen Render- und Device-Context, weiß aber nicht, wie ich das korrekt an die TextSuite koppel.

Ursprünglich wollte ich eine zentrale komponente machen, die alle benötigten Schriften erzeugt und vorhält: somit wäre z.B. nur ein tsContext und tsRenderer erforderlich. Dann ist aber nach 20 Schriften Schluss. Wenn ich nun für jede Schriftart einen eigenen Context, Renderer und tsFontCreatorGDI erzeuge, komme ich auf bis zu 100 Schriften.

Da ich nicht im Voraus weiß, wie viele verschiedene Schriften der Benutzer später auf einem gerenderten Frame haben möchte -oder wieviel sein PC verkraftet?-, bin ich hier ein wenig beunruhigt. Wenn ich eine neue Schrift erzeugen will läuft das dann irgendwie ins Leere, bzw. nur manche Buchstaben der Schrift können generiert werden, so das aus einem sinnvollen Satz bei der Textausgabe z.B. aus "Lorem Impsum" "___I___" wird (die "Unterstriche" kann er noch rendern, und das "I", weil die Textur klein ist, den Rest nicht"). Der RAM ist nicht voll (~80 MB), es kann aber sein, dass der Graphikspeicher für die Texturen aber voll ist. Wie kann man das prüfen?

Es wird wohl nicht sinnvoll sein, nach jedem Frame bzw. nach jedem Text die Schriftarten freigeben zu lassen und für jedes Wort neu zu erzeugen, weil ich dann ggf. nicht mehr auf 60 FPS komme?

Wie ist das denn bei Dir angedacht, wenn man z.B. 5 (TtsFont) Schriftarten hat. Wie viele
-TtsContext
-TtsRendererOpenGL
-TtsFontCreatorGDI
brauche ich insgesamt, und wann dürfen diese frühestens freigegeben werden? Ich hatte z.B. versucht

Code:
  1.  
  2.   tsCreate := TtsFontCreatorGDI.Create(ftsContext);
  3.   FtsFont := tsCreate.GetFontByFile(pAnsiChar(ansistring(tmpFontFileName)), abs(Font.Height), tmpStyle, tsAANormal);
  4.   FreeAndNil(tsCreate);
  5.  


aber dann ging des Text später nicht rendern, also muss der wohl bis zum Ende bestehen bleiben?

---

Im Endprodukt wird es wohl eh nur auf ~5 verschiedene Schriften gleichzeitig hinauslaufen, und unbenutzte Schriften kann man ja auch nach ein paar Sekunden freigeben. Dennoch würde ich es gerne "ordentlich" verwalten.

Gibt es eine einfache Möglichkeit den TtsPostProcessorBorder so umzustellen, dass er nicht "blendet" sondern solide zeichnet?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: TextSuite [2.0] Bugs
BeitragVerfasst: Fr Jan 20, 2017 14:25 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Slightly Off-Topic: Aber wenn du so dynamische Anforderungen an die Schriften hast, würde ich an deiner Stelle in Betracht ziehen, den Text vollständig in Software und auf der CPU in eine Textur zu rendern und dann im ganzen auf ein Quad zu knallen, ganz ohne Text Suite. Das sollte problemlos schnell genug werden und braucht nicht unmengen an VRAM für Glyphen die vielleicht nur ein paar mal gebraucht werden.

viele Grüße,
Horazont

_________________
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  
BeitragVerfasst: Di Jul 10, 2018 10:47 
Offline
DGL Member

Registriert: Mo Jul 17, 2006 13:16
Beiträge: 60
Lessons learned für die Nachwelt:
Moin, ich poste nochmal schnell hier hintendran, weil es sich nicht lohnt, dafür ein eigenes Thema aufzumachen:

Code:
  1. function TtsFontCreatorGDI.GetFontByName(const aFontname: String; const aSize: Integer; const aStyle: TtsFontStyles; const aAntiAliasing: TtsAntiAliasing): TtsFont;


Ich musste mit einigem Aufwand zu folgender Erkenntnis gelagen:
TextSuite (Font-)Size <> Windows.Font.Size
und
TextSuite (Font-)Size = Windows.Font.Height

Hintergrund:
Ich (Kunde) gebe ein Rechteck vor, in dem ein Wort/Satz möglichst groß dargestellt werden soll, max. Schriftgröße 72. Ich erstelle zur Schriftgrößenberechnung ein TBitmap, und mit tmpBitmap.Canvas.TextWidth lasse ich mir für meinen Text die Breite zurückgeben (natürlich für die passende Schrift, mit der Schriftgröße, die gerade getestet wird, Höhe ignorieren wir mal in diesem Beispiel). Der Wert für das Wort "Montag" ist mit Arial Größe 34 bei Canvas.TextWidth exakt 150px, bei TextSuite über block.GetTextWidthW(PWidechar('Montag')) kommen ~110px raus. Ich wundere mich die ganze Zeit, warum mit Schriftgröße 34 das 150px breite Feld nicht ausgefüllt ist...

Hinweis: Das "durchprobieren" verschiedener Schriftgrößen (von 72 in 2er-Schritten runter auf bis zu 6, für verschiedene Schriftarten und Formatierungen) ist mit TextSuite nicht nur sehr langsam (Textblock erzeugen, Text berechnen und Block abbrechen, erzeugen der neuen Schriftart), sondern verursacht auch das in anderen Threads erwähnte Problem, dass aber einer gewissen Menge erzeugter Schriften mit Textsuite Fehler auftreten (Buchstaben können nicht mehr gerendert werden etc.). Deshalb verwende ich die Methode mit dem Windows-Canvas. Bessere Ideen willkommen, aber ich glaube von der Performance unschlagbar?

Dateianhang:
Arial34_Windows.png
Dateianhang:
Arial34_TextSuite.png


Meine Vermutung wurde bestätigt, dass TextSuite sich bei dem Parameter "(Font)Size" auf die absolute Pixelhöhe der Schrift bezieht, und nicht die "Windows-übliche" Schriftgrößenangabe:
Code:
  1. FtsFont := tsCreate.GetFontByFile(pAnsiChar(ansistring(tmpFontFileName)), MeineFontSettings.FontSize, MeinStyle, tsAANormal);

Zugegeben: Für wahrscheinlich alle Anwendungen (außer meiner, weil ich mich nach den Benutzervorgaben "die-und-die Schrift in der-und-der Größe") ist diese Angabe auch wesentlich sinnvoller als die recht "abstrakte" Windows-Schriftgrößenangabe, die ja dazu noch Geräteabhängig ist (wegen DPI und so weiter).

Das "Problem" konnte ich nun für mich so lösen, indem ich entsprechend der Delphi-Hilfe FontSize in FontHeight umgewandelt habe:
Zitat:
Mit folgender Formel kann der Wert der Eigenschaft Height aus der Punktgröße ermittelt werden:

Font.Height = -Font.Size * Font.PixelsPerInch / 72

ergibt:
Code:
  1.   FtsFont := tsCreate.GetFontByFile(pAnsiChar(ansistring(tmpFontFileName)), round(abs(MeineFontSettings.FontSize) * 96/72), MeinStyle, tsAANormal);
  2.  

Somit werden die TextSuite-Schriften nun durch die Multiplikation von 96/72 in der "Windows-Schriftgröße" erzeugt.
Hinweis: die "96" PixelsPerInch sind meines Wissens der Standardwert für alle Bildschirme unter Windows, wenn die Schriftgröße in der Systemsteuerung auf 100% gesetzt ist. Zur korrekten Darstellung mit meinem Programm haben wir an die Kunden kommuniziert, dass der Zoomfaktor auf 100% stehen muss (jaja, wird mal irgendwann angepasst; es betrifft halt nicht nur Schriften sondern auch Alles andere), deshalb "erlaube" ich es mir, an dieser Stelle mit diesem statischen Wert zu arbeiten, damit es wirklich bei allen Kunden/Bildschirmen gleich aussieht.

@Bergmann89: Ich würde mir wünschen, dass der Parameter aSize von GetFontByName umbenannt wird, um solche Mißverständnisse für andere Leute (und mich in der Zukunft :lol: ) zu vermeiden. Vielleicht wären aFontHeight oder aSizeInPX bessere Namen? Naja egal, jetzt weiß ich es ja; es muss ja nicht jeder so verpeilt sein, wie ich. Wie immer: auf jeden Fall vielen Dank für das Weiterbetreiben der TextSuite, und natürlich auch danke an @LossyX für die ursprüngliche Fassung!

Schlagwörter:
TextSuite falsche Schriftgröße, FontSize, FontHeight, TextWidth, TextExtend


Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.


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 2 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.015s | 15 Queries | GZIP : On ]