# LWJGL - 2D Text über 3D Hintergrund



## tdc (6. Aug 2011)

Hi,

ich versuche zurzeit einen Timer in mein Spiel einzubauen. Die bisher benötigte Zeit in Sekunden soll mithilfe einer Font auf dem Bildschirm ausgegeben werden. Ich lasse bereits in der Mitte des Bildschirms mithilfe von OpenGL ein kleines Fadenkreuz zeichnen. Das funktioniert auch einwandtfrei, aber sobald ich den String mit der Font auf dem Bildschirm ausgeben lasse, fängt zumindest der 3D-Teil an, stark zu flackern.

Mein Code sieht bisher folgendermaßen aus:

```
...
	
	UnicodeFont timerfont;
	
	...
	
	public void initGame()
	{
		...
		timerfont = loadFont(25f); //selbstgeschriebene Methode... daran sollte es nicht liegen
		...
	}
	
	public void drawTimer()
	{
		timerfont.drawString(Display.getDisplayMode().getWidth()-80, 10, time+"", Color.white);
	}
	
	public void initOpenGL()
	{
		glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
		
        glShadeModel(GL_SMOOTH); // Enable Smooth Shading
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
        glClearDepth(1.0f); // Depth Buffer Setup
        glEnable(GL_DEPTH_TEST); // Enables Depth Testing
        glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do

        glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
        glLoadIdentity(); // Reset The Projection Matrix

        // Calculate The Aspect Ratio Of The Window
        GLU.gluPerspective(
                45.0f,
                (float) Display.getDisplayMode().getWidth() / (float) Display.getDisplayMode().getHeight(),
                0.1f,
                100.0f);
        glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix

        // Really Nice Perspective Calculations
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	}
	
	public void drawOpenGL()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);          // Clear The Screen And The Depth Buffer  
		
		//3D
        if(objects != null)
        {
        	for(GameObject obj:objects)
        	{
			//Objekte werden gezeichnet
        		obj.initDraw();
        		obj.drawOpenGL();
        		obj.endDraw();
        	}
        }
        
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        glOrtho(0,getWidth(),0,getHeight(),-1,1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        //2D
        drawInterface();              //zeichnet nur dieses "Fadenkreuz" OpenGL-2D-Zeichnungen funktionieren also
        //drawTimer();                <=== sobald // entfernt wird, flackert es
        
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
	}
	
	public void drawInterface()
	{
		glColor3f(0.3f, 0.3f, 0.3f);
        glBegin(GL_LINES);
       		glVertex2f(getWidth()/2-12, getHeight()/2);
       		glVertex2f(getWidth()/2+12, getHeight()/2);
        glEnd();
        glBegin(GL_LINES);
   			glVertex2f(getWidth()/2, getHeight()/2-12);
   			glVertex2f(getWidth()/2, getHeight()/2+12);
   		glEnd();
	}
	
	...
```

Die wichtigste Methode ist wohl drawOpenGL():

```
public void drawOpenGL()
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);          // Clear The Screen And The Depth Buffer  
		
		//3D
        if(objects != null)
        {
        	for(GameObject obj:objects)
        	{
        		obj.initDraw();
        		obj.drawOpenGL();
        		obj.endDraw();
        	}
        }
        
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        glOrtho(0,getWidth(),0,getHeight(),-1,1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        //2D
        drawInterface();
        //drawTimer();
        
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
	}
```

So funktioniert es, aber sobald ich die // vor "drawTimer()" entferne, fängt es an zu flackern.

Zum laden der Font verwende ich Slick. Slick ist ja eigentlich eine 2D-Library, aber ich zeichne die Font ja über die 3D-Szene, also sollte das ja kein Problem sein... oder? Und wenn es an Slick liegt, was könnte ich alternativ machen?


Ich hoffe ihr könnt mir weiterhelfen,
mfg tdc


----------



## Evil-Devil (7. Aug 2011)

Du weißt das es für SLICK eine eigene TTF Zeichen Klasse gibt?
Slick-Util Library - Part 3 - TrueType Fonts for LWJGL - LWJGL

Bei deinem Code wäre interessant zu wissen wie du den Timer zeichnest. Denn bereits in deinem Interface wechselst du, sofern nicht gewollt, nicht in den 2D Ortho Modus.


----------



## tdc (7. Aug 2011)

Wie ich den Timer zeichne sieht man doch:

```
timerfont.drawString(Display.getDisplayMode().getWidth()-80, 10, time+"", Color.white);
```
Und das ist doch genau so, wie auf der Seite, von der du mir den Link geschickt hast.

Auch das Laden der Font mache ich mit Slick genau so, wie in dem Link (daher hab ich das ja) und in meinem Menü funktioniert es bereits. Nur das zeichnen über die 3D-Szene klappt noch nicht.

Aber in den Ortho-Modus wechsele ich doch (erster Codeblock Zeile 63):

```
glOrtho(0,getWidth(),0,getHeight(),-1,1);
```

Oder verstehe ich da etwas falsch?


----------



## TimoH. (7. Aug 2011)

Es könnte eventuell das selbe Problem sein das ich hatte (war bei mir zwar in einer reinen 2D Umgebung): Versuche mal bevor du den Timer-String zeichnest die letzte Textur zu lösen (unbind). 
	
	
	
	





```
org.newdawn.slick.opengl.TextureImpl.bindNone();
        font.drawString(x, y, text,c);
```
 verwende ich dafür. Vlt. funktioniert es ja.


----------



## tdc (7. Aug 2011)

Das funktioniert leider auch nicht... ich benutze bisher auch noch gar keine Texturen in meiner 3D-Umgebung, sondern nur farbige Formen/Körper.


----------



## Evil-Devil (7. Aug 2011)

Wenn du keine Texturen nutzt, wie stellst du dann den Timer dar?

Hast du sonst vllt. eine binär Version zum ausprobieren? Vielleicht zuckelt das nur auf deinem Rechner.


----------



## tdc (7. Aug 2011)

Also den Timer mache ich über UnicodeFont von Slick... (ja, ok, da wird es vllt. mit einer Textur gemacht, aber ich benutze bisher keine eigenen Texturen)

Eine ausführbare *.jar habe ich zurzeit nicht, aber ich kann versuchen in den nächsten Tagen mal eine Version hochzuladen (hab jetzt leider keine Zeit).

An meinem PC sollte es eigentlich nicht liegen, wenn dann könnte es noch irgendwie an Ubuntu liegen aber Hardwaretechnisch habe ich einen recht aktuellen PC. 

Im Anhang aber mal 2 Screenshots. Das erste ist ein Screenshot ohne der Methode "drawTimer()" und das zweite mit dieser Methode.

Edit: Der Timer ist irgendwie auch falsch herum und sollte oben rechts sein... stimmt vllt. was mit meiner glOrtho() nicht?


----------



## tdc (10. Aug 2011)

Problem gelöst! 


```
public void drawTimer()
	{
		timerfont.drawString(Display.getDisplayMode().getWidth()-80, 10, time+"", Color.white);
		TextureImpl.bindNone();
	}
```

Mit TextureImpl.bindNone(); funktioniert es plötzlich. Obwohl ich gar keine Texturen verwende lag es wohl daran.

Edit: Oh, ich sehe gerade, dass es ungefähr das ist, was Timo H. vorgeschlagen hat... nur irgendwie muss es danach und nicht davor stehen.
(Mist, mit ein wenig herumprobieren hätte ich mir einiges an Zeit sparen können...)


----------

