AGB  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi OpenGL - Text ausgeben mit TextSuite klappt nicht

OpenGL - Text ausgeben mit TextSuite klappt nicht

Ein Thema von fui-tak · begonnen am 3. Aug 2010 · letzter Beitrag vom 7. Sep 2010
Antwort Antwort
fui-tak

Registriert seit: 24. Okt 2008
117 Beiträge
 
Turbo Delphi für Win32
 
#1

OpenGL - Text ausgeben mit TextSuite klappt nicht

  Alt 3. Aug 2010, 18:57
Hi Leute,
ich versuche jetzt schon verzweifelt in meinem OpenGL Spiel Text anzuzeigen, aber keine Möglichkeit, die ich gefunden habe, scheint zu klappen.

Schließlich bin ich hier auf die TextSuite gestoßen. Und habe mich an diese Anleitung gehalten, aber dennoch bekomme ich keinen Text angezeigt.


Hier mal ein bisschen Code:


Diese Funktion rufe ich einmal auf, und zwar nach dem initialisieren von OpenGL:
Delphi-Quellcode:
procedure TKKOpenGL.textsuiteInitialisieren;
var failed:boolean;
begin
  failed := false;

  if tsInit(TS_INIT_TEXTSUITE) = TS_FALSE then
     failed := true;

  if tsInit(TS_INIT_OPENGL) = TS_FALSE then
     failed := true;

  if tsInit(TS_INIT_GDI) = TS_FALSE then
     failed := true;


  if failed then
    ShowMessage('Fehler beim textsuite erzeugen');

  tsContextCreate(@ContextID);
  tsSetParameteri(TS_RENDERER, TS_RENDERER_OPENGL);
  tsSetParameteri(TS_CREATOR, TS_CREATOR_GDI);


  tsFontCreateCreatorA('C:\WINDOWS\Fonts\verdana.ttf', 512, TS_STYLE_NORMAL, TS_DEFAULT, TS_DEFAULT, @FontID);
  //tsfontdestroy

 // tsFontBind(FontID);
 // tsSetParameteri(TS_ALIGN, TS_ALIGN_LEFT);
end;
Die Datei "C:\WINDOWS\Fonts\verdana.ttf" existiert; habe ich mittels FileExists(...) überprüft





Meine Textausgabefunktion:
Delphi-Quellcode:
procedure TKKOpenGL.schreibeText(text:string;x,y:integer);
begin
  glTranslatef(x, y, 50);
  tsTextOutA(PAnsiChar(text));
  glTranslatef(-x, -y, -50);
end;


Meine OpenGL Zeichenfunktion:
Delphi-Quellcode:
procedure TSpielverwalter.zeichne;
var ...
begin

  og.beginRender;//was vorher noch so getan werden muss, u.a. 2D Modus mit glOrtho
   ...

   og.zeichneBild(1,64,128,feldbreite,feldbreite,30);
   og.schreibeText('Hallo Welt',64,64);
   og.zeichneBild(2,64,296,feldbreite,feldbreite,30);

  og.endRender;//u.a. SwapBuffers(DC);
end;
Die Bilder werden Problemlos gezeichnet (glBegin(GL_QUADS); ...Vertexes setzen mit Texturen... glEnd; ),
aber von der Schrift sieht man nichts. Überdeckt von den Bildern ist sie auch nicht, da die Bilder als Tiefe 30 haben und die Schrift 50 haben müsste (glTranslatef(x, y, 50); )


Weiß jemand was ich falsch mache?

Geändert von fui-tak ( 3. Aug 2010 um 18:59 Uhr)
  Mit Zitat antworten Zitat
blackfin
(Gast)

n/a Beiträge
 
#2

AW: OpenGL - Text ausgeben mit TextSuite klappt nicht

  Alt 3. Aug 2010, 21:30
Ich kenne jetzt das TextSuite-Zeugs nicht, aber normalerweise gibt man über OpenGL Text ungefähr so aus:

