lwjgl Lighting problems compared to JOGL

Started by hawkettc, February 12, 2006, 05:20:41

Previous topic - Next topic

hawkettc

Hi,

  I'm having difficulty getting lighting to work effectively under lwjgl on OS X.  The lighting works, but it produces shadow-like artefacts that look similar to aliasing, but not.  I recently moved to lwjgl from JOGL so it didn't take too much effort to put together a test in jogl using exactly the same gl commands.  The lighting is much better in JOGL.  The only thing I can think of at the moment is that some performance enhancement is on by default in lwjgl that is off by default in JOGL.  Or perhaps the bindings to the underlying gl are implemented differently.
 
Anyway - here is the lwjgl code -

public class CubeLightingTest {
	private boolean closing = false;
	
	private boolean lighting = true;
	
	private float rotation = 0;
	
	private void initGL() {
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		
		ByteBuffer temp = ByteBuffer.allocateDirect(16);
		temp.order(ByteOrder.nativeOrder());
		GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, (FloatBuffer)temp.asFloatBuffer().put(new float[] {0.9f, 0.9f, 0.9f, 1.0f}).flip());
		
		GL11.glLight(GL11.GL_LIGHT1, GL11.GL_POSITION, (FloatBuffer)temp.asFloatBuffer().put(new float[] {0.0f, 0.0f, 0.0f, 1.0f}).flip());
		GL11.glLight(GL11.GL_LIGHT1, GL11.GL_DIFFUSE, (FloatBuffer)temp.asFloatBuffer().put(new float[] {1.0f, 1.0f, 1.0f, 1.0f}).flip());
		GL11.glEnable(GL11.GL_LIGHTING);
		GL11.glEnable(GL11.GL_LIGHT1);
		
		GL11.glClearDepth(1.0f);
		GL11.glEnable(GL11.GL_DEPTH_TEST);
		GL11.glDepthFunc(GL11.GL_LEQUAL);
		
		GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
		
		GL11.glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GLU.gluPerspective(45.0f, (float) Display.getDisplayMode().getWidth() / (float) Display.getDisplayMode().getHeight(), 0.1f, 100.0f);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		GL11.glLoadIdentity();
	}
	
	private void render() {
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
		GL11.glLoadIdentity();
		
		GL11.glTranslated(0, 0, -60);
		GL11.glRotatef(rotation, 1f, 1f, 0f);
		
		rotation += 0.15f;
		if(rotation > 360) rotation -= 360;
		
		GL11.glBegin(GL11.GL_QUADS); // Start Drawing Quads
		// Front Face
		GL11.glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
		GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Point 1 (Front)
		GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Point 2 (Front)
		GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Point 3 (Front)
		GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Point 4 (Front)
		// Back Face
		GL11.glNormal3f(0.0f, 0.0f, -1.0f); // Normal Pointing Away From Viewer
		GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Point 1 (Back)
		GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Point 2 (Back)
		GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Point 3 (Back)
		GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Point 4 (Back)
		// Top Face
		GL11.glNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
		GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Point 1 (Top)
		GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Point 2 (Top)
		GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Point 3 (Top)
		GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Point 4 (Top)
		// Bottom Face
		GL11.glNormal3f(0.0f, -1.0f, 0.0f); // Normal Pointing Down
		GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Point 1 (Bottom)
		GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Point 2 (Bottom)
		GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Point 3 (Bottom)
		GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Point 4 (Bottom)
		// Right face
		GL11.glNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
		GL11.glVertex3f(1.0f, -1.0f, -1.0f); // Point 1 (Right)
		GL11.glVertex3f(1.0f, 1.0f, -1.0f); // Point 2 (Right)
		GL11.glVertex3f(1.0f, 1.0f, 1.0f); // Point 3 (Right)
		GL11.glVertex3f(1.0f, -1.0f, 1.0f); // Point 4 (Right)
		// Left Face
		GL11.glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
		GL11.glVertex3f(-1.0f, -1.0f, -1.0f); // Point 1 (Left)
		GL11.glVertex3f(-1.0f, -1.0f, 1.0f); // Point 2 (Left)
		GL11.glVertex3f(-1.0f, 1.0f, 1.0f); // Point 3 (Left)
		GL11.glVertex3f(-1.0f, 1.0f, -1.0f); // Point 4 (Left)
		GL11.glEnd(); // Done Drawing Quads
		
		GL11.glFlush();
	}
	
	protected void execute() {
		setupDisplay();
		while (!closing) {
			handleWindow();
			handleKeyboard();
			render();
		}
		Display.destroy();
	}

	private void setupDisplay() {
		try {
			Display.setDisplayMode(new DisplayMode(1024, 768));
			Display.setFullscreen(false);
			Display.create();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(-1);
		}

		initGL();
	}
	
	protected void handleWindow() {
		Display.update();
		closing = Display.isCloseRequested();
	}
	
	protected void handleKeyboard() {
		while (Keyboard.next()) {
			if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE && Keyboard.getEventKeyState()) {
				closing = true;
			}
			if (Keyboard.getEventKey() == Keyboard.KEY_L && Keyboard.getEventKeyState()) {
				if(!lighting) GL11.glEnable(GL11.GL_LIGHT1);
				else GL11.glDisable(GL11.GL_LIGHT1);
				lighting = !lighting;
			}
		}
	}
	
	public static void main(String[] args) {
		new CubeLightingTest().execute();
	}
}


