   Light from a stationary light is moving unexpectedly
  Hello, I have a simply scene that is basically a big box with a light near each corner. Each light is a spotlight type like that points down from the ceiling. However, when I rotate my camera view up or down, the apparent light on the surfaces of my box changes. To see what I mean, I video captured the viewing and put it up on YouTube so that the effect I'm talking about might be more clear.I am setting the light position after the viewing transformations and before any objects are drawn. In my research, I came across this article that deals with something like what is happening in my scene: http://gregs-blog.com/2007/12/21/theres-nothing-wrong-with-opengls-specular-lighting/ . In response to that article, I turned off all specular lighting and specular material, but to no effect.Now, I'm largely a newb with OpenGL and computer graphics in general, so is there something I'm not understanding so that this effect is actually the way it should be? If so, how would I get it so that the light on surfaces does not change when I look up or down? Below is where I set up one light (the rest are the same, except for position) and also the code for drawing one of my walls (the others are basically the same). If anyone can help or point me to a resource that might explain things, I would appreciate it. float strongWhite[] = {1, 1, 1};float direction[] = { 0.0, -1.0, 0.0 };glLightfv(GL_LIGHT0, GL_DIFFUSE, strongWhite);//glLightfv(GL_LIGHT0, GL_SPECULAR, strongWhite);  glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 15);glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 75.0);glEnable( GL_LIGHT0 );void FirstLevel::buildCeiling(){glBindTexture(GL_TEXTURE_2D, ceilingTexture);glEnable(GL_TEXTURE_2D);GLfloat board_specr[] = {1, 1, 1, 1.0};GLfloat board_d[] = {1.0, 1.0, 1.0, 1};//glMaterialfv(GL_FRONT, GL_SPECULAR, board_d);glMaterialfv(GL_FRONT, GL_DIFFUSE, board_d);glMaterialfv(GL_FRONT, GL_AMBIENT, board_d);//glMaterialf(GL_FRONT, GL_SHININESS, 5.0);glPushMatrix();glRotatef(-90, 1.0, 0, 0);glRotatef(180, 0.0, 1.0, 0.0);glTranslatef(0, 0, -10);glNormal3f(0.0, 0.0, -1.0); // Normal pointing downfor (int x = -20; (x < 20); x++){for (int y = 0; (y < 60); y++){glBegin(GL_QUADS);glTexCoord2f(0.0,0.0);glVertex3f(x, y, 0);glTexCoord2f(1.0,0.0);glVertex3f(x + 1, y, 0);glTexCoord2f(1.0,1.0);glVertex3f(x + 1, y + 1, 0);glTexCoord2f(0.0,1.0);glVertex3f(x, y + 1, 0);glEnd();}}glPopMatrix();glDisable(GL_TEXTURE_2D);}[Edited by - voxelgenesis on April 4, 2009 2:00:20 PM]
  Well you need to set normals per vertex, or at least per face if you wish to get decent lighting results. At the moment you only ever set one normal, for absolutely every polygon. This will not lead to incorrect lighting results.The normal is a vector perpendicular to the polygon. However you seem to be using it as a direction that the light points in, I guess.http://www.codeguru.com/cpp/g-m/opengl/article.php/c2681The link there is a good article for learning about normals.Hope this helps.;  "I am setting the light position after the viewing transformations"You didn't show that in the above code.   ;  Thank you Andy. I was taught to use the normals as I have been using them (direction the light points in) :( I'm guessing mostly as a short cut, but it was never explained as thus. I will look into this more.Also, I didn't put the light setting in the code because I was trying not to clutter up the issue too much and because I have experience with creating a flashlight type light, so I do know what that behavior looks like. In any case:setViewPoint();float light0[] = {-10, 12.0, -10.0, 1.0};glLightfv(GL_LIGHT0, GL_POSITION, light0);float light1[] = {10, 12.0, -10.0, 1.0};glLightfv(GL_LIGHT1, GL_POSITION, light1);float light2[] = {-10, 12.0, -50.0, 1.0};glLightfv(GL_LIGHT2, GL_POSITION, light2);float light3[] = {10, 12.0, -50.0, 1.0};glLightfv(GL_LIGHT3, GL_POSITION, light3);// Draw the scene objectsdrawScene();That's where I set their positions.   ;  I take back what I said about how I was taught. I was neglecting to do certain steps because I am forgetful and sleepy :(   ;  Hmm, now I am confused.I looked at that article and then also looked at this article: http://jerome.jouvie.free.fr/OpenGl/Tutorials/Tutorial12.phpIn there, there is a section for Quads + Normal Vectors. What I was doing is what he seems to be doing.Wouldn't a normal vector for a square be right in the middle pointing out? So, a square that is lying flat would have a normal of [0, 1, 0]. Thus, if I am just tiling a bunch of squares, wouldn't the normal be the same for all of them (I would have to adjust if I made vertical squares or upside down squares, etc)? Is my thinking on this off?   ;  RE:Is my thinking on this off?No, your fine there (well done).That's one issue cleared(so it seems).which leaves:setViewPoint(); ?still not enough code there. What we are really expecting to see is something like this in or before setViewPoint():// viewing transformations->   glMatrixMode (GL_MODELVIEW);   glLoadIdentity();// apply 'camera' manipulations:// e.g. // glRotate*(x,...);// glRotate*(y,...);// glRotate*(z,...);//// Then so that the new 'camera' transformations in the modelview matrix // apply to the direction, (as a minimum) call something like:   glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction);Can you show us your code that actually manipulates the Modelview matrix?   ;  I perhaps have trusted the Camera class too much. It is one I was given to start with and so I'm not really familiar with how it does everything. So, here is that function and those it uses:void Camera::setViewPoint(void){   gluLookAt(position[0], position[1], position[2], focusPoint[0], focusPoint[1], focusPoint[2], 0.0, 1.0, 0.0);}void Camera::rotateViewUp(void){focusPoint[1] = position[1] + (focusPoint[1] - position[1]) + sin(deg2rad(rotationIncrement));}void Camera::rotateViewDown(void){focusPoint[1] = position[1] + (focusPoint[1] - position[1]) - sin(deg2rad(rotationIncrement));}bool Camera::setRotationIncrement(GLfloat rotInc){if(rotInc > 0.0) {this->rotationIncrement = rotInc;return true;}else {return false;}}void Camera::setPosition( GLfloat x, GLfloat y, GLfloat z ){focusPoint[1] = y + (focusPoint[1] - position[1]);VisualObject::setPosition( x, y, z);this->rotate();} // end setPositionvoid Camera::setPosition( GLfloat* coordinates){focusPoint[1] = coordinates[1] + (focusPoint[1] - position[1]);VisualObject::setPosition( coordinates);this->rotate();} // end setPositionvoid Camera::move(GLfloat moveAngle){    position[0] += - moveIncrement * sin(deg2rad(moveAngle));position[1] = position[1];    position[2] += - moveIncrement * cos(deg2rad(moveAngle));rotate();}void Camera::rotate( void ){focusPoint[0] = position[0] - sin(deg2rad(this->azimuth));//focusPoint[1] = focusPoint[1];    focusPoint[2] = position[2] - cos(deg2rad(this->azimuth));};  I don't know?Here try this:simply changevoid Camera::setViewPoint(void){   gluLookAt(position[0], position[1], position[2], focusPoint[0], focusPoint[1], focusPoint[2], 0.0, 1.0, 0.0);}to:void Camera::setViewPoint(void){   // this explicitly ensures gluLookAt applies to the Modelview matrix    glMatrixMode (GL_MODELVIEW);   glLoadIdentity();   gluLookAt(position[0], position[1], position[2], focusPoint[0], focusPoint[1], focusPoint[2], 0.0, 1.0, 0.0);}thus you can surmise that the code:glMatrixMode (GL_PROJECTION);glLoadIdentity();explicitly selects the projection matrix stack as the one to which subsequent gl calls will apply to. Further more, you typically need to be careful and select the appropriate stack to fit your purpose. The redbook contains the old fashion conventional use of these stacks for more understanding of my suggestion (chapter 3?). You may then want to change your code more appropriately to reflect your understanding.yeah?e.g. Whereever/However you are dealing with the projection in you app: i.e. calling something like glOrtho(), glfrustum() or glPerspective, make sure you switch back to the projection matrix with glMatrixMode(GL_PROJECTION) beforehand.[Edited by - steven katic on April 4, 2009 7:39:28 PM];  The other thing is if you have: setViewPoint();float light0[] = {-10, 12.0, -10.0, 1.0};glLightfv(GL_LIGHT0, GL_POSITION, light0);float light1[] = {10, 12.0, -10.0, 1.0};glLightfv(GL_LIGHT1, GL_POSITION, light1);float light2[] = {-10, 12.0, -50.0, 1.0};glLightfv(GL_LIGHT2, GL_POSITION, light2);float light3[] = {10, 12.0, -50.0, 1.0};glLightfv(GL_LIGHT3, GL_POSITION, light3);// Draw the scene objectsdrawScene();andsetViewPoint() belongs to your Camera class: Does that mean you are actually drawing the scene within a function that belongs to the camera?   