Delphi-Quellcode:
var
  MyFont: HFONT;
  CharLists : GLuint ;
...
..
.
{
Displaylisten für 96 Zeichen generieren (Standard-ASCII-Zeichensatz 0-128).
Wir lassen aber die ersten 0-31 aus, da das eh nur Steuerzeichen sind,
und fangen beim Leerzeichen (#32) an (siehe weiter unten)
}

CharLists := glGenLists(96);

// Schrift erzeugen
MyFont := CreateFont(-12, // Höhe der Schrift (12 Punkt)
                     0, // Keine durchschnittliche Breite, brauchen wir hier nicht
                     0, // Escapement, brauchen wir hier nicht
                     0, // Orientation brauchen wir hier nicht
                     FW_NORMAL, // Schrift-Dicke (normal, bold, bla...)
                     0, // Kursiv? 0=nein, 1=ja
                     0, // Unterstrichen? 0=nein, 1=ja
                     0, // Durchgestrichen? 0=nein, 1=ja
                     ANSI_CHARSET, // Character Set
                     OUT_TT_PRECIS, // Standard-Präzision
                     CLIP_DEFAULT_PRECIS, // Standard-Clip-Präzision
                     ANTIALIASED_QUALITY, // Render-Qualität => Antialiased
                     FF_DONTCARE or DEFAULT_PITCH, // Pitch und Schrift-Familie (Standard)
                     'Verdana'                           // Name der Schrift(-datei)
);

// Schrift dem OGL-Rendering-Context zuweisen
SelectObject(ContextID,MyFont);

{
Nun die Bitmap-Font erzeugen (OpenGL Display-Listen mit den Zeichen füllen).
Und zwar hat die erste die ID 32, da wir ja die ersten 32 Zeichen übergehen.
Die Funktion holt sich die zuvor zugewiesene Schrift aus dem Device-Context und erzeugt daraus Bitmaps mit glBitmap-Befehlen.
Diese werden dann in den Displaylisten gespeichert. Somit hat man dann eine Bitmap-Font (Ein Bitmap pro Zeichen)
}

wglUseFontBitmaps(ContextID,32,96,CharLists);
   

...
..
.
// RENDERING-LOOP BEGIN
                                                       

// Der Text, der ausgegeben werden soll
myText := 'Hallo Welt!' ;

// Farbpuffer und Tiefenpuffer zurücksetzen
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);


// View zurücksetzen (Identitätsmatrix laden)
glLoadIdentity();   

// A bissl "rauszoomen", damit man auch was sieht
glTranslatef(0.0,0.0,-1);

// Schriftfarbe setzen (dieses mal ein freundliches weiss)
glColor3f(255,255,255);

 // Text in der Mitte des Viewports ausgeben (Achtung: Koordinaten gehen von -0.5 bis 0.5!)
glRasterPos2f(0,0);

// Displaylisten-Basis setzen
glPushAttrib(GL_LIST_BIT);

{
Die Basis der Liste hat die ID 96 (höchstes Zeichen) - 32 (niedrigstes Zeichen), so sagen wir OGL die Basis-ID,
um nicht doof rumrechnen zu müssen
}

glListBase(CharLists - 32);

{
Die Displaylisten für jeden Chararakter im Text aufrufen / Text rendern (endlich!)
Für jedes Zeichen im Text wird also die zuvor erzeugte Display-Liste mit der ID des Zeichen-Ordinalwertes aufgerufen.
Da die Displaylisten Bitmaps enthalten, wird also für jedes übergebene Zeichen das entsprechende Bitmap gerendert.
Die PChar-Umwandlung kommt uns hier zu Gute, da ein PChar ja ein "Zeichen-Array" ist.
}

glCallLists(Length(myText),GL_UNSIGNED_BYTE,Pchar(myText));


// Attribute zurückpoppen (hier: Displaylisten-Basis zurücksetzen)
glPopAttrib;

