Jump to content
  • Advertisement
Sign in to follow this  
capn_midnight

[java] JOGL text rendering

This topic is 4535 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Okay, so rendering text is pretty shitty with the normal OpenGL calls. I've written a system to use Java2D, but it really bogs when user events occur (moving the window, dragging the mouse, etc). Other than using display lists, is there anything anyone else is using? here is the basic breakdown:
/*
 * Created on May 7, 2006
 *
 */
package testjogl;

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

import javax.media.opengl.GL;

import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureCoords;
import com.sun.opengl.util.texture.TextureIO;

public class TextLayer
{
    BufferedImage textLayer;
    Graphics2D    java2d;
    float         left, right, top, bottom;
    public TextLayer (int width, int height, float left, float right,
            float top, float bottom)
    {

        textLayer = new BufferedImage (width, height,
                BufferedImage.TYPE_INT_ARGB_PRE);
        java2d = (Graphics2D) textLayer.getGraphics ();
        this.left = left;
        this.right = right;
        this.top = top;
        this.bottom = bottom;
    }
    public void print (String output, float x, float y, Font font, Color color)
    {
        java2d.setColor (color);
        java2d.setFont (font);
        java2d.drawString (output, x, y);
    }
    public void flushText (GL gl)
    {
        Texture temp = TextureIO.newTexture (textLayer, false);
        java2d.setColor (new Color (0, 0, 0, 0));
        java2d.clearRect (0, 0, textLayer.getWidth (), textLayer.getHeight ());
        temp.enable ();
        temp.bind ();
        gl.glBegin (GL.GL_QUADS);

        TextureCoords tc = temp.getImageTexCoords ();
        gl.glTexCoord2f (tc.left (), tc.bottom ());
        gl.glVertex2f (left, bottom);
        gl.glTexCoord2f (tc.right (), tc.bottom ());
        gl.glVertex2f (right, bottom);
        gl.glTexCoord2f (tc.right (), tc.top ());
        gl.glVertex2f (right, top);
        gl.glTexCoord2f (tc.left (), tc.top ());
        gl.glVertex2f (left, top);

        gl.glEnd ();
        temp.disable ();
    }
}


The really slow method is the flushText method, and TextureIO.newTexture() call is the only heavy method in the bunch (try stepping through it once. There is waaay too much indirection). I have a sample app that calls it and makes 20fps on my p4 2.4ghz machine with a Radeon 9800 GPU. If I cut just the call to flushText (even leaving in the print calls, so still having the Java2D overhead), the avg FPS jumps to 2000+. [Edited by - capn_midnight on May 7, 2006 4:25:51 PM]

Share this post


Link to post
Share on other sites
Advertisement
haha, two things I've found:
1.) TYPE_3BYTE_BGR is the fastest BufferedImage type to use for the text layer. Unfortunately, the text layer will be completely opaque, you'll have to use some blending first.
2.) I wasn't disposing my textures. I was wondering why I was hitting a significant sluggish point (going from 60fps to 3fps) after ~900 frames.

Anyway, new version is up to 60FPS. The flushText method should only be called once per frame, and it's the slow part, so it shouldn't be too bad.


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

import javax.media.opengl.GL;

import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureCoords;
import com.sun.opengl.util.texture.TextureIO;

public class TextLayer
{
BufferedImage textLayer;
Graphics2D java2d;
float left, right, top, bottom;
/**
*
* Initializes a new instance of TextLayer
*
* @param width
* of the viewport
* @param height
* of the viewport
* @param left
* of the projection
* @param right
* of the projection
* @param top
* of the projection
* @param bottom
* of the projection
*/

public TextLayer (int width, int height, float left, float right,
float top, float bottom)
{

textLayer = new BufferedImage (width, height,
BufferedImage.TYPE_3BYTE_BGR);
java2d = (Graphics2D) textLayer.getGraphics ();
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
}
public void print (String output, float x, float y, Font font, Color color)
{
java2d.setColor (color);
java2d.setFont (font);
java2d.drawString (output, x, y);
}
public void flushText (GL gl)
{
Texture temp = TextureIO.newTexture (textLayer, false);
java2d.setColor (new Color (0, 0, 0, 0));
java2d.clearRect (0, 0, textLayer.getWidth (), textLayer.getHeight ());
temp.enable ();
temp.bind ();
gl.glBegin (GL.GL_QUADS);

TextureCoords tc = temp.getImageTexCoords ();
gl.glTexCoord2f (tc.left (), tc.bottom ());
gl.glVertex2f (left, bottom);
gl.glTexCoord2f (tc.right (), tc.bottom ());
gl.glVertex2f (right, bottom);
gl.glTexCoord2f (tc.right (), tc.top ());
gl.glVertex2f (right, top);
gl.glTexCoord2f (tc.left (), tc.top ());
gl.glVertex2f (left, top);

gl.glEnd ();
temp.disable ();
temp.dispose ();
}
}




Share this post


Link to post
Share on other sites
Your class should be a lot faster if you create the Texture object once and use Texture.updateSubImage() repeatedly to update its contents. The creation of the OpenGL texture object is the really expensive operation in your code.

Share this post


Link to post
Share on other sites
Okay, thanks. I'll see what I can make out of it. As for FengGUI, I don't know if that is something I'll be able to use or not. Part of the motivation for my work in JOGL is to be able to develop a commercial map rendering kit (top down, geographic maps, that is). I haven't done much work yet, but already I have something that is head and shoulders above the competition, performance-wise, so open source is not really an option.

Share this post


Link to post
Share on other sites
thank you for this useful function!

you say one could use blending to make it transparent. how exactly would one do this? thanks!

Share this post


Link to post
Share on other sites
Quote:
Original post by kbr
Your class should be a lot faster if you create the Texture object once and use Texture.updateSubImage() repeatedly to update its contents. The creation of the OpenGL texture object is the really expensive operation in your code.


Unfortunately, the really expensive operation is the creating of the opengl TextureData object, which is main parameter of the Texture.updateSubImage method. The difference between creating new Texture objects vs creating new TextureData objects is mostly negligible. Much better improvements will come from elliminating the full-screen BufferedImage for drawing the text, using just-large-enough BufferedImage objects for rendering the individual words, and include some clever caching of the volatile vs. static text (in this case, volatile text means it changes every frame).

But hey, it's a work in progress.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!