Just been fiddling with a JOGL testcase that uses glLockArraysEXT and glDrawElements for a geometry discretized by indexed triangle strips. On a AMD 3000+, 6600GT 128MB, 2x512 MB PDP XBLK rig I get about 40FPS with the CPU at stock 1.8GHz and 50FPS with the CPU oc-ed to 2.2GHz. Based on the corresponding numbers using Java 3D (though it actually picks up glMultiDrawElementsEXT in my gfx config), something appears awry…may be with my jogl code ! Would like someone to check it out if possible, please. I’m looking at per-frame performance and not at the initial cost of setting up the buffers etc.
The geometry consists of nk = 101 square planes in the k-/z-dir. Each square plane is discretized by square cells with ni = 51 vertices in the i-/x-dir and nj = 51 vertices in the j-/y-dir. The strips are oriented along the i-dir, i.e., each j = constant row is a strip. There are (51 - 1) x 101 strips; each strip has 2 x ni = 102 vertices comprising 100 tris. Hope I got these right…!
The JOGL version that I used is one of the recent jsr231 daily builds I believe…! The files Main.java, ITSAEventHandler.java, and ITSA.java are below:
Main.java
/*
* Test Case P7: IndexedTriangleStripArray
* Geometry: C9/split
* Date: Jan 05, '06
* Author: N. Vaidya
* Notes:
* JOGL uses glLockArraysEXT and glDrawElements
* Java 3D equivalent is GeomPerf.java, ITSAVisual.java
* Java 3D uses glMultidDrawElementsEXT, glLockArraysEXT
*
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.media.opengl.*;
import com.sun.opengl.utils.*;
public class Main {
public static void main( String[] args ) {
GLCanvas canvas = new GLCanvas();
canvas.addGLEventListener( new ITSAEventHandler() );
final Animator animator = new Animator( canvas );
// animator.setRunAsFastAsPossible( true );
JFrame frame = new JFrame( "ITSA" );
frame.add( canvas );
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.pack();
frame.setSize( 400, 400 );
frame.setVisible( true );
animator.start();
}
}
ITSAEventHandler.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.nio.*;
import java.util.*;
import javax.media.opengl.*;
import com.sun.opengl.utils.*;
public class ITSAEventHandler implements GLEventListener {
private GeomBuffers geomBufs;
public ITSAEventHandler() {
ITSA geom = new ITSA();
geomBufs = new GeomBuffers( geom );
}
public void init( GLAutoDrawable drawable ) {
// Use debug pipeline
// drawable.setGL( new DebugGL( drawable.getGL() ) );
GL gl = drawable.getGL();
System.err.println( "INIT GL IS: " + gl.getClass().getName() );
gl.setSwapInterval(0);
gl.glEnable( GL.GL_DEPTH_TEST );
gl.glShadeModel( GL.GL_SMOOTH );
float pos[] = { 0.0f, 0.0f, 10.0f, 0.0f };
float yellow[] = { 1.0f, 1.0f, 0.0f, 1.0f };
float white[] = { 1.0f, 1.0f, 1.0f, 1.0f };
float gray[] = { 0.3f, 0.3f, 0.3f, 1.0f };
float shininess[] = { 64.f };
gl.glLightfv( GL.GL_LIGHT0, GL.GL_POSITION, pos, 0 );
gl.glLightfv( GL.GL_LIGHT0, GL.GL_DIFFUSE, gray, 0 );
gl.glLightfv( GL.GL_LIGHT0, GL.GL_AMBIENT, gray, 0 );
gl.glLightfv( GL.GL_LIGHT0, GL.GL_SPECULAR, gray, 0 );
gl.glEnable( GL.GL_LIGHTING );
gl.glEnable( GL.GL_LIGHT0 );
gl.glPolygonMode( GL.GL_FRONT_AND_BACK, GL.GL_FILL );
gl.glMaterialfv( GL.GL_FRONT_AND_BACK,
GL.GL_AMBIENT_AND_DIFFUSE, white, 0 );
gl.glMaterialfv( GL.GL_FRONT_AND_BACK,
GL.GL_SPECULAR, gray, 0 );
gl.glMaterialfv( GL.GL_FRONT_AND_BACK,
GL.GL_SHININESS, shininess, 0 );
gl.glColorMaterial( GL.GL_FRONT_AND_BACK,
GL.GL_AMBIENT_AND_DIFFUSE );
gl.glEnable( GL.GL_COLOR_MATERIAL );
}
public void reshape(
GLAutoDrawable drawable,
int x,
int y,
int width,
int height
) {
GL gl = drawable.getGL();
System.err.println( "GL_VENDOR: " +
gl.glGetString( GL.GL_VENDOR ) );
System.err.println( "GL_RENDERER: " +
gl.glGetString( GL.GL_RENDERER ) );
System.err.println( "GL_VERSION: " +
gl.glGetString( GL.GL_VERSION ) );
float h = (float)height / (float)width;
gl.glMatrixMode( GL.GL_PROJECTION );
gl.glLoadIdentity();
gl.glFrustum( -1.0f, 1.0f, -h, h, 5.0f, 60.0f );
gl.glMatrixMode( GL.GL_MODELVIEW );
gl.glLoadIdentity();
gl.glTranslatef( 0.0f, 0.0f, -10.0f );
}
public void display( GLAutoDrawable drawable ) {
GL gl = drawable.getGL();
if ( ( drawable instanceof GLJPanel ) &&
!( (GLJPanel) drawable ).isOpaque() &&
( (GLJPanel) drawable ).shouldPreserveColorBufferIfTranslucent() ) {
gl.glClear( GL.GL_DEPTH_BUFFER_BIT );
} else {
gl.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
}
renderGeometry( gl );
}
public void displayChanged(
GLAutoDrawable drawable,
boolean modeChanged,
boolean deviceChanged
) {
}
private void renderGeometry( GL gl ) {
gl.glEnableClientState( gl.GL_COLOR_ARRAY );
gl.glEnableClientState( gl.GL_NORMAL_ARRAY );
gl.glEnableClientState( gl.GL_VERTEX_ARRAY );
gl.glVertexPointer( 3, gl.GL_FLOAT, 0, geomBufs.vcoordBuf );
gl.glNormalPointer( gl.GL_FLOAT, 0, geomBufs.vnormalBuf );
gl.glColorPointer( 3, gl.GL_FLOAT, 0, geomBufs.vcolorBuf );
// for a weeny boost !?!
gl.glLockArraysEXT( 0, geomBufs.vertexKnt );
int[] stripIC = geomBufs.stripIC;
IntBuffer vidBuf = geomBufs.vidBuf;
int offset = 0;
for ( int i = 0, imax = stripIC.length; i < imax; i++ ) {
gl.glDrawElements( gl.GL_TRIANGLE_STRIP,
stripIC[i],
gl.GL_UNSIGNED_INT,
vidBuf );
offset += stripIC[i];
vidBuf.position( offset );
}
gl.glUnlockArraysEXT();
gl.glDisableClientState( gl.GL_COLOR_ARRAY );
gl.glDisableClientState( gl.GL_NORMAL_ARRAY );
gl.glDisableClientState( gl.GL_VERTEX_ARRAY );
}
private class GeomBuffers {
int vertexKnt;
FloatBuffer vcoordBuf;
FloatBuffer vnormalBuf;
FloatBuffer vcolorBuf;
IntBuffer vidBuf;
int[] stripIC;
GeomBuffers( ITSA geom ) {
vertexKnt = geom.vertexKnt;
vcoordBuf = BufferUtils.newFloatBuffer( geom.vcoords.length );
vcoordBuf.put( geom.vcoords );
vcoordBuf.rewind();
vcolorBuf = BufferUtils.newFloatBuffer( geom.vcolors.length );
vcolorBuf.put( geom.vcolors );
vcolorBuf.rewind();
vnormalBuf = BufferUtils.newFloatBuffer( geom.vnormals.length );
vnormalBuf.put( geom.vnormals );
vnormalBuf.rewind();
vidBuf = BufferUtils.newIntBuffer( geom.vids.length );
vidBuf.put( geom.vids );
vidBuf.rewind();
stripIC = geom.stripIC;
}
}
}