JOGL: all gl method calls throw "GL_INVALID_ENUM"

Hello All,

I am trying to port over a piece of sample code from the OpenGL SuperBible from C to JOGL and have been running into a bizarre issue. In my display(GLAutoDrawable) method, ALL calls to my GL object (e.g. gl.glMatrixMode(GL.GL_PROJECTION):wink: return a glError which resolves to:

“glGetError() returned the following error codes after a call to gl________(): GL_INVALID_ENUM”

Note that I have wrapped my GL object into a DebugGL wrapper in order for it to throw an exception.

The sample code involves shadow mapping, but I think this is more of a general JOGL issue. Here is my ported sample code for reference. The issue specifically involves gl calls in display() but do not have any issues with gl calls in init():

This issue has had me stumped since yesterday and most of today. Has anybody ever run into this issue and know how to resolve it?

I’ve included my code for reference. The display() routine is bolded. Thanks for reading:

package sm;

import graphicslib3D.Matrix3D;

import javax.media.opengl.DebugGL;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.TraceGL;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;

import sm.util.GLCheckError;

import com.sun.opengl.util.Animator;
import com.sun.opengl.util.GLUT;

public class Display extends JFrame implements GLEventListener
{
private GLCanvas glCanvas;
private GLU glu;
private GLUT glut;
private Animator animator;

private boolean ambientShadowAvailable = false;
private boolean npotTexturesAvailable = false;
private boolean controlCamera = true; // xyz keys will control lightpos
private boolean noShadows = false; // normal lighting
private boolean showShadowMap = false; // show the shadowmap texture

private float factor = 4.0f; // for polygon offset

private int windowWidth = 1024; // window size
private int windowHeight = 512;

private int shadowWidth = 1024;
private int shadowHeight = 512;
private int shadowTextureID;

private int maxTexSize; // maximum allowed size for 1D/2D texture

private float[] ambientLight = { 0.2f, 0.2f, 0.2f, 1.0f};
private float[] diffuseLight = { 0.7f, 0.7f, 0.7f, 1.0f};
private float[] noLight = { 0.0f, 0.0f, 0.0f, 0.0f};
private float[] lightPos = { 100.0f, 150.0f, 200.0f, 1.0f};

private float[] cameraPos = { 100.0f, 150.0f, 200.0f, 1.0f};
double cameraZoom = 0.3;

private Matrix3D textureMatrix = new Matrix3D();

public Display()
{
super();
setTitle(“ShadowMap Demo”);
setSize(windowWidth, windowHeight);
setLocation(200, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);

GLCapabilities caps = new GLCapabilities();
caps.setDoubleBuffered(true);
caps.setHardwareAccelerated(true);

// create a canvas on which to draw
//glCanvas = new GLCanvas(caps);
glCanvas = new GLCanvas();
glCanvas.addGLEventListener(this);

// add the canvas to the JFrame and make it visible
this.add(glCanvas);
this.setVisible(true);

// start animating
animator = new Animator(glCanvas);
animator.start();
}

// called to draw scene objects
private void drawModels(GLAutoDrawable drawable,
boolean drawBasePlane)
{
GL gl = drawable.getGL();

if (drawBasePlane)
{
// Draw plane that the objects rest on
gl.glColor3f(0.0f, 0.0f, 0.90f); // Blue
gl.glNormal3f(0.0f, 1.0f, 0.0f);
gl.glBegin(GL.GL_QUADS);
gl.glVertex3f(-100.0f, -25.0f, -100.0f);
gl.glVertex3f(-100.0f, -25.0f, 100.0f);
gl.glVertex3f(100.0f, -25.0f, 100.0f);
gl.glVertex3f(100.0f, -25.0f, -100.0f);
gl.glEnd();
}

// Draw red cube
gl.glColor3f(1.0f, 0.0f, 0.0f);
glut.glutSolidCube(48.0f);

// Draw green sphere
gl.glColor3f(0.0f, 1.0f, 0.0f);
gl.glPushMatrix();
gl.glTranslatef(-60.0f, 0.0f, 0.0f);
glut.glutSolidSphere(25.0f, 50, 50);
gl.glPopMatrix();

// Draw yellow cone
gl.glColor3f(1.0f, 1.0f, 1.0f);
gl.glPushMatrix();
gl.glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(60.0f, 0.0f, -24.0f);
glut.glutSolidCone(25.0f, 50.0f, 50, 50);
gl.glPopMatrix();

// Draw magenta torus
gl.glColor3f(1.0f, 0.0f, 1.0f);
gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.0f, 60.0f);
glut.glutSolidTorus(8.0f, 16.0f, 50, 50);
gl.glPopMatrix();

// Draw cyan octaheron
gl.glColor3f(0.0f, 1.0f, 1.0f);
gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.0f, -60.0f);
gl.glScalef(25.0f, 25.0f, 25.0f);
glut.glutSolidOctahedron();
gl.glPopMatrix();
}