// RENDERING-LOOP ENDE

...
..
.
// Irgendwann später (beim Programm-Ende?) => Listen löschen
glDeleteLists(CharLists,96);

Geändert von blackfin ( 4. Aug 2010 um 10:52 Uhr)
  Mit Zitat antworten Zitat
fui-tak

Registriert seit: 24. Okt 2008
117 Beiträge
 
Turbo Delphi für Win32
 
#3

AW: OpenGL - Text ausgeben mit TextSuite klappt nicht

  Alt 6. Aug 2010, 21:22
hi, ich habe jetzt die Lösung von blackfin ausprobiert aber leider immer noch keinen Erfolg....

hier nochmal etwas mehr Code von mir:


Erzeugen:
Delphi-Quellcode:
function TKKOpenGL.init(pHandleUntergrund:THandle;pbreite,phoehe:integer):boolean;
begin
  Result := InitOpenGL;

  if not Result then
     exit;


  setLength(texturen,1);

  fensterBreite := pbreite;
  fensterHoehe := phoehe;
  aktuellesBild := -1;
  zoomFaktorX := 1;
  zoomFaktorY := 1;
  aktRotationsWinkel := 0;

  HandleUntergrund := pHandleUntergrund;
  DC:= GetDC(HandleUntergrund);

  RC:= CreateRenderingContext( DC,
                               [opDoubleBuffered],
                               32,
                               24,
                               0,0,0,
                               0);
  ActivateRenderingContext(DC, RC);

  

  glClearColor(0.3, 0.4, 0.7, 0.0); //Hintergrundfarbe: Hier ein leichtes Blau
  //glClearColor(0, 0, 0, 0.0); //Schwarz
  glEnable(GL_DEPTH_TEST); //Tiefentest aktivieren
  glDepthFunc(GL_LESS);//Neue Fragmente bestehen den Vergleich, wenn sie einen geringeren Tiefenwert haben.
  glEnable(GL_CULL_FACE); //Backface Culling aktivieren - Rückseiten werden nicht gerendert
  glCullFace(GL_BACK);

  glEnable(GL_ALPHA_TEST); //Transparenz
  glAlphaFunc(GL_GREATER, 0.1);//alles mit einem größeren Alphawert als 0.1 wird gerendert

  glEnable(GL_TEXTURE_2D); //Texturen zeichnen einschalten;


  textVorbereiten;
end;



procedure TKKOpenGL.textVorbereiten;
begin}
CharLists := glGenLists(96);

// Schrift erzeugen
MyFont := CreateFont(-12, // Höhe der Schrift (12 Punkt)
                     0, // Keine durchschnittliche Breite, brauchen wir hier nicht
                     0, // Escapement, brauchen wir hier nicht
                     0, // Orientation brauchen wir hier nicht
                     FW_NORMAL, // Schrift-Dicke (normal, bold, bla...)
                     0, // Kursiv? 0=nein, 1=ja
                     0, // Unterstrichen? 0=nein, 1=ja
                     0, // Durchgestrichen? 0=nein, 1=ja
                     ANSI_CHARSET, // Character Set
                     OUT_TT_PRECIS, // Standard-Präzision
                     CLIP_DEFAULT_PRECIS, // Standard-Clip-Präzision
                     ANTIALIASED_QUALITY, // Render-Qualität => Antialiased
                     FF_DONTCARE or DEFAULT_PITCH, // Pitch und Schrift-Familie (Standard)
                     'Verdana'                           // Name der Schrift(-datei)
);

SelectObject(ContextID,MyFont);

wglUseFontBitmaps(ContextID,32,96,CharLists);
end;


