I've been drawing Cornell box. I want to place light in my lamp(lamp is a white cube placed on the right wall). It will make an illusion that lamp is shining. But I can't place my light into the cube. I have tried to Set the view transform and then set light position, but it doesn't work.
Here is my simple code: ( lamp cube has been moved glTranslatef(0.63, 0.3, 0.0)
)
void display(void)
{
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, 600, 600);
glClearColor(0.32, 0.32, 0.32, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw cube
glPushMatrix();
glTranslatef(0.2, -0.3, 0.4);
glColor3d(1.0, 0.38, 0.0);
glutSolidCube(0.2);
glPopMatrix();
// draw sphere
glPushMatrix();
glTranslatef(0.2, -0.1, 0.4);
glColor3d(0.71, 0.0, 0.59);
glutSolidSphere(0.1,100,100);
glPopMatrix();
// draw parallelepiped
glPushMatrix();
glTranslatef(-0.2, -0.2, 0.25);
glRotatef(20, 0.0, 1.0, 0.0);
glColor3d(1.0, 0.38, 0.0);
glScalef(1, 1.8, 1);
glutSolidCube(0.2);
glPopMatrix();
// draw lamp
glPushMatrix();
glTranslatef(0.63, 0.3, 0.0);
glScalef(1.5, 0.3, 1);
glColor3d(1.0, 1.0, 1.0);
glutSolidCube(0.2);
glPopMatrix();
glBegin(GL_QUADS);
glNormal3f(0, 1.0, 0);
glColor3d(0.69, 0.69, 0.69); // bottom
glVertex3d(-0.5, -0.5, 0.5);
glVertex3d(-0.5, -0.5, -0.5);
glVertex3d(0.5, -0.5, -0.5);
glVertex3d(0.5, -0.5, 0.5);
glEnd();
glBegin(GL_QUADS);
glNormal3f(0, -1.0, 0);
glColor3d(0.69, 0.69, 0.69); // top
glVertex3d(-0.5, 0.5, 0.5);
glVertex3d(-0.5, 0.5, -0.5);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(0.5, 0.5, 0.5);
glEnd();
glBegin(GL_QUADS);
glNormal3f(-1.0, 0.0, 0.0);
glColor3d(0.0, 0.79, 0.05); // right
glVertex3d(0.5, -0.5, 0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(0.5, -0.5, -0.5);
glEnd();
glBegin(GL_QUADS);
glNormal3f(1.0, 0.0, 0.0);
glColor3d(1.0, 0.16, 0.0); // left
glVertex3d(-0.5, -0.5, 0.5);
glVertex3d(-0.5, 0.5, 0.5);
glVertex3d(-0.5, 0.5, -0.5);
glVertex3d(-0.5, -0.5, -0.5);
glEnd();
glBegin(GL_QUADS);
glNormal3f(0.0, 0.0, 1.0);
glColor3d(0.69, 0.69, 0.69); // back
glVertex3d(-0.5, -0.5, -0.5);
glVertex3d(-0.5, 0.5, -0.5);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(0.5, -0.5, -0.5);
glEnd();
glFlush();
glPopMatrix();
glutSwapBuffers();
}
void Initialize() {
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
GLfloat global_ambient[] = { 0.1, 0.1, 0.1, 1.0 };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
GLfloat ambient[] = { 0.0,0.0,0.0,1.0 };
GLfloat diffuse[] = { 1.0,1.0,1.0,1.0 };
GLfloat spec[] = { 1,1,1,1 };
GLfloat specref[] = { 1,1,1,1 };
GLfloat lpos[] = { 0.0, 0.0, 0.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, spec);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specref);
glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 64);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
}
void exitFunc(unsigned char key, int x, int y) {
switch (key) {
case 27:
exit(0);
break;
}
}
void reshape(int w, int h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-0.35, 0.35, -0.35, 0.35, 1.2, 400.0);
glMatrixMode(GL_MODELVIEW);
glTranslatef(0, 0, -2);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutInitWindowPosition(0, 0);
glutCreateWindow("Cornell Box");
Initialize();
glutDisplayFunc(display);
glutKeyboardFunc(exitFunc);
glutReshapeFunc(reshape);
glutIdleFunc(display);
glutMainLoop();
return 0;
}
Note, that drawing by glBegin
/glEnd
sequences, the fixed function pipeline matrix stack and fixed function pipeline per vertex light model, is deprecated since decades.
Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.
Anyway, when the light position is set by glLightfv(GL_LIGHT0, GL_POSITION, pos)
, then
pos
is multiplied by the current model view matrix.
This means if the position is set before the model view matrix is set, then the light position is placed in absolut coordinates to the world.
If it is set after the model view matrix was set, then the light position can be set in the coordinate system of the model.
Set the light position when you draw the lamp, to the center of the "lamp":
// draw lamp
glPushMatrix();
glTranslatef(0.63, 0.3, 0.0);
glScalef(1.5, 0.3, 1);
GLfloat lpos[] = { 0.0, 0.0, 0.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
glColor3d(1.0, 1.0, 1.0);
glutSolidCube(0.2);
glPopMatrix();
The OpenGL fixed function pipeline calculates the light per vertex: Gouraud shading.
This may cause, that you can't "see" the light, if the light vector hits the vertex coordinate by a acute angle relative to the plane of the surface.
In your case the green wall is almost unlit, because the light source is almost directly on the wall. The lam itself is not lit, because the light source is inside the lamp and it is light from the backside.
See OpenGL Lighting on texture plane is not working
Change the light position slightly, to put it in front of the wall, and tessellate the right wall to 4 quads, to "see" what I mean:
GLfloat lpos[] = { -0.1, 0.0, 0.0, 1.0 };
// right
glBegin(GL_QUADS);
glNormal3f(-1.0, 0.0, 0.0);
glColor3d(0.0, 0.79, 0.05);
glVertex3d(0.5, 0.3, 0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, 0.0);
glVertex3d(0.5, 0.3, 0.0);
glVertex3d(0.5, 0.3, 0.0);
glVertex3d(0.5, 0.5, 0.0);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(0.5, 0.3, -0.5);
glVertex3d(0.5, -0.5, 0.5);
glVertex3d(0.5, 0.3, 0.5);
glVertex3d(0.5, 0.3, 0.0);
glVertex3d(0.5, -0.5, 0.0);
glVertex3d(0.5, -0.5, 0.0);
glVertex3d(0.5, 0.3, 0.0);
glVertex3d(0.5, 0.3, -0.5);
glVertex3d(0.5, -0.5, -0.5);
glEnd();