public void regenerateShadowMap(GLAutoDrawable drawable)
{
GL gl = drawable.getGL();

float lightToSceneDistance, nearPlane, fieldOfView;
Matrix3D lightProjection, lightModelView;
float[] temp = new float[16];
float sceneBoundingRadius = 95.0f; // based on objects in the scene

// Save the depth precision for where it’s useful
lightToSceneDistance = (float)Math.sqrt(lightPos[0] * lightPos[0] +
lightPos[1] * lightPos[1] +
lightPos[2] * lightPos[2]);
nearPlane = lightToSceneDistance - sceneBoundingRadius;
// Keep the scene filling the depth texture
fieldOfView = (float)Math.toDegrees(2.0f * Math.atan(sceneBoundingRadius / lightToSceneDistance));

gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(fieldOfView, 1.0f, nearPlane, nearPlane + (2.0f * sceneBoundingRadius));
gl.glGetFloatv(GL.GL_PROJECTION_MATRIX, temp, 0);
lightProjection = new Matrix3D(floatArrayToDouble(temp));
// Switch to light’s point of view
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
glu.gluLookAt(lightPos[0], lightPos[1], lightPos[2],
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, temp, 0);
lightModelView = new Matrix3D(floatArrayToDouble(temp));
gl.glViewport(0, 0, shadowWidth, shadowHeight);

// Clear the depth buffer only
gl.glClear(GL.GL_DEPTH_BUFFER_BIT);

// All we care about here is resulting depth values
gl.glShadeModel(GL.GL_FLAT);
gl.glDisable(GL.GL_LIGHTING);
gl.glDisable(GL.GL_COLOR_MATERIAL);
gl.glDisable(GL.GL_NORMALIZE);
gl.glColorMask(false, false, false, false);

// Overcome imprecision
gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);

// Draw objects in the scene except base plane
// which never shadows anything
drawModels(drawable, false);

// Copy depth values into depth texture
gl.glCopyTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_DEPTH_COMPONENT,
0, 0, shadowWidth, shadowHeight, 0);

// Restore normal drawing state
gl.glShadeModel(GL.GL_SMOOTH);
gl.glEnable(GL.GL_LIGHTING);
gl.glEnable(GL.GL_COLOR_MATERIAL);
gl.glEnable(GL.GL_NORMALIZE);
gl.glColorMask(true, true, true, true);
gl.glDisable(GL.GL_POLYGON_OFFSET_FILL);

// Set up texture matrix for shadow map projection,
// which will be rolled into the eye linear
// texture coordinate generation plane equations
textureMatrix.setToIdentity();
textureMatrix.translate(0.5, 0.5, 0.5);
textureMatrix.scale(0.5, 0.5, 0.5);
textureMatrix.concatenate(lightProjection);
textureMatrix.concatenate(lightModelView);
// transpose to get the s, t, r, and q rows for plane equations
textureMatrix.transpose();
}

//–GLEventListener–
// initializes GL stuff
public void init(GLAutoDrawable drawable)
{
glu = new GLU();
glut = new GLUT();
GL gl = drawable.getGL();

int[] temp = new int[1];
gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, temp, 0);
maxTexSize = temp[0];

ambientShadowAvailable = true; // hard-coded

// Black background
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

// Hidden surface removal
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL.GL_LEQUAL);
gl.glPolygonOffset(factor, 0.0f);

// Set up some lighting state that never changes
gl.glShadeModel(GL.GL_SMOOTH);
gl.glEnable(GL.GL_LIGHTING);
gl.glEnable(GL.GL_COLOR_MATERIAL);
gl.glEnable(GL.GL_NORMALIZE);
gl.glEnable(GL.GL_LIGHT0);

// Set up some texture state that never changes
gl.glGenTextures(1, temp, 0);
shadowTextureID = temp[0];
gl.glBindTexture(GL.GL_TEXTURE_2D, shadowTextureID);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_DEPTH_TEXTURE_MODE, GL.GL_INTENSITY); //??
if (ambientShadowAvailable)
gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_COMPARE_FAIL_VALUE_ARB,
0.5f);
gl.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR);
gl.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR);
gl.glTexGeni(GL.GL_R, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR);
gl.glTexGeni(GL.GL_Q, GL.GL_TEXTURE_GEN_MODE, GL.GL_EYE_LINEAR);

regenerateShadowMap(drawable);
}

