Rotating Objects - Light Rotating not expected

The below code rotates a pyramid and a cube around their local axis (I believe). Why do both objects go light and dark with this code? Surely the light would come from one fixed position (like the sun) and the objects themselves would not go dark and light in entirety?

It appears that the light source is “glued” to a face of each object. When each object rotates, it rotates it’s light source along with it.

What causes this behaviour? This is old immediate mode. I am an OpenGL newbie.

#include <windows.h>							// Header File For Windows
#include <gl\gl.h>								// Header File For The OpenGL32 Library
#include <gl\glu.h>								// Header File For The GLu32 Library
#include <GL\glut.h>

static void resize(int width, int height)
{
    const float ar = (float) width / (float) height;
 
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
 
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity() ;
}
 
GLfloat		rtri  = 0.0;						  // Angle For The Triangle 
GLfloat		rquad = 0.0;						// Angle For The Quad     
GLfloat		xPosCube = 0.0;

//--------------------------------------------------------------------------------------------
// DrawPyramid
//--------------------------------------------------------------------------------------------
void DrawPyramid( void )
{
	glLoadIdentity();
  glTranslatef( -1.5f, 0.0f, -6.0f );					// Move Left 1.5 Units And Into The Screen 6.0

  glRotatef( rtri, 0.0f, 1.0f, 0.0f );				// Rotate The Triangle On The Y axis

	glBegin( GL_TRIANGLES );					// Start Drawing The Pyramid

    // Face 1
	  glVertex3f( 0.0f, 1.0f, 0.0f );			// Top Of Triangle (Front)
	  glVertex3f( -1.0f, -1.0f, 1.0f );			// Left Of Triangle (Front)
	  glVertex3f( 1.0f, -1.0f, 1.0f );			// Right Of Triangle (Front)

    // Face 2
	  glVertex3f( 0.0f, 1.0f, 0.0f);			// Top Of Triangle (Right)
	  glVertex3f( 1.0f,-1.0f, 1.0f);			// Left Of Triangle (Right)
	  glVertex3f( 1.0f,-1.0f, -1.0f);			// Right Of Triangle (Right)

    // Face 3
	  glVertex3f( 0.0f, 1.0f, 0.0f);			// Top Of Triangle (Back)
	  glVertex3f( 1.0f,-1.0f, -1.0f);			// Left Of Triangle (Back)
	  glVertex3f(-1.0f,-1.0f, -1.0f);			// Right Of Triangle (Back)

    // Face 4
	  glVertex3f( 0.0f, 1.0f, 0.0f);			// Top Of Triangle (Left)
	  glVertex3f(-1.0f,-1.0f,-1.0f);			// Left Of Triangle (Left)
	  glVertex3f(-1.0f,-1.0f, 1.0f);			// Right Of Triangle (Left)
	glEnd();
}

//--------------------------------------------------------------------------------------------
// DrawCube
//--------------------------------------------------------------------------------------------
void DrawCube( void )
{
  glLoadIdentity();
	glTranslatef( 1.75f /* + xPosCube*/ ,0.0f,-7.0f + xPosCube);				// Move Right And Into The Screen

  glRotatef(rquad,1.0f,1.0f,1.0f);			// Rotate The Cube On X, Y & Z

	glBegin(GL_QUADS);

		glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Top)
		glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Top)
		glVertex3f(-1.0f, 1.0f, 1.0f);			// Bottom Left Of The Quad (Top)
		glVertex3f( 1.0f, 1.0f, 1.0f);			// Bottom Right Of The Quad (Top)

		glVertex3f( 1.0f,-1.0f, 1.0f);			// Top Right Of The Quad (Bottom)
		glVertex3f(-1.0f,-1.0f, 1.0f);			// Top Left Of The Quad (Bottom)
		glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Bottom)
		glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Bottom)

		glVertex3f( 1.0f, 1.0f, 1.0f);			// Top Right Of The Quad (Front)
		glVertex3f(-1.0f, 1.0f, 1.0f);			// Top Left Of The Quad (Front)
		glVertex3f(-1.0f,-1.0f, 1.0f);			// Bottom Left Of The Quad (Front)
		glVertex3f( 1.0f,-1.0f, 1.0f);			// Bottom Right Of The Quad (Front)

		glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Back)
		glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Back)
		glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Back)
		glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Back)

		glVertex3f(-1.0f, 1.0f, 1.0f);			// Top Right Of The Quad (Left)
		glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Left)
		glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Left)
		glVertex3f(-1.0f,-1.0f, 1.0f);			// Bottom Right Of The Quad (Left)

		glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Right)
		glVertex3f( 1.0f, 1.0f, 1.0f);			// Top Left Of The Quad (Right)
		glVertex3f( 1.0f,-1.0f, 1.0f);			// Bottom Left Of The Quad (Right)
		glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Right)

	glEnd();						// Done Drawing The Quad
}

