Basic lighting doesn't work

Hi,

I’m a very new beginner to OpenGL. I’m trying to add a light source that points to a specific location on my plane surface containing 2 axes (X and Y), which means it appears like a cone.

However, the code below doesn’t work the way I want it to, and I’m not really sure why, since the light just scatters all over the surface of the plane.


void init_light()
{
	GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
	GLfloat mat_shininess[] = { 50.0 };
	GLfloat light_position[] = { 1.0, 1.0, 1.0, 1.0 };
	glClearColor (0.0, 0.0, 0.0, 0.0);
	glShadeModel (GL_SMOOTH);

	glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
	glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
	glLightfv(GL_LIGHT0, GL_POSITION, light_position);

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);
	}


void display() {
      computeCameraPosition();
      glClearColor(0.1, 0.1, 0.1, 1.0);
      /* Clear frame buffer and z buffer */
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      gluLookAt(eye[0], eye[1], eye[2], 
              centroid[0], centroid[1], centroid[2], 
              yaxis[0], yaxis[1], yaxis[2]); 
      
      drawAxes();
       
      glFlush();
      glutSwapBuffers();
}

int main(int argc, char **argv) {

      glutInit(&argc, argv);
      glutInitWindowSize(800, 800);
      glutInitWindowPosition (200, 100);
      glutCreateWindow("Scene Editor");
      
      init_light();
      
      glutDisplayFunc(display);
      // glutReshapeFunc(myReshape); - leave it for a while
      glutMainLoop();
}

First of all, take a look at OpenGL Programming Guide Ch05

  1. The light is positioned somewhere above and to the right side of the viewer. Is it what you want to achieve?

  2. You didn’t create a spotlight (if you want a cone-like effect you have to define at least GL_SPOT_CUTOFF and GL_SPOT_DIRECTION).

  3. Did you tessellate an object which you want to illuminate enough? The lighting effect is calculated only in vertices in fixed functionality. You need to tessellate objects or switch to per-pixel lighting and shaders.

  4. Don’t expect to have a volumetric effect of your light source.

Thanks for replying me :slight_smile: I have just changed my code, the one above seems a bit incorrect.

void init_light()
{
	GLfloat spot_direction[] = { 1.0, 1.0, 0.0 };
	glLightfv( GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction );
	glLightf( GL_LIGHT0, GL_SPOT_EXPONENT, 2.0 );
	glLightf( GL_LIGHT0, GL_SPOT_CUTOFF, 45.0 );

	glShadeModel(GL_SMOOTH);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_COLOR_MATERIAL);
}

So I set a spotlight pointing to the plane on the right-hand side (as what you said). But the result is still the same (the light is kinda scattered). I have a black surface with 2 white axes (XY), after initializing the light, the whole surface seems to be covered by a light layer that makes it gray.

Any ideas?

  1. Did you tessellate an object which you want to illuminate enough? The lighting effect is calculated only in vertices in fixed functionality. You need to tessellate objects or switch to per-pixel lighting and shaders.

Sorry didn’t notice this one, will try to figure it out.

By the way, how can I draw a rectangle shape as a ground (with 4 vertices) while having the camera setup as modelview mode. For example, in this snippet of code, the white rectangle shape isn’t drawn.



void display() {
	computeCameraPosition();
	glClearColor(0.1, 0.1, 0.1, 1.0);
	/* Clear frame buffer and z buffer */
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(eye[0], eye[1], eye[2], 
	      centroid[0], centroid[1], centroid[2], 
	      yaxis[0], yaxis[1], yaxis[2]); 

	glTranslatef(0.0f, 0.0f, -5.0f);

	glBegin(GL_QUADS);

	glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner  
	glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner  
	glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner  
	glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner  
 
	glEnd();

	drawAxes();

	glFlush();
	glutSwapBuffers();
}

The reason is explained in the third comment; the one that you didn’t notice.

The lighting equation is calculated in the vertices only. If you have just 4 vertices and the light source is somewhere near the surface, the whole surface will be dimly illuminated since all the vertices are distant from the light source (although the surface is actually near).

Suggestion: Instead of a single quad draw a matrix of quads (or better quad strips) and observe the difference.

In old games, when only fixed functionality existed, programmers used tricks to achieve that kind of effects with less polygon complexity. One of the best was to use multitexturing.

Here is what I tried, using glutSolidCube() built-in shape drawer, but still cannot solve it, the light still scatters.

Before that I tried putting together 4 quad strips to form the ground, nothing changes though… Probably the problem is with the lighting function?

void init_light()
{
	
GLfloat light0_position[] = { -2.0, 2.0, 1.0, 1.0 };
GLfloat spot_direction[] = { -1.0, -1.0, 0.0 };

glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0);

glEnable(LIGHTING);
glEnable(GL_LIGHT0);

}


void display() {

	computeCameraPosition();
	glClearColor(0.9, 0.9, 0.9, 1.0);
	/* Clear frame buffer and z buffer */
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(eye[0], eye[1], eye[2], 
	      centroid[0], centroid[1], centroid[2], 
	      yaxis[0], yaxis[1], yaxis[2]); 
	
	//glTranslatef(0.0f, 0.0f, -5.0f);
	drawAxes();
	
	
	glBegin(GL_QUAD_STRIP);
	
	glColor3f(0.7, 0.7, 0.7);
	glVertex3f(-1.0f, 0.0f, 0.0f);
	glVertex3f(-1.0f, 1.0f, 0.0f);
	glVertex3f(0.0f, 0.0f, 0.0f);
	glVertex3f(0.0f, 1.0f, 0.0f);

	glVertex3f(1.0f, 0.0f, 0.0f);
	glVertex3f(1.0f, 1.0f, 0.0f);
	
	glVertex3f(-1.0f, -1.0f, 0.0f);
	glVertex3f(-1.0f, 0.0f, 0.0f);
	glVertex3f(0.0f, -1.0f, 0.0f);
	glVertex3f(0.0f, 0.0f, 0.0f);

	glVertex3f(0.0f, -1.0f, 0.0f);
	glVertex3f(0.0f, 0.0f, 0.0f);
	glVertex3f(1.0f, -1.0f, 0.0f);
	glVertex3f(1.0f, 0.0f, 0.0f);
	
	glEnd();

	glFlush();
	glutSwapBuffers();
}

I think that both the position and the orientation of the light are wrong.

  1. Your light source is always on the same position relative to the viewer. That means: the light source position in the world space changes along with the viewer position (defined with gluLookAt)

  2. The light is oriented down and to the left side of the viewer.

  3. Since you didn’t give (eye[0], eye[1], eye[2]) it is up to you to determine how much light comes to the plate infant of the viewer if any.

By the way, the code you have posted on the gamedev contains some interesting details missing here.

Actually all the camera rotating is there but I haven’t implemented it yet, so even when I comment them out, there’s still no affect. I just changed the value of light source position to:

GLfloat spot_direction[] = { 0.0, 0.0, 0.0 };

But nothing changes.

By the way, the code you have posted on the gamedev contains some interesting details missing here.

You mean glutSolidCube(2.0); or?

Quite tired of it already… have no idea why I picked this course LOL.

Certainly, because you set the transformation on the wrong place and the model-view matrix used for the scene drawing is not affected by that transformation.

Sure, because the presented code defines a singularity. The spot_direction is a vector. You have defined a vector without the direction.

Please, before going any further, read chapters 3 and 5 from the Red book.