2D fonts won't display - any help appreciated

Hey all!

I’m sure most of you hate getting 2D questions, but I’ve done searching for this topic, followed tutorials, etc, and I can’t seem to get it to work! I’m using the LWJGL conversion of NeHe’s tutorial #17 on Bitmap Fonts, but no dice. The 2D fonts just do not want to display on the screen!

Here’s the code for my BitmapFont class (it controls loading of the font and printing it):


package common.gui.font;

import common.gui.texture.*;

import java.awt.Color;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import java.awt.FontMetrics;

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.ByteOrder;

import org.lwjgl.opengl.GL11;

public class BitmapFont {

	private static final BitmapFont source = new BitmapFont();
	
	private static final Color OPAQUE_WHITE = new Color(0xFFFFFFFF, true);
	private static final Color TRANSPARENT_BLACK = new Color(0x00000000, true);
	
	/** The display list id, where each character to print to the screen
	 *  is added to this value.  For example, listBase+65 would be the character
	 *  'A'.*/
	private int listBase;
	/** The texture for this font */
	private Texture texture;
	/** The current font */
	private String currentFont = "Courier New";
	
	
	private BitmapFont() {
		init();
	}
	
	private void init() {
		buildFont();
		buildDisplayLists();
	}
	
	private void buildFont() {
		try {
			texture = TextureMgr.get().getTexture("res/Font.bmp");
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(0);
		}
	}
	
	private int testid;
	/**
	 * Create the display lists used for drawing characters to the screen.
	 */
	private void buildDisplayLists() {
		listBase = GL11.glGenLists(256); // Storage For 256 Characters
		testid = GL11.glGenLists(1);
		
		
		float x = (float)(texture.getWidth()/2);
		float y = (float)(texture.getHeight()/2);
		x = 2.0f;
		y = 2.0f;
		GL11.glNewList(testid, GL11.GL_COMPILE);
		texture.bind();
		GL11.glBegin(GL11.GL_QUADS);
			GL11.glTexCoord2f(1.0f, 0.0f);
			GL11.glVertex3f(x, -y, 0.0f);
			GL11.glTexCoord2f(1.0f, 1.0f);
			GL11.glVertex3f(x, y, 0.0f);
			GL11.glTexCoord2f(0.0f, 1.0f);
			GL11.glVertex3f(-x, y, 0.0f);
			GL11.glTexCoord2f(0.0f, 0.0f);
			GL11.glVertex3f(-x, -y, 0.0f);
		GL11.glEnd();
		GL11.glEndList();

        /* Generate the display lists.  One for each character in the standard/extended ASCII chart.
         */
        float textureDelta = 1.0f / 16.0f;
        for(int i=0;i<256;i++) {
            float u = ((float)(i % 16)) / 16.0f;
            float v = 1.f - (((float)(i / 16)) / 16.0f);
            GL11.glNewList(listBase + i, GL11.GL_COMPILE);
            texture.bind();
            GL11.glBegin(GL11.GL_QUADS);
                GL11.glTexCoord2f(u, v - textureDelta);
                GL11.glVertex3f(-0.0450f, -0.0450f, 0.0f);
                GL11.glTexCoord2f((u + textureDelta), v - textureDelta);
                GL11.glVertex3f(0.0450f, -0.0450f, 0.0f);
                GL11.glTexCoord2f((u + textureDelta), v);
                GL11.glVertex3f(0.0450f, 0.0450f, 0.0f);
                GL11.glTexCoord2f(u, v);
                GL11.glVertex3f(-0.0450f, 0.0450f, 0.0f);
            GL11.glEnd();
            GL11.glEndList();
        }
	}
	
	public static BitmapFont get() {
		return source;
	}
	
	/**
	 * Prepare OpenGL for Orthographic rendering.  The method will ensure that
	 * all states are saved.
	 */
	private void enterOrtho() {
		GL11.glDisable(GL11.GL_DEPTH_TEST);
		
		// Load the projection mode and save it's current state
		GL11.glMatrixMode(GL11.GL_PROJECTION); 
		GL11.glPushMatrix();
		GL11.glLoadIdentity();
		
		// Set up orthographic projection mode
		GL11.glOrtho(0, 800, 0, 600, -1, 1);
		
		// Enter model view mode
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		GL11.glPushMatrix();
		GL11.glLoadIdentity();
	}
	
