Search code examples
javaopenglgraphicsjogl

OpenGL Lighting with Display Lists


I'm developing some OpenGL game using JOGL library.

When I draw objects regulary, e.g. using GL_QUADS directly in the display method, the scene lighting appears on the object.

However, when I prepare objects in the init method and load using glCallList in the display list, those objects doesn't seem to be affected from the lighting.

To be precise, they are affected in SOME way: altering the materialfv function parameters or the ambient parameters brighten or darken the scene, but the color I'm trying to diffuse is not working (only on the regular drawn objects without lists).

Code

Here's the lighting code:

public void init(GLAutoDrawable drawable) {
    GL2 gl = drawable.getGL().getGL2();

    gl.glShadeModel(GL2.GL_SMOOTH); // Enable Smooth Shading
    gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
    gl.glClearDepth(1.0f); // Depth Buffer Setup
    gl.glEnable(GL2.GL_DEPTH_TEST); // Enables Depth Testing
    gl.glDepthFunc(GL2.GL_LEQUAL); // The Type Of Depth Testing To Do
    glu = new GLU();
    // Really Nice Perspective Calculations
    gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);

    // Light
    float   ambient[] = {0.1f,0.1f,0.1f,1.0f};
    float   diffuse0[] = {1f,0f,0f,1.0f};
    float   diffuse1[] = {0f,0f,1f,1.0f};

    gl.glShadeModel(GL2.GL_SMOOTH); 

    gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, ambient, 0);
    gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, diffuse0, 0);
    gl.glEnable(GL2.GL_LIGHT0);

    gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_AMBIENT, ambient, 0);
    gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_DIFFUSE, diffuse1, 0);
    gl.glEnable(GL2.GL_LIGHT1);

    gl.glEnable(GL2.GL_LIGHTING);

    // make display lists here...

The lighting part of display:

// display method...
// apply light
float position0[] = {500, 300, 3500,1.0f};
float position1[] = {500, 300, 500,1.0f};
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, position0, 0);
gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_POSITION, position1, 0);
// draw objects directly
// draw objects using glCallLists

Here's an example of how I draw regular object in the display method:

gl.glPushMatrix();
    gl.glTranslatef(1000, 500, 2000);
    gl.glTexParameteri ( GL.GL_TEXTURE_2D,GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT );
    gl.glTexParameteri( GL.GL_TEXTURE_2D,GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT );
    float   material[] = {0.8f,0.8f,0.8f,1.0f};
    gl.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_AMBIENT_AND_DIFFUSE, material, 0);
    gl.glBegin(GL2.GL_QUADS);
    // Front Face
    gl.glNormal3f(0,0,1);
    gl.glTexCoord2f(0.0f, 0.0f);
    gl.glVertex3f(-1.0f, -1.0f, 1.0f);
    gl.glTexCoord2f(2f, 0.0f);
    gl.glVertex3f(1.0f, -1.0f, 1.0f);
    gl.glTexCoord2f(2f, 1.0f);
    gl.glVertex3f(1.0f, 1.0f, 1.0f);
    gl.glTexCoord2f(0.0f, 1.0f);
    gl.glVertex3f(-1.0f, 1.0f, 1.0f);
    // Back Face
    gl.glNormal3f(0,0,-1);
    gl.glTexCoord2f(1.0f, 0.0f);
    gl.glVertex3f(-1.0f, -1.0f, -1.0f);
    gl.glTexCoord2f(1.0f, 1.0f);
    gl.glVertex3f(-1.0f, 1.0f, -1.0f);
    gl.glTexCoord2f(0.0f, 1.0f);
    gl.glVertex3f(1.0f, 1.0f, -1.0f);
    gl.glTexCoord2f(0.0f, 0.0f);
    gl.glVertex3f(1.0f, -1.0f, -1.0f);
    // Top Face
    gl.glNormal3f(0,1,0);
    gl.glTexCoord2f(0.0f, 1.0f);
    gl.glVertex3f(-1.0f, 1.0f, -1.0f);
    gl.glTexCoord2f(0.0f, 0.0f);
    gl.glVertex3f(-1.0f, 1.0f, 1.0f);
    gl.glTexCoord2f(1.0f, 0.0f);
    gl.glVertex3f(1.0f, 1.0f, 1.0f);
    gl.glTexCoord2f(1.0f, 1.0f);
    gl.glVertex3f(1.0f, 1.0f, -1.0f);
    // Bottom Face
    gl.glNormal3f(0,-1,0);
    gl.glTexCoord2f(1.0f, 1.0f);
    gl.glVertex3f(-1.0f, -1.0f, -1.0f);
    gl.glTexCoord2f(0.0f, 1.0f);
    gl.glVertex3f(1.0f, -1.0f, -1.0f);
    gl.glTexCoord2f(0.0f, 0.0f);
    gl.glVertex3f(1.0f, -1.0f, 1.0f);
    gl.glTexCoord2f(1.0f, 0.0f);
    gl.glVertex3f(-1.0f, -1.0f, 1.0f);
    // Right face
    gl.glNormal3f(1,0,0);
    gl.glTexCoord2f(1.0f, 0.0f);
    gl.glVertex3f(1.0f, -1.0f, -1.0f);
    gl.glTexCoord2f(1.0f, 1.0f);
    gl.glVertex3f(1.0f, 1.0f, -1.0f);
    gl.glTexCoord2f(0.0f, 1.0f);
    gl.glVertex3f(1.0f, 1.0f, 1.0f);
    gl.glTexCoord2f(0.0f, 0.0f);
    gl.glVertex3f(1.0f, -1.0f, 1.0f);
    // Left Face
    gl.glNormal3f(-1,0,0);
    gl.glTexCoord2f(0.0f, 0.0f);
    gl.glVertex3f(-1.0f, -1.0f, -1.0f);
    gl.glTexCoord2f(1.0f, 0.0f);
    gl.glVertex3f(-1.0f, -1.0f, 1.0f);
    gl.glTexCoord2f(1.0f, 1.0f);
    gl.glVertex3f(-1.0f, 1.0f, 1.0f);
    gl.glTexCoord2f(0.0f, 1.0f);
    gl.glVertex3f(-1.0f, 1.0f, -1.0f);
    gl.glEnd();
    gl.glPopMatrix(); 

Here's the class I use to load obj files.

I use the method loadWavefrontObjectAsDisplayList which accepts a path to obj file and then returns the list integer.

Another Edit:

The scene (lamp is being lighten up, crate is not):

enter image description here

Link to lamp and crate .obj files.


Solution

  • The normals are probably missing in the WaveFront OBJ file of the crate model.

    Then, the OBJ importer that you use generates plain wrong normals whose coordinates are (0, 0, 0), it has no chance to work with the lightning.