Problem: Inverted lighting position

Since a couple of weeks, I’ve been trying to learn OpenGL with the tutorials on http://www.videotutorialsrock.com. They are really great but this week, when I did a change of system, I got a problem with the lighting. What I try to do is a situation similar to the one in lesson 4, but with a couple of different shapes. Almost everything works satisfactory, but the thing is that the lighting acts as if the light source position would have been spacially inverted. Insted of comming from the top right, it comes from the left and below. What am I doing wrong?

I submit the code for the program beneath.

main file:


#include <iostream>
#include <stdlib.h> //Needed for "exit" function
#include <math.h>

//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif


#include "shapedrawer.h"

using namespace std;

float _rotAngle = 0.0f;
float _camAngle = 0.0f;


//Called when a key is pressed
void handleKeypress(unsigned char key, //The key that was pressed
		    int x, int y) {    //The current mouse coordinates
  switch (key) {
  case 27: //Escape key
    exit(0); //Exit the program
    break;
  case 'j':
    _camAngle+=5.0f;
    glutPostRedisplay();
    break;
  case 'k':
    _camAngle-=5.0f;
    glutPostRedisplay();
    break;
  case 'l':
    if(glIsEnabled(GL_LIGHTING))
      glDisable(GL_LIGHTING);
    else
      glEnable(GL_LIGHTING);
    break;
  }
}

//Initializes 3D rendering
void initRendering() {
  //Makes 3D drawing work when something is in front of something else
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_COLOR_MATERIAL);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_NORMALIZE);

  //glShadeModel(GL_FLAT);
  glShadeModel(GL_SMOOTH);
  glClearColor(0.7f, 0.9f, 0.8f, 1.0f);

}

//Called when the window is resized
void handleResize(int w, int h) {
  //Tell OpenGL how to convert from coordinates to pixel values
  glViewport(0, 0, w, h);
	
  glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective
	
  //Set the camera perspective
  glLoadIdentity(); //Reset the camera
  gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);                
}

//Draws the 3D scene
void drawScene() {
  //Clear information from last draw
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
  glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
  glLoadIdentity(); //Reset the drawing perspective
  glTranslatef(0.0f, 0.0f , -5.0f);
  
  glRotatef(15.0f, 1.0f, 0.0f, 0.0f);
  glRotatef(-_camAngle, 0.0f, 1.0f, 0.0f);
  
  GLfloat ambientColor[] = {0.2f, 0.2f, 0.2f, 1.0f};
  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientColor);
  

  GLfloat light0position[] = {4.0f, 4.0f, 0.0f};
  GLfloat light0ambientColor[] = {0.0f, 0.0f, 0.0f, 1.0f};
  GLfloat light0diffuseColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
  GLfloat light0specularColor[] = {1.0f, 1.0f, 1.0f, 1.0f};

  glLightfv(GL_LIGHT0, GL_POSITION, light0position);
  glLightfv(GL_LIGHT0, GL_AMBIENT, light0ambientColor);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light0diffuseColor);
  glLightfv(GL_LIGHT0, GL_SPECULAR, light0specularColor);

  
  //GLfloat matSpecColor[] = {1.0f, 1.0f, 1.0f, 1.0f};
  //GLfloat matEmColor[] = {0.0f, 0.0f, 0.0f, 1.0f};
  //glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
  //glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matSpecColor);
  //glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, matEmColor);


  //pyramid
  glPushMatrix();
  glColor3f(0.0f, 0.6f, 0.0f);
  drawPyramid(1);
  glPopMatrix(); //End of pyramid


  //sphere
  glPushMatrix();
  glTranslatef(0.5f, 0.5f, 0.5f);
  glColor3f(0.2f, 0.6f, 0.5f);
  drawSphere(0.3,20,40); 
  glPopMatrix();


  //cone
  glPushMatrix();
  glTranslatef(-1.0f, 0.0f, 1.0f);
  glColor3f(0.7f, 0.7f, 0.4f);
  drawCone(0.2,0.7,20);
  glPopMatrix(); 
  
  glutSwapBuffers(); //Send the 3D scene to the screen
}

void update(int value) {
  _rotAngle += 3.0f;

  if (_rotAngle >= 360) {
    _rotAngle -= 360;
  }

   _camAngle += 0.5f;

   if (_camAngle >= 360) {
     _camAngle -= 360;
   }

  glutPostRedisplay();
  glutTimerFunc(25, update, 0);
}

int main(int argc, char** argv) {
  
  
  //Initialize GLUT
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(800, 800); //Set the window size
	
  //Create the window
  glutCreateWindow("Kalles OpenGL-skola");
  initRendering(); //Initialize rendering
	
  //Set handler functions for drawing, keypresses, and window resizes
  glutDisplayFunc(drawScene);
  glutKeyboardFunc(handleKeypress);
  glutReshapeFunc(handleResize);

  glutTimerFunc(25, update, 0);	
  glutMainLoop(); //Start the main loop.  glutMainLoop doesn't return.
  return 0; //This line is never reached
}

Helping functions to draw various shapes:


#include <iostream>
#include <stdlib.h> //Needed for "exit" function
#include <math.h>

