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:
glEnable(GL_LIGHT0); // Enable diffuse light glEnable(GL_LIGHT1); // Enable ambient light
Next, we define the properties for each light.
Diffuse Light:
The diffuse light color is set to white:
GLfloat dlr = 1.0; // Red component GLfloat dlg = 1.0; // Green component GLfloat dlb = 1.0; // Blue component
Ambient Light:
The ambient light is also white, ensuring uniform illumination:
GLfloat alr = 1.0; // Red component GLfloat alg = 1.0; // Green component GLfloat alb = 1.0; // Blue component
Light Position:
Here’s where the light comes from:
GLfloat lx = 0.0; // X position GLfloat ly = 0.0; // Y position GLfloat lz = 1.0; // Z position 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:
GLfloat DiffuseLight[] = {dlr, dlg, dlb}; // Diffuse light color GLfloat AmbientLight[] = {alr, alg, alb}; // Ambient light color GLfloat LightPosition[] = {lx, ly, lz, lw}; // Light position glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight); // Set diffuse light glLightfv(GL_LIGHT1, GL_AMBIENT, AmbientLight); // Set ambient light 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:
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:
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.
#include <GL/gl.h> #include <GL/glut.h> // Angle of rotation GLfloat angle = 0.0; // Diffuse light color variables GLfloat dlr = 1.0, dlg = 1.0, dlb = 1.0; // Ambient light color variables GLfloat alr = 1.0, alg = 1.0, alb = 1.0; // Light position variables GLfloat lx = 0.0, ly = 0.0, lz = 1.0, 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 depth testing glEnable(GL_LIGHTING); // Enable lighting glEnable(GL_LIGHT0); // Enable diffuse light glEnable(GL_LIGHT1); // Enable ambient light glShadeModel(GL_SMOOTH); // Set smooth shading } void display(void) { glClearColor(0.0, 0.0, 0.0, 1.0); // Clear screen to black glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); GLfloat DiffuseLight[] = {dlr, dlg, dlb}; GLfloat AmbientLight[] = {alr, alg, alb}; GLfloat LightPosition[] = {lx, ly, lz, lw}; glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseLight); glLightfv(GL_LIGHT1, GL_AMBIENT, AmbientLight); glLightfv(GL_LIGHT0, GL_POSITION, LightPosition); gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // Camera setup cube(); // Draw the cube glutSwapBuffers(); angle++; // Increment rotation angle } void reshape(int w, int h) { glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); } void keyboard(unsigned char key, int x, int y) { if (key == 'r') { dlr = 1.0; dlg = 0.0; dlb = 0.0; } // Red light if (key == 'g') { dlr = 0.0; dlg = 1.0; dlb = 0.0; } // Green light if (key == 'b') { dlr = 0.0; dlg = 0.0; dlb = 1.0; } // Blue light if (key == 'w') { ly += 10.0; } // Move light up if (key == 's') { ly -= 10.0; } // Move light down if (key == 'a') { lx -= 10.0; } // Move light left if (key == 'd') { lx += 10.0; } // Move light right } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow("OpenGL Lighting Example"); init(); glutDisplayFunc(display); glutIdleFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMainLoop(); return 0; }
If you have any questions or encounter issues, feel free to email me at swiftless@gmail.com. Happy coding!
nice tutorials for the beginners….
nice tutor atlest hlping my work here
Great help with my work. Dont know where id be without this
Shall be visiting these tutorials often =D
Just add glutDisplayFunc(display) to the main function.
good tutos, but the code dont run. thanks anyway.
Hey Ferchoff,
It does run, if you are having problems, then it’s with your setup.
Cheers,
Swiftless
What doesn’t run? some of them come up with errors but are easy to fix so i don’t see why you will have any trouble?
Awesome tutorials so far. They’re great for total OpenGL beginners.