//--------------------------------------------------------------------------------------------
// DrawPyramidHiddenLinesPolygonOffset()
//--------------------------------------------------------------------------------------------
void DrawPyramidHiddenLinesPolygonOffset( void )
{
  // Draw cube - Hidden Line Removal with Polygon Offset.. 
  glEnable(GL_DEPTH_TEST);
  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  glColor4f(1.0f,0.0f,0.0f, 1.0f);			// Set The Color To Violet

  DrawPyramid();

  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glEnable(GL_POLYGON_OFFSET_FILL);
  glPolygonOffset(1.0, 1.0);
  glColor4f(0.5f,0.0f,0.0f, 0.1f);			// Set The Color To Violet

  DrawPyramid();

  glDisable(GL_POLYGON_OFFSET_FILL);
}

//--------------------------------------------------------------------------------------------
// DrawCubeHiddenLinesPolygonOffset()
//--------------------------------------------------------------------------------------------
void DrawCubeHiddenLinesPolygonOffset( void )
{
  // Draw cube - Hidden Line Removal with Polygon Offset.. 
  glEnable(GL_DEPTH_TEST);
  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  glColor4f(1.0f,0.0f,1.0f, 1.0f);			// Set The Color To Violet

  DrawCube();

  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glEnable(GL_POLYGON_OFFSET_FILL);
  glPolygonOffset(1.0, 1.0);
  glColor4f(0.5f,0.0f,0.5f, 0.1f);			// Set The Color To Violet

  DrawCube();

  glDisable(GL_POLYGON_OFFSET_FILL);
}

//--------------------------------------------------------------------------------------------
// DrawGLScene()
//--------------------------------------------------------------------------------------------
void DrawGLScene(void)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // Do camera rotation first..

  // Now draw and rotate objects..
  DrawCubeHiddenLinesPolygonOffset();
  DrawPyramidHiddenLinesPolygonOffset();


	rtri  += 0.022f;						// Increase The Rotation Variable For The Triangle 
	rquad -= 0.045f;						// Decrease The Rotation Variable For The Quad     
  //xPosCube -= 0.0005f;

  glutSwapBuffers();
}
 
const GLfloat light_ambient[]  = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat light_diffuse[]  = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
 
const GLfloat mat_ambient[]    = { 0.7f, 0.7f, 0.7f, 1.0f };
const GLfloat mat_diffuse[]    = { 0.8f, 0.8f, 0.8f, 1.0f };
const GLfloat mat_specular[]   = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat high_shininess[] = { 100.0f };
 
    

void IdleFunc()
{
  glutPostRedisplay();
}


void KeyboardFunc( BYTE key, int x, int y )
{
  switch (key)
  {
     case 27: // Escape key
      //glutDestroyWindow( Win.id );
      exit (0);
      break;
  }
}


