Surfaces get darker when light gets closer?

Hi!

I have sat and stared at the following lighting problem for quite a while, but cannot find a solution. As an opengl-newbie, I suppose something is fundamentally wrong. The problem is, that the surfaces I am rendering seem to become darker when the light-source comes closer, and lighter when the light-source moves away. Not quite what I want… Please have a look:

  • (void)drawRect NSRect)aRect
    {
    float ambientLight = { 0.3f, 0.3f, 0.5f, 1.0f };
    float diffuseLight = { 0.25f, 0.25f, 0.25f, 1.0f };
    float lightPosition = { xPos, 1.0f, zPos, 1.0f };

    float matAmbient = { 1.0f, 1.0f, 1.0f, 1.0f };
    float matDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f };

    glViewport( 0,0,NSWidth([self bounds]),NSHeight([self bounds]) );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    gluPerspective( 60,0.9,1,20 );
    glMatrixMode( GL_MODELVIEW );

    glLoadIdentity();
    gluLookAt( 3, 8, 3, // looking from
    3, 1, 3, // looking at
    0, 0, -1 ); // up-vector (0, 0, -1): camera top pointing down the negative z-axis

    glClear( GL_COLOR_BUFFER_BIT );
    glEnable(GL_LINE_SMOOTH);

    glClearColor( 0,0,0,0 );
    glShadeModel(GL_SMOOTH);

    glEnable(GL_LIGHTING);

    glMaterialfv(GL_FRONT, GL_AMBIENT, matAmbient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiffuse);

    glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);

    glEnable(GL_LIGHT0);

    glBegin( GL_POINTS );
    glVertex3f( lightPosition[0], lightPosition[1], lightPosition[2] );
    glEnd();

    glBegin( GL_QUADS );
    glNormal3f( 0.0, 0.0, 1.0 );
    glVertex3f( 0.0, 0.0, 0.0 );
    glVertex3f( 2.0, 0.0, 0.0 );
    glVertex3f( 2.0, 2.0, 0.0 );
    glVertex3f( 0.0, 2.0, 0.0 );
    glEnd();
    glBegin( GL_QUADS );
    glNormal3f( 0.0, 0.0, 1.0 );
    glVertex3f( 2.0, 0.0, 0.0 );
    glVertex3f( 4, 0.0, 0.0 );
    glVertex3f( 4, 2, 0.0 );
    glVertex3f( 2.0, 2, 0.0 );
    glEnd();
    glBegin( GL_QUADS );
    glNormal3f( 0.0, 0.0, 1.0 );
    glVertex3f( 4.0, 0.0, 0.0 );
    glVertex3f( 6, 0.0, 0.0 );
    glVertex3f( 6, 2, 0.0 );
    glVertex3f( 4.0, 2, 0.0 );
    glEnd();

    glFlush();
    }

This is in Objective-C, but shouldn’t be any problem to read, since OpenGL-Calls are just standard C. drawRect() is the refresh-method for the component that displays OpenGL. I have a slider that can change the values for xPos and ZPos (of the light-Position).

Thanks for helping!

Dunken

What you observe is correct.

Each vertex has a normal pointing up. As the light gets closer to the quad, the angle between N, the normal, and L, the vector from the vertex to the light, increases. Hence the L.N dot product decreases, so the lighting darkens.

Light high up:

| L |<-normal
| \ |
| \ |
| \ |
| |
----------<-quad

Light lower down:

| L-- |<-normal
| --|
----------<-quad

Note the light vector is supposed to be a straight line.

The solution (at least the simple solution) is to tesselate your geometry. Instead of drawing a quad, try drawing a grid.

[This message has been edited by bakery2k (edited 10-15-2002).]

Thanks for Your answer. I have now tessalated the surfaces (into 10*10). The lighting effect looks much better now. However, the problem remains - the surfaces become brighter when the light moves away from them. This seems logical, considering Your explanation. However, it is undesired!
Basically, what I want at a later stage is a maze through which the user can move (with 1st person perspective). The light source would represent a torch in his hand. Walls that are far away should be darker or not visible at all. The closer the wall, the brighter it should be. could someone point me to a method for achieving this effect?

Thanks!

Dunk

You can set the attenuation parameters for the lights. Look up the GL_CONSTANT/LINEAR/QUADRATIC_ATTENUATION-parameters for glLight().