JOGL: all gl method calls return "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

[b] 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);
}[/b]

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;
}

}

Did you try a well-known JOGL example, to rule out a problem coming from your setup or build environment ?

Thanks for the response. Yes, I have been able to run other JOGL programs on the same machine and in the same manner…which makes it even that much more perplexing as to why this program alone has this problem.