And here is the JOGL code

public class CubeLightingTest extends JFrame implements GLEventListener {
	public static final Dimension PREFERRED_FRAME_SIZE = new Dimension (1024,768);
	
	private GLCanvas canvas;
	private Animator anim;
	
	private float rotation = 0;
	
	public CubeLightingTest() {
		super("Cube Lighting Test");
		
		addWindowListener(new ShutdownWindowAdapter());
		
		canvas = GLDrawableFactory.getFactory().createGLCanvas(	new GLCapabilities());
		canvas.addGLEventListener(this);
		anim = new Animator(canvas);
		anim.start();
		
		getContentPane().add(canvas, BorderLayout.CENTER);

	}
	
	public static void main (String[] args) {
		CubeLightingTest f = new CubeLightingTest();
		f.pack();
		f.setVisible(true);
    }
	
	public void init(GLDrawable drawable) {
		final GL gl = drawable.getGL();
		
		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
		gl.glShadeModel(GL.GL_SMOOTH);

		gl.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, new float[] {0.9f, 0.9f, 0.9f, 1.0f});
		gl.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION, new float[] {0.0f, 0.0f, 0.0f, 1.0f});
		gl.glLightfv(GL.GL_LIGHT1, GL.GL_DIFFUSE, new float[] {1.0f, 1.0f, 1.0f, 1.0f});
		gl.glEnable(GL.GL_LIGHTING);
		gl.glEnable(GL.GL_LIGHT1);
		
		gl.glClearDepth(1.0f);
		gl.glEnable(GL.GL_DEPTH_TEST);
		gl.glDepthFunc(GL.GL_LEQUAL);
		
		gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);		
	}
	
	public void reshape(final GLDrawable drawable, final int x, final int y, final int width, int height) {
		final GL gl = drawable.getGL();
		final GLU glu = drawable.getGLU();

		if (height <= 0) height = 1;
		final float h = (float) width / (float) height;
		gl.glViewport(0, 0, width, height);
		gl.glMatrixMode(GL.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(45.0f, h, 0.1, 100.0);
		gl.glMatrixMode(GL.GL_MODELVIEW);
		gl.glLoadIdentity();
	}
	
	public void display(GLDrawable drawable) {
		final GL gl = drawable.getGL();
		
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
		gl.glLoadIdentity();
		
		gl.glTranslated(0, 0, -60);
		gl.glRotatef(rotation, 1f, 1f, 0f);
		
		rotation += 0.15f;
		if(rotation > 360) rotation -= 360;
		
		gl.glBegin(GL.GL_QUADS); // Start Drawing Quads
		// Front Face
		gl.glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
		gl.glVertex3f(-1.0f, -1.0f, 1.0f); // Point 1 (Front)
		gl.glVertex3f(1.0f, -1.0f, 1.0f); // Point 2 (Front)
		gl.glVertex3f(1.0f, 1.0f, 1.0f); // Point 3 (Front)
		gl.glVertex3f(-1.0f, 1.0f, 1.0f); // Point 4 (Front)
		// Back Face
		gl.glNormal3f(0.0f, 0.0f, -1.0f); // Normal Pointing Away From Viewer
		gl.glVertex3f(-1.0f, -1.0f, -1.0f); // Point 1 (Back)
		gl.glVertex3f(-1.0f, 1.0f, -1.0f); // Point 2 (Back)
		gl.glVertex3f(1.0f, 1.0f, -1.0f); // Point 3 (Back)
		gl.glVertex3f(1.0f, -1.0f, -1.0f); // Point 4 (Back)
		// Top Face
		gl.glNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
		gl.glVertex3f(-1.0f, 1.0f, -1.0f); // Point 1 (Top)
		gl.glVertex3f(-1.0f, 1.0f, 1.0f); // Point 2 (Top)
		gl.glVertex3f(1.0f, 1.0f, 1.0f); // Point 3 (Top)
		gl.glVertex3f(1.0f, 1.0f, -1.0f); // Point 4 (Top)
		// Bottom Face
		gl.glNormal3f(0.0f, -1.0f, 0.0f); // Normal Pointing Down
		gl.glVertex3f(-1.0f, -1.0f, -1.0f); // Point 1 (Bottom)
		gl.glVertex3f(1.0f, -1.0f, -1.0f); // Point 2 (Bottom)
		gl.glVertex3f(1.0f, -1.0f, 1.0f); // Point 3 (Bottom)
		gl.glVertex3f(-1.0f, -1.0f, 1.0f); // Point 4 (Bottom)
		// Right face
		gl.glNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
		gl.glVertex3f(1.0f, -1.0f, -1.0f); // Point 1 (Right)
		gl.glVertex3f(1.0f, 1.0f, -1.0f); // Point 2 (Right)
		gl.glVertex3f(1.0f, 1.0f, 1.0f); // Point 3 (Right)
		gl.glVertex3f(1.0f, -1.0f, 1.0f); // Point 4 (Right)
		// Left Face
		gl.glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
		gl.glVertex3f(-1.0f, -1.0f, -1.0f); // Point 1 (Left)
		gl.glVertex3f(-1.0f, -1.0f, 1.0f); // Point 2 (Left)
		gl.glVertex3f(-1.0f, 1.0f, 1.0f); // Point 3 (Left)
		gl.glVertex3f(-1.0f, 1.0f, -1.0f); // Point 4 (Left)
		gl.glEnd(); // Done Drawing Quads
		
		gl.glFlush();
	}
	
	public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged) {
		System.out.println("displayChanged() called");
	}
	
	public Dimension getPreferredSize () {
        return PREFERRED_FRAME_SIZE;
    }
	
	public void stop() {
		anim.stop();
		System.exit(0);
	}
	
	private class ShutdownWindowAdapter extends WindowAdapter {
        public void windowClosing(WindowEvent e) {
            stop();
        }
    }
}


