Lighting appears backwards?

So… I’m really confused as to what’s going on with my lighting effect here. Let me preface this by saying I’m really new to OpenGL and I’m finding lighting to be a pretty big stumbling block. Right now, here’s what I’m trying to do with this project:

  1. Create a solid sphere at 0,0,0.
  2. Create a torus at 3,0,0 and another at -3,0,0.
  3. Create a spotlight at 10,0,0, oriented left (-1,0,0).

When I run the program however, my objects are brightly light on the left sides and dark on the right sides… but on the ones that are lit on both sides, the glare is brightest on the right, indicating the light IS coming from the right. I’ve tried moving the light all around and keep getting all sorts of strange results, I’m really confused. In fact, if I cut the spotlight cutoff from 55 to 45, all light disappears completely. Can anyone see something obvious that I’m doing wrong?

#include <iostream>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

using namespace std;

/**********************
Init function:
 - Set up LIGHT0 as a spotlight
 - 55 degree cutoff... 45 degree makes it disapper?
 - Put it at (10,0,0)
 - Point it down -x axis

***********************/
void init(){

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glShadeModel(GL_SMOOTH);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);

    /// light variables
    GLfloat light0_ambient[] = { 1.0, 1.0, 1.0, 1 };
    GLfloat light0_position[] = { 10.0, 0.0, 0.0, 1.0 };
    GLfloat light0_spotdirection[] = { -1, 0, 0 };
    GLfloat light0_spotlightcutoff[] = { 55 };
    GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat mat_shininess[] = { 50.0 };

    /// set light properties
    glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
    glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0_spotdirection);
    glLightfv(GL_LIGHT0, GL_SPOT_CUTOFF, light0_spotlightcutoff);
    glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0.5);
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glMaterialfv(GL_BACK, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_BACK, GL_SHININESS, mat_shininess);

    glEnable(GL_LIGHT0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glClearColor(0,0,0,0);

}



/******************
Render function:
 - Position the camera at (0,0,10), look at origin.
 - Create a sphere at the origin.
 - Create a torus to the right of the origin.
 - Create a torus to the left of the origin.
*******************/
void renderScene(void){

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    gluLookAt(0, 0, 10,   0, 0, 0,   0, 1, 0);

    glutSolidSphere(1, 40, 40);

    glTranslatef(3, 0, 0);
    glutSolidTorus(.5, 1, 40, 40);

    glTranslatef(-6,0, 0);
    glutSolidTorus(.5, 1, 40, 40);

    glutSwapBuffers();

}


/******************
Reshape function:
 - Standard reshape func.
******************
void reshape( int h, int w ){
    if (h == 0) { h = 1; }

    glViewport(0,0, (GLsizei) w, (GLsizei) h);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    if (w < h || w == h) { gluPerspective(45, (GLdouble) w/h, 1, 1000); }
    else        { gluPerspective(45, (GLdouble) h/w, 1, 1000); }

    glMatrixMode(GL_MODELVIEW);
}



/******************
Main function
  - Standard main function.
******************/
int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
    glutInitWindowSize(800, 800);
    glutInitWindowPosition(100, 100);

    glutCreateWindow("3d lighting test");

    init();

    glutDisplayFunc(renderScene);
    glutReshapeFunc(reshape);

    glutMainLoop();

    return 0;
}

Check out the glLight man page:

GL_POSITION: The position is transformed by the modelview matrix when glLight is called (just as if it were a point), and it is stored in eye coordinates.

GL_SPOT_DIRECTION: The spot direction is transformed by the upper 3x3 of the modelview matrix when glLight is called, and it is stored in eye coordinates.

In your code, you’re setting the light position and direction before the call to gluLookAt(). Try it the other way around and you will succeed :slight_smile:

… I’m a bit confused by that… I didn’t think gluLookAt() transformed anything… and given the eye was only moved back a few positions back the z-axis, not rotated at all, so why would the light be?

You initially set up the light at position (10,0,0), when your modelview matrix is still identity. The light position is stored in eye space, so that puts it 10 units to the right of the camera, and pointing towards the camera.

You then pass (0,0,10) as your reference point to gluLookAt(). This results in a translation of 10 units along the z axis. The light, since it’s positioned in eye space, “moves along” with it.

So your light cone extends to the left, but since you made the angle wide enough it still touches part of your scenery. As you already noticed, when you make the angle smaller, it all turns black.

Hope this helped…