13. OpenGL Lighting Types (Version 2.0)

Introduction

Previously, we talked about setting up some basic lights in OpenGL. Now, we’re going to expand on that by configuring the type of shading, the color of the light, the color of the object, and the type of light we’re using.

It’s important to understand that OpenGL supports several types of lights:
Specular: This type of light is responsible for highlights and shininess on objects. For example, when you light a sphere with both diffuse and specular light, the specular light adds the shiny highlights.
Diffuse: Diffuse light adds the base color of the light to your object. It determines how bright or colorful the light looks on the object’s surface.
Ambient: Ambient light fills the scene with light from all directions. It’s like the background light we see during the day, where the sun acts as a diffuse light but provides ambient illumination from all around.
Emissive: This type of light makes an object appear to emit its own light, like a glow. However, it doesn’t create a soft halo effect—just a steady radiance from the object itself.

These light types, combined with proper material settings, allow us to create complex lighting effects.

Setting Up Lights

For this tutorial, we’ll use two lights:

1. Diffuse Light (`GL_LIGHT0`)
This light provides color and brightness to objects.

2. Ambient Light (`GL_LIGHT1`)
This light illuminates everything equally, without a specific direction.

We start by enabling both lights:

  1. glEnable(GL_LIGHT0); // Enable diffuse light  
  2. glEnable(GL_LIGHT1); // Enable ambient light  

Next, we define the properties for each light.

Diffuse Light:
The diffuse light color is set to white:

  1. GLfloat dlr = 1.0; // Red component  
  2. GLfloat dlg = 1.0; // Green component  
  3. GLfloat dlb = 1.0; // Blue component  

Ambient Light:
The ambient light is also white, ensuring uniform illumination:

  1. GLfloat alr = 1.0; // Red component  
  2. GLfloat alg = 1.0; // Green component  
  3. GLfloat alb = 1.0; // Blue component  

Light Position:
Here’s where the light comes from:

  1. GLfloat lx = 0.0; // X position  
  2. GLfloat ly = 0.0; // Y position  
  3. GLfloat lz = 1.0; // Z position  
  4. GLfloat lw = 0.0; // W determines type (point or directional)  

So, what does this all mean?
– The diffuse light is white, set with `R = 1, G = 1, B = 1`.
– The ambient light is also white, which ensures everything has a minimum brightness.
– The light position is set at `X = 0, Y = 0, Z = 1, W = 0`. Setting `W = 0` makes this a directional light, like sunlight. If you want a point light (like a bulb), set `W = 1`, and the light will radiate outward from the position.

To apply these properties in OpenGL:

  1. GLfloat DiffuseLight[] = {dlr, dlg, dlb}; // Diffuse light color  
  2. GLfloat AmbientLight[] = {alr, alg, alb}; // Ambient light color  
  3. GLfloat LightPosition[] = {lx, ly, lz, lw}; // Light position  
  4.   
  5. glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);  // Set diffuse light  
  6. glLightfv(GL_LIGHT1, GL_AMBIENT, AmbientLight); // Set ambient light  
  7. glLightfv(GL_LIGHT0, GL_POSITION, LightPosition); // Set light position  

We’ve split these into two lights—`GL_LIGHT0` handles the diffuse light, while `GL_LIGHT1` handles the ambient light. Technically, you could combine these into a single light, but splitting them gives you more control.

Shading Model

Let’s briefly discuss shading. OpenGL provides two shading models:
GL_SMOOTH: This is the default and provides smooth transitions between light and dark across the surface. It works well for rounded objects like spheres.
GL_FLAT: Flat shading applies a single color to each polygon face, giving the object a faceted appearance.

For this example, we’re using smooth shading:

  1. glShadeModel(GL_SMOOTH); // Enable smooth shading  

Flat shading can be useful for certain visual styles or when you want to emphasize the polygonal nature of a model:

  1. glShadeModel(GL_FLAT); // Enable flat shading  

Bringing It All Together

To summarize:
1. `GL_LIGHT0` is our diffuse light, providing directional illumination.
2. `GL_LIGHT1` is our ambient light, ensuring a base level of brightness.
3. Smooth shading ensures light transitions are gradual, giving the scene a polished appearance.

Tutorial Code