Renderprozedur:
Delphi-Quellcode:
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
 
  glOrtho(0,fensterBreite,0,fensterHoehe,NearClipping,FarClipping);//2D erstellen, http://wiki.delphigl.com/index.php/Tutorial_2D

  glMatrixMode(GL_MODELVIEW);

  glLoadIdentity;

  
  //hier male ich verschiedene Texturen, habe ich aber zu Testzwecken aus meinem Programm zurzeit entfernt

  
  //Text schreiben
  text := 'Hallo Welt';
  
  glTranslatef(0,0,-10);

  glColor3f(255,255,255);

  glRasterPos2f(0,0);

  glPushAttrib(GL_LIST_BIT);

  glListBase(CharLists - 32);

  glCallLists(Length(text),GL_UNSIGNED_BYTE,Pchar(text));

  glPopAttrib;


  SwapBuffers(DC);
Ich bekomme keine Fehlermeldungen, es wird einfach nicht angezeigt. Ich sehe nur den blauen Hintergrund von glClear

Hat jemand eine Idee?

Geändert von fui-tak ( 6. Aug 2010 um 21:25 Uhr)
  Mit Zitat antworten Zitat
blackfin
(Gast)

n/a Beiträge
 
#4

AW: OpenGL - Text ausgeben mit TextSuite klappt nicht

  Alt 9. Aug 2010, 09:37
Deine ContextID ist aber schon dein DC, oder?
Ansonsten, bitte poste mal die unit (evtl gestrippt) komplett, damit man auch sieht, in welchen Variablen was steht, so ist das ganze etwas zerrissen und man kann es nicht ganz verfolgen.
  Mit Zitat antworten Zitat
fui-tak

Registriert seit: 24. Okt 2008
117 Beiträge
 
Turbo Delphi für Win32
 
#5

AW: OpenGL - Text ausgeben mit TextSuite klappt nicht

  Alt 10. Aug 2010, 02:18
Deine ContextID ist aber schon dein DC, oder?
Ups... nein ist er nicht. Jetzt hab ich es geändert aber ich sehe immer noch keinen Text...

Ich hänge mal die beiden wichtigen Klassen an.