// draw commands
public void display(GLAutoDrawable drawable)
{
// Debugging stuff
DebugGL dbg = new DebugGL(drawable.getGL());
drawable.setGL(dbg);

GL gl = drawable.getGL();
// Track camera angle
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
if (windowWidth > windowHeight)
{
double ar = (double)windowWidth / (double)windowHeight;
gl.glFrustum(-ar * cameraZoom, ar * cameraZoom,
-cameraZoom, cameraZoom, 1.0, 1000.0);
}
else
{
double ar = (double)windowHeight / (double)windowWidth;
gl.glFrustum(-cameraZoom, cameraZoom,
-ar * cameraZoom, ar * cameraZoom, 1.0, 1000.0);
}

gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
glu.gluLookAt(cameraPos[0], cameraPos[1], cameraPos[2],
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

gl.glViewport(0, 0, windowWidth, windowHeight); // necessary?

// Track light position
gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, lightPos, 0);

// Clear the window with current clearing color
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

if (showShadowMap)
{
// Display shadow map for educational purposes
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glMatrixMode(GL.GL_TEXTURE);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glDisable(GL.GL_LIGHTING);
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE);
// Show the shadowmap at its actual size relative to window
gl.glBegin(GL.GL_QUADS);
gl.glTexCoord2f(0.0f, 0.0f);
gl.glVertex2f(-1.0f, -1.0f);
gl.glTexCoord2f(1.0f, 0.0f);
gl.glVertex2f(((float)shadowWidth / (float)windowWidth)*2.0f-1.0f,
-1.0f);
gl.glTexCoord2f(1.0f, 1.0f);
gl.glVertex2f(((float)shadowWidth / (float)windowWidth)*2.0f-1.0f,
((float)shadowHeight / (float)windowHeight)*2.0f-1.0f);
gl.glEnd();
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glEnable(GL.GL_LIGHTING);
gl.glPopMatrix();
gl.glMatrixMode(GL.GL_PROJECTION);
glu.gluPerspective(45.0f, 1.0f, 1.0f, 1000.0f); // why different?
gl.glMatrixMode(GL.GL_MODELVIEW);
}
else if (noShadows)
{
// Set up some simple lighting
gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambientLight, 0);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuseLight, 0);

// Draw objects in the scene including base plane
drawModels(drawable, true);
}
else
{
if (!ambientShadowAvailable)
{
float[] lowAmbient = { 0.1f, 0.1f, 0.1f, 1.0f};
float[] lowDiffuse = { 0.35f, 0.35f, 0.35f, 1.0f};

// Because there is no support for an “ambient”
// shadow compare fail value, we’ll have to
// draw an ambient pass first…
gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, lowAmbient, 0);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, lowDiffuse, 0);

// Draw objects in the scene, including base plane
drawModels(drawable, true);

// Enable alpha test so that shadowed fragments are discarded
gl.glAlphaFunc(GL.GL_GREATER, 0.9f);
gl.glEnable(GL.GL_ALPHA_TEST);
}

gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, ambientLight, 0);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, diffuseLight, 0);

// Set up shadow comparison
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_COMPARE_MODE,
GL.GL_COMPARE_R_TO_TEXTURE);

// Set up the eye plane for projecting the shadow map on the scene
float[] textureMatrixValues =
doubleArrayToFloat(textureMatrix.getValues());
gl.glEnable(GL.GL_TEXTURE_GEN_S);
gl.glEnable(GL.GL_TEXTURE_GEN_T);
gl.glEnable(GL.GL_TEXTURE_GEN_R);
gl.glEnable(GL.GL_TEXTURE_GEN_Q);
gl.glTexGenfv(GL.GL_S, GL.GL_EYE_PLANE, textureMatrixValues, 0);
gl.glTexGenfv(GL.GL_T, GL.GL_EYE_PLANE, textureMatrixValues, 4);
gl.glTexGenfv(GL.GL_R, GL.GL_EYE_PLANE, textureMatrixValues, 8);
gl.glTexGenfv(GL.GL_Q, GL.GL_EYE_PLANE, textureMatrixValues, 12);

// Draw objects in the scene, including base plane
drawModels(drawable, true);

gl.glDisable(GL.GL_ALPHA_TEST);
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glDisable(GL.GL_TEXTURE_GEN_S);
gl.glDisable(GL.GL_TEXTURE_GEN_T);
gl.glDisable(GL.GL_TEXTURE_GEN_R);
gl.glDisable(GL.GL_TEXTURE_GEN_Q);
}

gl.glFlush();
GLCheckError.displayErrorStatus(gl, glu, null, false);
}

public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}

// Converts a double array to a float array.
private float[] doubleArrayToFloat(double[] source)
{
float[] dest = new float[source.length];
for (int i = 0; i < source.length; i++)
dest[i] = (float)source[i];

return dest;
}

// Converts a float array to a double array.
private double[] floatArrayToDouble(float[] source)
{
double[] dest = new double[source.length];
for (int i = 0; i < source.length; i++)
dest[i] = (double)source[i];

return dest;
}
}