I don’t have any experience in setting up OpenGL lights. Probably I made a simple mistake, but I am not able to find it.
There is a code of my application. Application let user to move using arrow keys and rotate by clicking and mouse moving.
I set up lights and drew sphere in place where the positioned light source is placed. I expected, that some sides of walls will be bright, and others will be dark. The problem is both sides of some walls are bright, and both sides of others are dark.
You can change drawing walls into drawing teapots and then the problem dissapears.
#include <math.h>
#include <stdlib.h>
#include <GL/glut.h>
//horizontal camera angle
float angle = 0.0;
//vertical camera angle
float angleV = 0.0;
//position of the camera
float x = 5.0f, y = 2.0f, z = 5.0f;
//vector - shows camera direction
float lx = 0.0f, ly = 0.0f, lz = -1.0f;
float rotationSpeed = 0.0f;
float moveSpeed= 0.0f;
int mouseX = 0.0f;
int mouseY = 0.0f;
const float mapSizeX = 1000.0f, mapSizeZ = 1000.0f;
void wall()
{
const float height = 5.0;
const float width = 6.0;
glBegin(GL_QUADS);
glNormal3f(0.0, 0.0, 1.0);
glColor3f(1.0, 1.0, 1.0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-width/2.0, 0.0, 0.0);
glTexCoord2f(1.0f, 0.0f); glVertex3f(width/2.0, 0.0, 0.0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(width/2.0, height, 0.0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-width/2.0, height, 0.0);
glEnd();
glDisable(GL_TEXTURE_2D);
}
void lights ()
{
GLfloat lightColor0[] = {0.9f, 0.9f, 0.9f, 1.0f};
GLfloat lightPos0[] = {5.0f, 5.0f, 12.0f, 1.0f};
//GLfloat lightPos0[] = {5.0f, 5.0f, 12.0f, 0.0f};
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor0);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
glPushMatrix();
glColor3f(1.0, 1.0, 1.0);
glTranslatef(lightPos0[0], lightPos0[1], lightPos0[2]);
glutWireSphere(2.0, 100, 100);
glPopMatrix();
}
void refreshMyRoation (float angleArg)
{
lx = sin(angle);
ly = -sin(angleV);
lz = -cos(angle);
}
void refreshMyPosition (float speedArg)
{
x = x + moveSpeed*(lx);
y = y + moveSpeed*(ly);
z = z + moveSpeed*(lz);
}
void drawScene()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.1, 0.1, 0.1, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gluLookAt(x, y, z, x + lx, y + ly, z + lz, 0.0f, 1.0f, 0.0f);
lights();
for(int i = -5; i < 5; i++)
for(int j = -3; j < 3; j++)
{
glPushMatrix();
glTranslatef((float)i*30.0, 0, (float)j*30.0);
wall();
//glTranslatef(0.0, 1.0, 0.0);
//glutSolidTeapot(2.0);
glPopMatrix();
}
glutSwapBuffers();
}
void pressKey(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_LEFT : rotationSpeed = -0.05f; break;
case GLUT_KEY_RIGHT : rotationSpeed = 0.05f; break;
case GLUT_KEY_UP : moveSpeed = 1.1; break;
case GLUT_KEY_DOWN : moveSpeed = -1.1; break;
}
glutPostRedisplay();
}
void releaseKey(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_LEFT :
case GLUT_KEY_RIGHT : rotationSpeed = 0.0f; break;
case GLUT_KEY_DOWN :
case GLUT_KEY_UP : moveSpeed = 0.0f; break;
}
glutPostRedisplay();
}
void mouseMotion (int xpos, int ypos)
{
angle += 0.01f*(xpos - mouseX);
angleV += 0.01f*(ypos - mouseY);
mouseX = xpos;
mouseY = ypos;
}
void mouseButtons (int button, int state, int xclick, int yclick)
{
if(state == GLUT_DOWN)
{
mouseX = xclick;
mouseY = yclick;
}
}
void reshape(int w, int h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45, ((float)w) / ((float)h), 0.5, 1000);
}
void idle (int value) {
angle += rotationSpeed;
refreshMyPosition(moveSpeed);
refreshMyRoation(angle);
glutPostRedisplay();
glutTimerFunc(15, idle, 0);
}
void init ()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glutDisplayFunc(drawScene);
glutIgnoreKeyRepeat(1);
glutSpecialFunc(pressKey);
glutSpecialUpFunc(releaseKey);
glutMotionFunc(mouseMotion);
glutMouseFunc(mouseButtons);
glutReshapeFunc(reshape);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("3D");
init();
glutTimerFunc(25, idle, 0);
glutMainLoop();
return 0;
}