In SpielverwalterUnit ist für mein Problem die Methode "zeichne" wichtig. Alles was mit OpenGL zu tun hat ist dann in der Unit SpielOGLUnit2 zu finden (ein bisschen durcheinander, wegen der ganzen Rumprobiererei )
Angehängte Dateien
Dateityp: pas SpielOGLUnit2.pas (20,0 KB, 12x aufgerufen)
Dateityp: pas SpielverwalterUnit.pas (15,4 KB, 11x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von Lossy eX
Lossy eX

Registriert seit: 7. Aug 2007
113 Beiträge
 
#6

AW: OpenGL - Text ausgeben mit TextSuite klappt nicht

  Alt 11. Aug 2010, 10:05
Blackfin: Bitmaps fonts sind hoffnungslos veraltet, hässlich und langsam. Zur heutigen Zeit kann ich niemandem mehr empfehlen solche Texte zu benutzen.

fui-tak: Ich bin per Zufall gerade auf das Thema gestoßen. Normal bin ich nicht wirklich häufig hier unterwegs. Ich weiß nicht ob du die Lösung mit der TextSuite Bibliothek jetzt schon komplett verworfen hast oder nicht. Mir ist in deine Code aufgefallen, dass du ein Font mit der Größe 512 erstellst. Das ist doch ein bisschen arg groß. Vor allem wenn man bedenkt, dass die Zeichen dann eine Höhe von 512 Pixeln besitzen die benutzten Texture aber per default eine Größe von 256x256 haben. Mit anderen Worten. Aufgrund der viel zu großen Schriftgröße werden keine Buchstaben erstellt. Und wenn keine erstellt werden können auch keine dargestellt werden.

Ansonsten kann ich nur empfehlen auch das Faq "What should i do if it's dosn't work?" zu berücksichtigen. Also nach dem Initialisieren der Bibliothek auf Fehler prüfen. Wenn Fehler vorhanden sind, dann auch überprüfen in welchen Methoden die Fehler aufgetaucht sind.

Bei der TextSuite kommt noch hinzu, dass diese den Koordinatenursprung ObenLinks erwartet. Also wie das auf einer 2D Zeichenfläche so üblich ist. Wenn du jetzt aber mit einem Koordinatenursprung UntenLinks arbeitest kann es sein das der Text nicht da auftaucht wo du ihn erwartest. Er müsste auf dem Kopf stehen bzw im schlimmsten Fall je nachdem wie du dein OpenGL verändert hast ist es auch nicht auszuschließen, dass du die Rückseite des Textes siehst der durchaus aus ausgeblendet wird. Also das du nichts siehst obwohl alles funktioniert. Da im Zweifel mal GL_CULL_FACE deaktivieren.

PS: Nur für den Fall, dass du das noch mal probieren solltest. Die TextSuite arbeitet mit Texturen um die Schriften darzustellen. Beim Ausgeben von Text werden also anderen Texturen gebunden. Das heißt du darfst nach der TextAusgabe nicht erwarten, dass deine zuvor gebundene Textur immer noch aktiv ist.

PPS: Sowohl TexturFonts als auch BitmapFonts lassen sich durch deine OpenGL Einstellungen beeinflussen. Das soll bedeuten, wenn du typischerweise mit einem schwarzen Hintergrund arbeitest, irgendwann die Farbe Schwarz gesetzt hast und dann später Text ausgeben willst, dann wird sich diese Farbe auch auf den Text übertragen. Schwarz auf schwarzen Grund sieht man dann aber nicht. Genau so verhält es sich mit Texturen. Das letzte aktive Texel der noch aktiven Textur wird bei BitmapFonts auf die komplette Schrift gepackt. Oder Licht etc. Also alles was die Farben verändert verändert auch immer die Schrift.

Bei Bitmapfonts musst du im übrigen auch immer dafür sorgen, dass die RasterPos im Bild liegt. Sollte die obere Linke Ecke auch nur 1 pixel außerhalb des Bildes sein wird der komplette Text nicht mehr gezeichnet.
Ich habe ja keine Vorurteile gegenüber Autofahrern ... aber Fahrer von BMW und Mercedes bestätigen diese regelmäßig.
Außerdem neue technologische Errungenschaften: Serienmäßig eingebaute Rechtsfahrsperre und der stromsparende Blinker.
  Mit Zitat antworten Zitat
fui-tak

Registriert seit: 24. Okt 2008
117 Beiträge
 
Turbo Delphi für Win32
 
#7

AW: OpenGL - Text ausgeben mit TextSuite klappt nicht

  Alt 5. Sep 2010, 18:27
Hatte längere Zeit keine Zeit für mein Projekt, jetzt bin ich aber wieder dran. Deshalb hab ich so lange nicht geantwortet...

Und endlich sehe ich Schrift!!! Aber....

Ich habe jetzt die Anweisungen von Lossy eX befolgt, Schriftgröße heruntergeschraubt und das Backface Culling deaktiviert und jetzt habe ich Schrift, leider aber auf dem Kopf, wie schon vorausgesagt...

Was muss ich tun, damit diese richtig herum angezeigt wird und damit ich das Backface Culling wieder aktivieren kann?
  Mit Zitat antworten Zitat
Benutzerbild von Lossy eX
Lossy eX

Registriert seit: 7. Aug 2007
113 Beiträge
 
#8

AW: OpenGL - Text ausgeben mit TextSuite klappt nicht

  Alt 7. Sep 2010, 16:28
Bevor ich zu deinem Problem komme. Eigentlich alle OpenGL States kannst du auch temporär aktivieren. Also zum Beispiel kannst du Licht für einige Objekte aktivieren sonst aber komplett deaktiviert lassen. Genau so auch das Backface culling. Das kannst du explizit für 2-3 Objekte deaktivieren und sonst komplett aktiv lassen.

Mir persönlich ist es wichtig, dass man versteht warum etwas ist wie es ist. Dass der Text auf dem Kopf steht hat durchaus einen (hoffentlich) plausiblen Grund. Und zwar liegt das daran wie der Orthomodus aktiviert wurde. In OpenGL ist keineswegs vorgeschrieben mit welchen Werten glOrtho aufgerufen werden sollte. Der Schreiber des von dir verlinkten Tutorial arbeitet in 2D lieber mit dem Ursprung unten links. Ich persönlich empfinde es um ein vielfaches angenehmer mit einem Koordinatenursprung oben links zu arbeiten. Da ich sehr viel 2D arbeite (sowohl Windows als auch OpenGL). Mit einem Ursprung unten links muss man ständig so etwas wie ClientHeight - Position.Y rechnen. Das würde mit einem Ursprung oben links entfallen.

Du hast jetzt 2 mögliche Lösungen.
1) Wenn du den Ursprung oben links haben willst, dann genügt es bei glOrtho den dritten und vierten Parameter zu tauschen. Wenn du schon Dinge in 2D zeichnest musst du bei diesen aber die Y Positionen anpassen.

