0
votes

I've created a scene with a rotating cube in Java/lwjgl. If I enable lighting, I get a realistic behavior as if the light source were at the camera position, no matter where I place my light source.

Here is my method to initialize openGL:

private void initGL() throws LWJGLException {
    Display.create();
    Display.setFullscreen(true);
    Display.setVSyncEnabled(true);

    GL11.glViewport(0, 0, WIDTH, HEIGHT);
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GLU.gluPerspective(70, 4f / 3f, 1, 10000);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);

    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glDepthMask(true);

    GL11.glEnable(GL11.GL_CULL_FACE);

    // ----IMPORTANT PART----
    GL11.glEnable(GL11.GL_LIGHTING);
    GL11.glEnable(GL11.GL_LIGHT0);

    FloatBuffer position = ByteBuffer.allocateDirect(16).asFloatBuffer();
    position.mark();
    position.put(new float[] { -5f, 5f, 10f, 0f }); // even values about 10e3 for the first three parameters aren't changing anything
    position.reset();

    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, position);

    FloatBuffer ambient = ByteBuffer.allocateDirect(16).asFloatBuffer();
    ambient.mark();
    ambient.put(new float[] { 0.5f, 0.5f, 0.5f, 1f });
    ambient.reset();

    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, ambient);

    // Textures...
}

With this piece of code is called, when I start rendering:

private void renderGL() {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

    for (RenderObject ro : renderObjects) {
        ro.render();
    }
}

And this draws the cube. The normals are correct, I think, reversing them would prevent the face to be drawn, at least in my tests.

public void render() {
    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);
    GL11.glColor3f(1f, 1f, 1f);

    GL11.glPushMatrix();

    GL11.glTranslatef(x, y, z);
    GL11.glRotatef(rotation, 1, 1, 1);
    GL11.glTranslatef(-x, -y, -z);

    GL11.glBegin(GL11.GL_QUADS);

    GL11.glNormal3f(0, 0, -1f);
    GL11.glTexCoord2f(0, 0);
    GL11.glVertex3f(x - dx, y - dy, z - dz);
    GL11.glTexCoord2f(0, 1);
    GL11.glVertex3f(x - dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 1);
    GL11.glVertex3f(x + dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 0);
    GL11.glVertex3f(x + dx, y - dy, z - dz);

    // the other five faces

    GL11.glEnd();

    GL11.glPopMatrix();
}

What am I doing wrong with the lighting stuff?

EDIT: Additional information about the error

When I set the last value of the light position array to 0, the whole scene is black. Setting it to any other value, the light comes out of the viewport as described. Ambient light does not change anything, the cube I want to draw stays dark, when the light source is not working. I tried to put the lighting stuff at other positions in the code, e.g. directly after the GLU.gluPerspective(70, 4f / 3f, 1, 10000); line, or into the loop, not changing any of the described effects.

1

1 Answers

1
votes

What am I doing wrong with the lighting stuff?

The lighting position is multiplied with the modelview matrix. So you must call glLightfv(GL_LIGHT_, GL_POSITION, …); right when your modelview matrix contains the viewing transformation.

Technically everything you've written in that initGL function belongs into the drawing function. OpenGL is not a scene graph you initialize.

Update:

Change your code like this:

public void render() {
    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);
    GL11.glColor3f(1f, 1f, 1f);

    GL11.glPushMatrix();

    // this is where you set up your view:
    GL11.glTranslatef(x, y, z);
    GL11.glRotatef(rotation, 1, 1, 1);
    GL11.glTranslatef(-x, -y, -z);

    // and now it's time to set the light position:
    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, position);

    GL11.glBegin(GL11.GL_QUADS);

    GL11.glNormal3f(0, 0, -1f);
    GL11.glTexCoord2f(0, 0);
    GL11.glVertex3f(x - dx, y - dy, z - dz);
    GL11.glTexCoord2f(0, 1);
    GL11.glVertex3f(x - dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 1);
    GL11.glVertex3f(x + dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 0);
    GL11.glVertex3f(x + dx, y - dy, z - dz);

    // the other five faces

    GL11.glEnd();

    GL11.glPopMatrix();
}

Then you should drop initGL completely, move it's code into the drawing function, turning it into:

public void render() {

    GL11.glViewport(0, 0, WIDTH, HEIGHT);

    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GLU.gluPerspective(70, 4f / 3f, 1, 10000);

    GL11.glMatrixMode(GL11.GL_MODELVIEW);   
    glLoadIdentity();
    GL11.glPushMatrix();

    // this is where you set up your view:
    GL11.glTranslatef(x, y, z);
    GL11.glRotatef(rotation, 1, 1, 1);
    GL11.glTranslatef(-x, -y, -z);

    // and now it's time to set the light position:
    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, position);

    // we do the rest of the light here as well
    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, ambient);

    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glDepthMask(true);
    GL11.glEnable(GL11.GL_CULL_FACE);

    // we enable lighting right before rendering
    GL11.glEnable(GL11.GL_LIGHTING);
    GL11.glEnable(GL11.GL_LIGHT0);    

    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);

    GL11.glColor3f(1f, 1f, 1f);

    GL11.glBegin(GL11.GL_QUADS);

    GL11.glNormal3f(0, 0, -1f);
    GL11.glTexCoord2f(0, 0);
    GL11.glVertex3f(x - dx, y - dy, z - dz);
    GL11.glTexCoord2f(0, 1);
    GL11.glVertex3f(x - dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 1);
    GL11.glVertex3f(x + dx, y + dy, z - dz);
    GL11.glTexCoord2f(1, 0);
    GL11.glVertex3f(x + dx, y - dy, z - dz);

    // the other five faces

    GL11.glEnd();

    GL11.glPopMatrix();
}