How to work with the different lighting types in the OpenGL API

Back to OpenGL Tutorial Index

Previously we spoke about setting up some basic lights.

Here we are going to take that to the next level and set the type
of shading, the colour of the light, the colour of our object
and the type of light in which we are using.

Now lets take into account that OpenGL has different types of lights.
They are:
Specular
Diffuse
Ambient
Emissive

A specular light is a light that sets highlights and often the shininess of
an object. So if you light a sphere with a diffuse light and a specular light
the specular light will add the highlights.

A diffuse light, is a light that comes from a certain point. Like the sun.

An ambient light is a light that lights up the scene from every direction.
So even though the sun is a diffuse light, it acts like an ambient light
to us who are on the surface of the earth and during the day, see light
everywhere.

Now an emissive light is a light which radiates from an object. Like a glow.

Now first off we need variables to hold our light colours and positions.
I am setting these up in our Display function as they are requiring variables
which I am setting up at runtime.
set DiffuseLight[] to the specified values
GLfloat DiffuseLight[] = {dlr, dlg, dlb};
set AmbientLight[] to the specified values
GLfloat AmbientLight[] = {alr, alg, alb};
set the LightPosition to the specified values
GLfloat LightPosition[] = {lx, ly, lz, lw};

Now I am going to use 2 lights here, so I enable them with:
glEnable (GL_LIGHT0);
glEnable (GL_LIGHT1);

Next I am setting the light variables:

diffuse light color variables
GLfloat dlr = 1.0;
GLfloat dlg = 1.0;
GLfloat dlb = 1.0;

ambient light color variables
GLfloat alr = 1.0;
GLfloat alg = 1.0;
GLfloat alb = 1.0;

light position variables
GLfloat lx = 0.0;
GLfloat ly = 0.0;
GLfloat lz = 1.0;
GLfloat lw = 0.0;

As you can see, I have made the diffuse light white by setting it to:
R = 1, G = 1, B = 1
I have then done the same with the ambient light.

Next I have set the position so that it is placed at:
X = 0, Y = 0, Z = 1
Now as for the fourth variable, that sets whether or not we want a point light.

Now to get this to take effect in our application I set up the lights with:
Set our diffuse light to our diffuse light color
glLightfv (GL_LIGHT0, GL_DIFFUSE, DiffuseLight);
Set our ambient light to our ambient light color
glLightfv (GL_LIGHT1, GL_AMBIENT, AmbientLight);
Move the light to the position we have set
glLightfv (GL_LIGHT0, GL_POSITION, LightPosition);

So light0 is our diffuse light and light1 is our ambient light.
You could technically set all these values to one light, but I have
done it in 2.

Now as for the shade model, you can set this to either:
GL_SMOOTH
or
GL_FLAT

Smooth allows for a nice transition from the dark colour to the light
colour, while flat makes the side, 1 colour, instead of a nice gradient.

If you have any queries over this tutorial, email me at swiftless@gmail.com

#include <GL/gl.h>
#include <GL/glut.h>

//angle of rotation
GLfloat angle = 0.0;

//diffuse light color variables
GLfloat dlr = 1.0;
GLfloat dlg = 1.0;
GLfloat dlb = 1.0;

//ambient light color variables
GLfloat alr = 1.0;
GLfloat alg = 1.0;
GLfloat alb = 1.0;

//light position variables
GLfloat lx = 0.0;
GLfloat ly = 0.0;
GLfloat lz = 1.0;
GLfloat lw = 0.0;

//draw the cube
void cube (void) {
glRotatef(angle, 1.0, 0.0, 0.0); //rotate on the x axis
glRotatef(angle, 0.0, 1.0, 0.0); //rotate on the y axis
glRotatef(angle, 0.0, 0.0, 1.0); //rotate on the z axis
glutSolidCube(2); //draw the cube
}

void init (void) {
glEnable (GL_DEPTH_TEST); //enable the depth testing
glEnable (GL_LIGHTING); //enable the lighting
glEnable (GL_LIGHT0); //enable LIGHT0, our Diffuse Light
glEnable (GL_LIGHT1); //enable LIGHT1, our Ambient Light
glShadeModel (GL_SMOOTH); //set the shader to smooth shader
}

void display (void) {
glClearColor (0.0,0.0,0.0,1.0); //clear the screen to black
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //clear the color buffer and the depth buffer
glLoadIdentity();
GLfloat DiffuseLight[] = {dlr, dlg, dlb}; //set DiffuseLight[] to the specified values
GLfloat AmbientLight[] = {alr, alg, alb}; //set AmbientLight[] to the specified values
GLfloat LightPosition[] = {lx, ly, lz, lw}; //set the LightPosition to the specified values
glLightfv (GL_LIGHT0, GL_DIFFUSE, DiffuseLight); //change the light accordingly
glLightfv (GL_LIGHT1, GL_AMBIENT, AmbientLight); //change the light accordingly
glLightfv (GL_LIGHT0, GL_POSITION, LightPosition); //change the light accordingly
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); //camera position, x,y,z, looking at x,y,z, Up Positions of the camera
cube(); //call the cube drawing function
glutSwapBuffers(); //swap the buffers
angle++; //increase the angle
}

void reshape (int w, int h) {
glViewport (0, 0, (GLsizei)w, (GLsizei)h); //set the viewport to the current window specifications
glMatrixMode (GL_PROJECTION); //set the matrix to projection
glLoadIdentity ();
gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0); //set the perspective (angle of sight, width, height, , depth)
glMatrixMode (GL_MODELVIEW); //set the matrix back to model
}

void keyboard (unsigned char key, int x, int y) {
if (key=='r') {
dlr = 1.0; //change light to red
dlg = 0.0;
dlb = 0.0;
}
if (key=='g') {
dlr = 0.0; //change light to green
dlg = 1.0;
dlb = 0.0;
}
if (key=='b') {
dlr = 0.0; //change light to blue
dlg = 0.0;
dlb = 1.0;
}
if (key=='w') {
ly += 10.0; //move the light up
}
if (key=='s') {
ly -= 10.0; //move the light down
}
if (key=='a') {
lx -= 10.0; //move the light left
}
if (key=='d') {
lx += 10.0; //move the light right
}
}

int main (int argc, char **argv) {
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH); //set the display to Double buffer, with depth
glutInitWindowSize (500, 500); //set the window size
glutInitWindowPosition (100, 100); //set the position of the window
glutCreateWindow ("A basic OpenGL Window"); //the caption of the window
init (); //call the init function
glutDisplayFunc (display); //use the display function to draw everything
glutIdleFunc (display); //update any variables in display, display can be changed to anyhing, as long as you move the variables to be updated, in this case, angle++;
glutReshapeFunc (reshape); //reshape the window accordingly
glutKeyboardFunc (keyboard); //check the keyboard
glutMainLoop (); //call the main loop
return 0;
}

Download C++ Source Code for this Tutorial

Download Visual Basic Source Code for this Tutorial

 

     

 

Copyright 2008, Donald Urquhart
Proudly supported by http://www.cdadc.com