The shadowy things I am talking about are clearly visible along the edges of the cube at various points during the rotation when running under lwjgl, and not at all under JOGL.  The aliasing seems to be about the same - the chunky shadow things are what is different.  If anyone has any ideas why one would look good and the other not - it would be much appreciated - lwjgl is much better to develop with.  

Its bound to be something really obvious - but I can't spot it.

Cheers,

Colin

hawkettc

Additional information -

lwjgl ver : 0.99
jogl ver  : 1.1.1

The cube is smallish in the example because that's the distance at which the effect is most obvious.  If it is close to the viewer, then the effect iis negligible.  Unfortunately not all objects in my scene are close to the viewer.

The more objects there are in the scene the worse the effect gets - combining together to produce dark diagonal strips pulstaing across the whole scene.

The other thing is that the faces of the cube appear bettter lit - clearly the JOGL faces vary in shading depending on their angle to the light, whereas  the lwjgl faces appear all the same colour (except for the unwanted shadow effects).

I'd even be interested to know if the effect is OS X only or appears on windows/linux as well. Thanks,

Colin

Fool Running

Just a guess (Could you maybe post a screenshot?):
Try setting the glFrontFace to GL_CW. I think your polygons are in clockwise direction. (Someone correct me on this. I have a hard time telling :) ). LWJGL defaults to a counter clockwise direction. This would produce some wierd effects (possibly what you are describing). :lol:
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

hawkettc



Hi I'm pretty sure I am doing them counter clockwise... will check - here is the screenshot in the meantime - cheers,

Colin

hawkettc



This is JOGL at roughly the same point in the rotation.  I also tried GL_CW and GL_CCW in lwjgl - I had expected the lighting to be different if the front faces were all on the inside of the cube instead of the outside - but there wasn't actually any discernable difference either way.... the order in the code should be CCW i.e. - bottom left, bottom right, top right, top left....

spasi

Maybe Display.create() is the cause of the problem. The default PixelFormat used there is a PixelFormat(0, 0, 8, 0, 0). Try this:

Display.create(new PixelFormat(24, 8, 24, 0, 0));


I don't know about JOGL, but I can assure you that LWJGL contains no GL related optimization and does not modify the GL state in any way, except from initContext() in the Display class that just sets up an orthographic view.

Fool Running

QuoteThe default PixelFormat used there is a PixelFormat(0, 0, 8, 0, 0)
I didn't realize the default depth bit was set so low. That's almost worthless for 3D graphics. :lol:
QuoteHi I'm pretty sure I am doing them counter clockwise... will check - here is the screenshot in the meantime - cheers
Yeah, that doesn't look like your problem from the screenshots. I think spasi is right. 8)
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

hawkettc

Cool - thats done the trick - thanks heaps.  btw great work on lwjgl guys - as an fyi - it was Mouse.setGrabbed() that got me from JOGL to lwwjgl... but there are so many other small tings that make it better to work with... keep it up

Colin