//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#include "shapedrawer.h"

using namespace std;


//sphere drawing function
static void sphericalToCart(double r, double theta, double phi, float x[3]) {

  x[0] = r*sin(theta)*sin(phi);
  x[1] = r*cos(theta);
  x[2] = r*sin(theta)*cos(phi);

}

static void cylindricalToCart(double rho, double phi, double z, float x[3]) {

  x[0] = rho*sin(phi);
  x[1] = z;
  x[2] = rho*cos(phi);
}

void drawCone(double radius, double height, int Nlong) {

  double phi = 0.0;
  double dPhi = (2*M_PI)/Nlong;
  float x1[3], x2[3];
  float top [] = {0.0f, height/2, 0.0f};

  glBegin(GL_TRIANGLE_FAN);

  glNormal3f(top[0], top[1], top[2]);
  
  for(int i=0; i<Nlong; i++) {
    
    phi = i*dPhi;
    
    cylindricalToCart(radius, phi, -height/2, x1);
    cylindricalToCart(radius, phi+dPhi, -height/2, x2);

    //glBegin(GL_TRIANGLES);
  

    
    glVertex3f(top[0], top[1], top[2]);
    glNormal3f(x1[0], (float)(radius*radius/height), x1[2]);
    glVertex3f(x1[0], x1[1], x1[2]);
    glNormal3f(x2[0], (float)(radius*radius/height), x2[2]);
    glVertex3f(x2[0], x2[1], x2[2]);

    
  }
  glEnd();
}

void drawSphere(double radius, int Nlat, int Nlong) {

  double theta = 0.0;
  double phi = 0.0;
  double dTheta = M_PI/Nlat;
  double dPhi = (M_PI*2)/Nlong;
  float x1[3],x2[3],x3[3],x4[3];

  for(int i=0; i<Nlat; i++) {
  
    theta = i*dTheta;

    for(int j=0; j<Nlong; j++) {

      phi = j*dPhi;
      
      sphericalToCart(radius, theta, phi, x1);
      sphericalToCart(radius, theta, phi + dPhi, x2);
      sphericalToCart(radius, theta + dTheta, phi, x3);
      sphericalToCart(radius, theta + dTheta, phi + dPhi, x4);
    
      glBegin(GL_QUADS);
      //glNormal3f(x1[0]+x4[0], x1[1]+x4[1], x1[2]+x4[2]);
      glNormal3f(x1[0], x1[1], x1[2]);
      glVertex3f(x1[0], x1[1], x1[2]);
      glNormal3f(x2[0], x2[1], x2[2]);
      glVertex3f(x2[0], x2[1], x2[2]);
      glNormal3f(x4[0], x4[1], x4[2]);
      glVertex3f(x4[0], x4[1], x4[2]);
      glNormal3f(x3[0], x3[1], x3[2]);
      glVertex3f(x3[0], x3[1], x3[2]);
      glEnd();
  
    }
  }

}


void drawPyramid(double side) {
  
  glPushMatrix();

  glScalef(side,side,side);

  glBegin(GL_TRIANGLES);

  //bottom face
  glNormal3f(0.0f, -1.0f, 0.0f);
  glVertex3f(-0.5f, -0.2041f, -0.2887f);
  glVertex3f(0.5f, -0.2041f, -0.2887f);
  glVertex3f(0.0f, -0.2041f, 0.5774f);  

  // back face
  glNormal3f(0.0f, 2.041f, -5.774f);
  glVertex3f(-0.5f, -0.2041f, -0.2887f);
  glVertex3f(0.5f, -0.2041f, -0.2887f);
  glVertex3f(0.0f, 0.6124f, 0.0f);

  // right face
   glNormal3f(0.5f, 0.2041f, 0.2887f);
  glVertex3f(0.5f, -0.2041f, -0.2887f);
  glVertex3f(0.0f, -0.2041f, 0.5774f);  
  glVertex3f(0.0f, 0.6124f, 0.0f);
  
  // left face
   glNormal3f(-0.5f, 0.2041f, 0.2887f);
  glVertex3f(-0.5f, -0.2041f, -0.2887f);
  glVertex3f(0.0f, -0.2041f, 0.5774f);
  glVertex3f(0.0f, 0.6124f, 0.0f);

  glEnd();

  glPopMatrix();
}


Screenshot:

I see that you apply several transformations to your scene. Are you sure of how your light is transformed? Don’t forget that all transformations applied above the line that sets the light position, affects this last one.

EDIT:

is the screenshot for camAngle = 0.0 ?

One suspicious thing I found in your code.


GLfloat light0position[] = {4.0f, 4.0f, 0.0f};
glLightfv(GL_LIGHT0, GL_POSITION, light0position);

The GL_POSITION expects four float values instead of three you are providing (the light position is expressed in homogeneous coordinates). Because of this it will fetch a undefined value behind the end of the light0position array. Depending on the compiler and compilation options you are using, the undefined value might be anything, possibly even a negative value which might explain the unexpected direction.

hm, perhaps not exactly. as you see it spins around, but i tried catching it there.

This was it. Of course this error was really stupid and I can’t understand how i missed it. Thanks for pointing it out!