Ok, here is a test case. Let me know if you see something funny in the code… I am no expert.
This test case shows (at least on my machine) that it is not only text rendering that is slow. It is actually anything that is rendered using Java2D. As soon as it dips into any Graphics calls, things slow down considerably.
The program will create a TextureRenderer object. You can manipulate the size of the texture by altering the texW and texH fields. In the display method the TextureRenderer will get the Graphics2D object, clear the g2 background to blue, draw 200 white, randomly position circles in it and then use the resulting texture in a GL QUAD. You should see a blue quad with white dots in it, on a black background. In XP, as it should, the white dots flicker very fast. On OS X with the same config (ATI X1600), things are decidedly on the slow side.
thanks
package test;
import static javax.media.opengl.GL.GL_COLOR_BUFFER_BIT;
import static javax.media.opengl.GL.GL_DEPTH_BUFFER_BIT;
import static javax.media.opengl.GL.GL_MODELVIEW;
import static javax.media.opengl.GL.GL_PROJECTION;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
import com.sun.opengl.util.j2d.TextureRenderer;
import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureCoords;
/**
* Testing Graphics2D and TextureRenderer
* @author cmendoza
*
*/
public class TestCase extends GLCanvas implements GLEventListener {
protected GL gl;
protected GLU glu = new GLU();
protected int width, height;
protected String name;
TextureRenderer tr;
Texture texture;
int texW, texH;
private Object thisTime;
private long lastTime;
public TestCase(int width, int height, String name) {
super();
this.setSize(width, height);
this.width = width;
this.height = height;
this.name = name;
this.addGLEventListener(this);
//this is the size of the texture rendered with Java2D
texH = texW = 512;
tr = new TextureRenderer(texW, texH, false, false);
}
public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2) {
// TODO Auto-generated method stub
}
public void init(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
gl.glEnable(GL.GL_BLEND);
//gl.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE_MINUS_SRC_ALPHA);
gl.glBlendFunc(GL.GL_SRC_ALPHA,GL.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL.GL_SMOOTH);
gl.glEnable(GL.GL_POINT_SMOOTH);
gl.glHint(GL.GL_POINT_SMOOTH_HINT, GL.GL_NICEST);
gl.glEnable(GL.GL_LINE_SMOOTH);
gl.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_NICEST);
gl.glEnable(GL.GL_POLYGON_SMOOTH);
gl.glHint(GL.GL_POLYGON_SMOOTH_HINT, GL.GL_NICEST);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LESS);
gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
gl.glClearColor(0, 0, 0, 1);
texture = tr.getTexture();
}
public void reshape(GLAutoDrawable drawable,
int x, int y, int width, int height) {
gl = drawable.getGL();
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL_PROJECTION);
gl.glLoadIdentity();
double aspectRatio = (double)width / (double)height;
glu.gluPerspective(45.0, aspectRatio, 1f, 400.0);
gl.glMatrixMode(GL_MODELVIEW);
gl.glLoadIdentity();
}
public void display(GLAutoDrawable drawable) {
thisTime = System.currentTimeMillis() - lastTime;
lastTime = System.currentTimeMillis();
System.out.println("Frame time: " + thisTime );
gl = drawable.getGL();
gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0f, 0f, -5f);
Graphics2D g2 = tr.createGraphics();
g2.setColor(Color.WHITE);
g2.setBackground(Color.blue);
g2.clearRect(0, 0, texW, texH);
//to test Graphics2D I am drawing N circles randomly in the Graphics object
//this particular config gives me about 600ms per frame in OS X, but it is much quicker in XP (realtime in terms of animation)
for(int i = 0; i < 200; i++) { //try increasing the number of iterations to get a more dramatic result...
g2.fillOval(randomRange(0, texW), randomRange(0, texH), 20, 20);
}
g2.dispose();
tr.markDirty(0, 0, texW, texH);
texture = tr.getTexture();
texture.enable();
texture.bind();
TextureCoords coords = texture.getImageTexCoords();
float w = 1.5f;
//yeah, whatever...
float h = (float)texH / (float)texW;
h = h * w;
gl.glColor4f(1, 0, 0, 1);
gl.glBegin(GL.GL_QUADS);
gl.glTexCoord2f(coords.left(), coords.bottom());
gl.glVertex3f(-w, -h, 1);
gl.glTexCoord2f(coords.right(), coords.bottom());
gl.glVertex3f(w, -h, 1);
gl.glTexCoord2f(coords.right(), coords.top());
gl.glVertex3f(w, h, 1);
gl.glTexCoord2f(coords.left(), coords.top());
gl.glVertex3f(-w, h, 1);
gl.glEnd();
// texture.disable();
}
public int randomRange(int low, int high) {
if(low > high){
int temp = low;
low = high;
high = temp;
}
int ran = (int)(Math.random() * (high - low /*+1*/) + low);
//System.out.println("high was " + high + " low was " + low + " rand was " + ran);
return ran;
}
public void launch(){
Frame frame = new Frame(name);
frame.add(this);
frame.setSize(width, height);
frame.setLocationRelativeTo(null);
final com.sun.opengl.util.Animator animator =
new com.sun.opengl.util.Animator(this);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// Run this on another thread than the AWT event queue to
// make sure the call to Animator.stop() completes before
// exiting
new Thread(new Runnable() {
public void run() {
animator.stop();
System.exit(0);
}
}).start();
}
});
frame.setVisible(true);
animator.start();
}
public static void main(String[] args){
new TestCase(1024, 768, "test").launch();
}
}