Text Rendering

Text rendering is necessary for just about every game. Text rendering is used for tasks ranging from in-game console windows used to execute commands and send text messages, displaying mission descriptions, and GUI component labels. There are different techniques for drawing text in a 3D window. One approach is to use images; another is to use textured polygons.

Bitmap Fonts

The glBitmap method can be used to set the value of each pixel to the current color. Unlike the well-known bitmap file format, an OpenGL bitmap is literally a bitmap, where each bit corresponds to a pixel and indicates only whether a pixel is on or off. The following code segment draws a 32 x 8 pixel square with a cutout center. Pixels that correspond to the “on” bits are set to the current color, and pixels that correspond to “off” bits are left alone.

byte[] bitmap = {      (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,       (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,      (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0xFF,      (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0xFF,      (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0xFF,       (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0xFF,      (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,      (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, }; gl.glRasterPos2i( 300, 300 ); gl.glBitmap(4*8, 8, 0, 0, 0, 0, bitmap);  

The first two parameters of glBitmap are the width and the height of the bitmap, and the last parameter is a reference to the bitmap data. Note that bitmaps are drawn to the current raster position. You must set the raster position accordingly, before using glBitmap.

To draw text, you can use a separate bitmap for each character. You can make each bitmap yourself, or use actual Java (or Windows) fonts to draw every character on a 2D context and then read the pixels to create the bitmaps. This can be done by using a rather simple and small external tool to create the bitmaps and saving them to a stream.

Alternatively, you can use the glutBitmapCharacter method, which has been exposed through the net.java.games.jogl.util.GLUT class. Even though it has only a few fonts with only a few different fixed sizes, it is just fine for getting something up quick. This method uses glBitmap to draw the characters, as explained earlier. The following segment uses glutBitmapString, which calls glutBitmapCharacter for every character. The text is drawn at the current raster position.

GLUT glut = new GLUT(); glut.glutBitmapString(gl, GLUT.BITMAP_TIMES_ROMAN_24,                             "Text using GLUT");

The problem with using glBitmap is that the text cannot be rotated, zoomed, or made transparent. The text does not look very nice because the edges are too crisp. In addition, each character can only have one color. You can use glDrawPixel to draw pixels as opposed to bits. When drawing, you can also enable blending so that the image blends with the screen contents.

Using Textures

Another technique is to use a textured geometry. The texture can be made in an art package and highly customized. For example, the you won message at the end of a fighting game can be made as a single texture. Just about every game uses this technique for some of its text. The main disadvantage of this technique is that it consumes a lot of texture memory. It also works only for static text or text that is not generated during runtime from the game data or user input.

To reduce texture memory consumption, instead of making a texture for every string, we can make a single texture that contains the entire alphabet. To draw the text, we can use quads that use the texture and have appropriate texture coordinates. The following method renders a string at the provided coordinates. The ID of the texture that contains the characters is passed in as an integer. The texture is assumed to be a square texture with 16 columns and 16 rows. The first character in the texture is assumed to be the space (or empty) character, which has the ASCII value of 32. In addition, the coordinate system is assumed to be set up as described in the previous section.

public void renderText(GL gl, int x, int y, String string,                        int fontTexture){     gl.glPushAttrib(GL.GL_CURRENT_BIT |                     GL.GL_COLOR_BUFFER_BIT);     gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);     gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE);     gl.glEnable(GL.GL_BLEND);     gl.glBindTexture(GL.GL_TEXTURE_2D, fontTexture);     for(int i=0; i<string.length(); i++){         float cxIndex = ((string.charAt(i)-32)%16)/16.0f;         float cyIndex = ((string.charAt(i)-32)/16)/16.0f;         gl.glBegin(GL.GL_QUADS);           gl.glTexCoord2f(cxIndex,1-cyIndex-0.0625f);              gl.glVertex3f(x, y+16,  0.0f);            // SW         gl.glTexCoord2f(cxIndex+0.0625f,1-cyIndex-0.0625f);         gl.glVertex3f(x+16, y+16,  0.0f);         // SE         gl.glTexCoord2f(cxIndex+0.0625f,1-cyIndex);          gl.glVertex3f(x+16, y,  0.0f);            // NE         gl.glTexCoord2f(cxIndex,1-cyIndex);           gl.glVertex3f(x, y,  0.0f);               // NW         gl.glEnd();         x += 16;     }     gl.glPopAttrib();        }

If the texture is 256 x 256, there will be a one-to-one mapping of texture pixels to screen pixels. Lower-resolution texture will result in the same size text with a lower quality. The texture can be generated from existing system fonts at some specific point size. If each character is 16 x 16 pixels, you can fit 256 characters in a 256 x 256 texture. Because you typically do not need a full character set for any given font, you can store multiple fonts in one texture. If you need to use variable-width fonts, you will have to keep track of the width of each character. You can create a Font class that stores the texture, character widths, and such information.



Practical Java Game Programming
Practical Java Game Programming (Charles River Media Game Development)
ISBN: 1584503262
EAN: 2147483647
Year: 2003
Pages: 171

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net