/* Program entry point */
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(640,480);
    glutInitWindowPosition(10,10);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
 
    glutCreateWindow("Programming Techniques - 3D Spheres");
 
    glutKeyboardFunc( KeyboardFunc );
    glutReshapeFunc(resize);
    glutDisplayFunc( DrawGLScene );
    glutIdleFunc( IdleFunc );
 
    glClearColor(1,1,1,1);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
 
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
 
    glEnable(GL_LIGHT0);
    glEnable(GL_NORMALIZE);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_LIGHTING);
 
    glLightfv(GL_LIGHT0, GL_AMBIENT,  light_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
 
    glMaterialfv(GL_FRONT, GL_AMBIENT,   mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE,   mat_diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR,  mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
 
    glutMainLoop();
 
    return EXIT_SUCCESS;
}

[QUOTE=SparkyNZ;1278870]It appears that the light source is “glued” to a face of each object. When each object rotates, it rotates it’s light source along with it.

What causes this behaviour?[/QUOTE]
You’ve enabled lighting but you aren’t specifying any normals. The result is that every vertex has a normal of (0,0,1). When this vector (transformed by the model-view matrix) points toward the light, all vertices will be fully lit.

Thanks for that. So I should go and read up about lighting and normals. I admit I haven’t played with lighting before and this was a snippet of code that I modified. Cheers.

What causes this behaviour?

You need six glNormal calls to render the cube correctly (one per face). Each call should go before the 4 glVertex calls that define that face. The normal is a vector perpendicular to the face. For your cube, the normals would be (1,0,0), (0,1,0), (0,0,1), (-1,0,0), (0,-1,0), and (0,0,-1). I’ll leave it up to you to figure out which normal goes with each face. Careful to get the winding correctly, or the faces will be pointing inward instead of outward, which will make your cube look screwy.

Thanks! I think this is working OK… I guess I’ll need to move a light source into an appropriate position so I can get a top/left “sun light” casting onto the objects and verify that they are lighting on the correct faces.

	glBegin(GL_QUADS);

    glNormal3f(0,1,0);
    glColor3f( 1, 0, 1 ); // Purple

		glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Top)
		glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Top)
		glVertex3f(-1.0f, 1.0f, 1.0f);			// Bottom Left Of The Quad (Top)
		glVertex3f( 1.0f, 1.0f, 1.0f);			// Bottom Right Of The Quad (Top)


    glNormal3f( 1, 0, 0 );
    glColor3f( 1, 1, 0 );  // Yellow
		glVertex3f(-1.0f, 1.0f, 1.0f);			// Top Right Of The Quad (Left)
		glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Left)
		glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Left)
		glVertex3f(-1.0f,-1.0f, 1.0f);			// Bottom Right Of The Quad (Left)

    glNormal3f(0,0,1);
    glColor3f( 0, 1, 0 ); // GREEN ???
		glVertex3f( 1.0f, 1.0f, 1.0f);			// Top Right Of The Quad (Front)
		glVertex3f(-1.0f, 1.0f, 1.0f);			// Top Left Of The Quad (Front)
		glVertex3f(-1.0f,-1.0f, 1.0f);			// Bottom Left Of The Quad (Front)
		glVertex3f( 1.0f,-1.0f, 1.0f);			// Bottom Right Of The Quad (Front)

    glNormal3f( 0, 1, 0 );
    glColor3f( 1, 0, 0 );
		glVertex3f( 1.0f,-1.0f, 1.0f);			// Top Right Of The Quad (Bottom)
		glVertex3f(-1.0f,-1.0f, 1.0f);			// Top Left Of The Quad (Bottom)
		glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Bottom)
		glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Bottom)


    glColor3f( 0, 0, 1 );
    glNormal3f(0,0,1);
		glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Left Of The Quad (Back)
		glVertex3f(-1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Back)
		glVertex3f(-1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Back)
		glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Left Of The Quad (Back)

    glNormal3f(1,0,0);
    glColor3f( 0, 1, 1 ); // Cyan ???

		glVertex3f( 1.0f, 1.0f,-1.0f);			// Top Right Of The Quad (Right)
		glVertex3f( 1.0f, 1.0f, 1.0f);			// Top Left Of The Quad (Right)
		glVertex3f( 1.0f,-1.0f, 1.0f);			// Bottom Left Of The Quad (Right)
		glVertex3f( 1.0f,-1.0f,-1.0f);			// Bottom Right Of The Quad (Right)

	glEnd();						// Done Drawing The Quad