	/**
	 * Leave Orthographic rendering in OpenGL.  Will restore all states saved
	 * by enterOrtho().
	 */
	private void leaveOrtho() {
		// Restore the state of the projection mode
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glPopMatrix();
		
		// Restore the state of the model view mode
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		GL11.glPopMatrix();
		GL11.glEnable(GL11.GL_DEPTH_TEST);
	}
	
	public void print(String msg, float x, float y) {
		enterOrtho();
		GL11.glTranslatef(x, y, 0.0f);
		
		// Ignore null value
		if (msg != null) {
			texture.bind();
			// Print the characters
			for(int i = 0; i < msg.length(); i++) {
				GL11.glCallList(listBase + msg.charAt(i));
				GL11.glTranslatef(1.0f, 0.0f, 0.0f);
            }			
		}
		leaveOrtho();	
	}
	
}


You might notice the TextureMgr.get().getTexture(“res/Font.bmp”); bit in there. I basically took the image loading code out of here and put it in another class to make it all nicer. Also, the Texture object here is basically a class to hold the width/height of the image used for the texture, and to hold the texture id generated by the OpenGL engine. The texture.bind() method just calls GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.id);, where this.id is the texture id given by OpenGL.

So basically, I call BitmapFont.get().print(“blah blah”, 100.0f, 100.0f); from some class, and it (should!) print the text to the display. But it doesn’t! And the weird thing about the above code is that, if I remove the enterOrtho() and leaveOrtho() methods, the text displays fine! (Albeit it doesn’t print using pixel coordinates, which I want!)

Does anyone have any idea what’s up here? I’m quite flustered at the moment. I decided to ask you guys for help before I threw my monitor out the window haha.

Thanks in advance!

ps: I thnk I’ve included all the relevant info, if not tho lemme know and I’ll give whatever you need!

Did you enable textures? Bound one? Set color to white? Checked the blending mode?

Yup, here’s the init code that readies OpenGL for me:


private void init() {
		// run through some based OpenGL capability settings. Textures
		// enabled, back face culling enabled, depth texting is on,
		GL11.glEnable(GL11.GL_TEXTURE_2D);
		GL11.glEnable(GL11.GL_CULL_FACE);
		// Enable hidden-surface removal
		GL11.glEnable(GL11.GL_DEPTH_TEST);
		GL11.glDepthFunc(GL11.GL_LEQUAL);
		GL11.glShadeModel(GL11.GL_SMOOTH); 
		
		// Set the clear color to Black
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
		// Set the depth to clear at
		GL11.glClearDepth(1.0f);
		
		// define the properties for the perspective of the scene
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();		
		GLU.gluPerspective(45.0f, ((float) 800) / ((float) 600), 0.1f, 100.0f);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		// Enable really nice perspective calculations
		GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
		// Enable line antialiasing
		GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST);
}

Not sure what you mean here…

Just added:


GL11.glColor3f(1.0f, 1.0f, 1.0f);

before the for loop that renders the characters, but no change.

After posting this code, I tried adding:


GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

before the for loop that rendered the characters, and then calling


GL11.glDisable(GL11.GL_BLEND);

after, but no dice. I also tried parameters (GL11.GL_SRC_ALPHA, GL11.GL_ONE) in the glBlendFunc to no avail.

Thanks for the post oNyx.

Not sure what you mean here…

Did you bind a texture? Well, I just listed the usual things which are usually forgotten.

Other than that… sometimes the things are simply not on screen or clipped away. Try orthographic projection.

Yes that’s exactly my problem, Orthographic projection isn’t work! gah!

And yes I have a texture bound.

Hi again!

I ended up finding code similar to mine that worked - looks like the problem was that my quads were built for a non-orthographic surface (they were iddy-bitty), so they didn’t display in Ortho mode! yeesh. I’m pretty sure I grew a few grays with this one.

Anywho, thanks for the help oNyx!