PDA

View Full Version : Positioned light problem

Kojot
05-30-2010, 01:20 PM
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;

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);

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);

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(&amp;argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);

glutCreateWindow("3D");
init();

glutTimerFunc(25, idle, 0);

glutMainLoop();
return 0;
}

mhagain
05-31-2010, 01:36 AM
I don't know the inner workings of glutSolidTeapot but it seems reasonable to assume that it uses correct normals. All of your walls however, irrespective of the way they're facing, use the same normal vector. Is this intentional?

Kojot
05-31-2010, 06:05 AM
Yes, my purpose was to use the same normal vector to all my walls. I think I found answer to my question, but I want to verify it. My conclusion is:
If the wall faces to the direction of the light source - both sides of wall are bright, if not - both sides are dark. There is nothing something I expected, that one side of wall will be bright and the other will be dark.
Am I right?

BionicBytes
06-01-2010, 05:03 AM
Er, no!
Normals facing the light direction are lit, and normals facing away from the light are not lit. Generally the equation OpenGL uses for this (diffuse lighting) is N dot L which is dependant upon the cosine of the angle between the normal and the light vector.