2) Wenn du den Ursprung unten links haben willst, dann musst du vor dem Zeichnen deines Textes die OpenGL Ansicht "verdrehen". Und zwar müssen wir dafür sorgen, dass die von der TextSuite übergebenen Y Werte negiert betrachtet werden. Dazu genügt es direkt vor dem Zeichnen ein "glScalef(1, -1, 1);" aufzurufen. Damit würden die in der Modelview Matrix gespeicherten Werte (für Y) negiert werden. Und schon sollte der Text auch mit backfaceculling richtig herum zu sehen sein.

Wichtig: Es ist wichtig, dass du das Scale nur direkt vor dem Zeichnen aufrufst. Denn ansonsten würde das Positionieren des Textes bereits negiert werden. Und damit sollte dein Text im nirvana landen. Dann ist der Text wieder verschwunden. Kleines Beispiel.
Delphi-Quellcode:
  glPushMatrix;
// glScalef(1, -1, 1); << Böse
    glTranslatef(ClientWidth div 2, 50, 0);
    glScalef(1, -1, 1); << Gut
    tsTextOutA('TextSuite Sample - Single Line');
  glPopMatrix;
Wenn du ohne Push- und PopMatrix arbeiten möchtest (was durchaus etwas an Leistung bringen dürfte), dann musst du nach der Textausgabe die Y Werte in der Modelview Matrix wiederherstellen. Also noch mal negieren damit sie wieder positiv werden.
Ich habe ja keine Vorurteile gegenüber Autofahrern ... aber Fahrer von BMW und Mercedes bestätigen diese regelmäßig.
Außerdem neue technologische Errungenschaften: Serienmäßig eingebaute Rechtsfahrsperre und der stromsparende Blinker.
  Mit Zitat antworten Zitat
fui-tak

Registriert seit: 24. Okt 2008
117 Beiträge
 
Turbo Delphi für Win32
 
#9

AW: OpenGL - Text ausgeben mit TextSuite klappt nicht

  Alt 7. Sep 2010, 17:35
Vielen Dank für die ausführlichen Erklärungen!!

Endlich funktioniert alles!
Ich habe die Möglichkeit Nummer 1 von dir genommen, also das Umdrehen der Y-Achse mittels Veränderung bei glOrtho, da ich ebenfalls einen Koordinatenursprung oben-links bevorzuge.


Für alle, die das gleiche Problem haben, hier noch etwas Code von mir:

Delphi-Quellcode:
procedure schreibeText(text:string;x,y:integer);
begin
  glTranslatef(x, y, 50);
  tsTextOutA(PAnsiChar(text));
  glTranslatef(-x, -y, -50);
end;


procedure render;
begin
  ...
  glOrtho(0,fensterBreite,fensterHoehe,0,NearClipping,FarClipping);
  ...
  schreibeText('Hallo Welt',128,64);
  ...
end;
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2014 by Daniel R. Wolf