Here’s the full code for this tutorial. It demonstrates how to configure and enable lights, adjust light properties dynamically, and apply smooth shading to a rotating cube.

  1. #include <GL/gl.h>  
  2. #include <GL/glut.h>  
  3.   
  4. // Angle of rotation  
  5. GLfloat angle = 0.0;  
  6.   
  7. // Diffuse light color variables  
  8. GLfloat dlr = 1.0, dlg = 1.0, dlb = 1.0;  
  9.   
  10. // Ambient light color variables  
  11. GLfloat alr = 1.0, alg = 1.0, alb = 1.0;  
  12.   
  13. // Light position variables  
  14. GLfloat lx = 0.0, ly = 0.0, lz = 1.0, lw = 0.0;  
  15.   
  16. // Draw the cube  
  17. void cube(void) {  
  18.     glRotatef(angle, 1.0, 0.0, 0.0); // Rotate on the X-axis  
  19.     glRotatef(angle, 0.0, 1.0, 0.0); // Rotate on the Y-axis  
  20.     glRotatef(angle, 0.0, 0.0, 1.0); // Rotate on the Z-axis  
  21.     glutSolidCube(2);                // Draw the cube  
  22. }  
  23.   
  24. void init(void) {  
  25.     glEnable(GL_DEPTH_TEST); // Enable depth testing  
  26.     glEnable(GL_LIGHTING);   // Enable lighting  
  27.     glEnable(GL_LIGHT0);     // Enable diffuse light  
  28.     glEnable(GL_LIGHT1);     // Enable ambient light  
  29.     glShadeModel(GL_SMOOTH); // Set smooth shading  
  30. }  
  31.   
  32. void display(void) {  
  33.     glClearColor(0.0, 0.0, 0.0, 1.0); // Clear screen to black  
  34.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  35.     glLoadIdentity();  
  36.   
  37.     GLfloat DiffuseLight[] = {dlr, dlg, dlb};  
  38.     GLfloat AmbientLight[] = {alr, alg, alb};  
  39.     GLfloat LightPosition[] = {lx, ly, lz, lw};  
  40.   
  41.     glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight);  
  42.     glLightfv(GL_LIGHT1, GL_AMBIENT, AmbientLight);  
  43.     glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);  
  44.   
  45.     gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // Camera setup  
  46.     cube(); // Draw the cube  
  47.     glutSwapBuffers();  
  48.     angle++; // Increment rotation angle  
  49. }  
  50.   
  51. void reshape(int w, int h) {  
  52.     glViewport(0, 0, (GLsizei)w, (GLsizei)h);  
  53.     glMatrixMode(GL_PROJECTION);  
  54.     glLoadIdentity();  
  55.     gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);  
  56.     glMatrixMode(GL_MODELVIEW);  
  57. }  
  58.   
  59. void keyboard(unsigned char key, int x, int y) {  
  60.     if (key == 'r') { dlr = 1.0; dlg = 0.0; dlb = 0.0; } // Red light  
  61.     if (key == 'g') { dlr = 0.0; dlg = 1.0; dlb = 0.0; } // Green light  
  62.     if (key == 'b') { dlr = 0.0; dlg = 0.0; dlb = 1.0; } // Blue light  
  63.     if (key == 'w') { ly += 10.0; } // Move light up  
  64.     if (key == 's') { ly -= 10.0; } // Move light down  
  65.     if (key == 'a') { lx -= 10.0; } // Move light left  
  66.     if (key == 'd') { lx += 10.0; } // Move light right  
  67. }  
  68.   
  69. int main(int argc, char** argv) {  
  70.     glutInit(&argc, argv);  
  71.     glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);  
  72.     glutInitWindowSize(500, 500);  
  73.     glutInitWindowPosition(100, 100);  
  74.     glutCreateWindow("OpenGL Lighting Example");  
  75.     init();  
  76.     glutDisplayFunc(display);  
  77.     glutIdleFunc(display);  
  78.     glutReshapeFunc(reshape);  
  79.     glutKeyboardFunc(keyboard);  
  80.     glutMainLoop();  
  81.     return 0;  
  82. }  

If you have any questions or encounter issues, feel free to email me at swiftless@gmail.com. Happy coding!

  • March 25, 2010
  • 8