12. OpenGL Materials and Lighting (Version 2.0)
Introduction
Lighting and materials go hand-in-hand when it comes to creating visually stunning 3D objects in OpenGL. While setting up lights allows us to illuminate objects, defining materials determines how those objects interact with the light.
In this tutorial, we’ll dive into adding colors to objects and manipulating material properties like shininess and light reflectivity. We’ll also explore the interplay between colored lights and materials to achieve realistic effects.
Light Basics
Before we get started, it’s important to understand how light behaves differently from paint. While mixing paints follows the rules of subtraction (e.g., red + green = brown), light follows the rules of addition (e.g., red + green = yellow). Here are some examples to clarify the difference:
Paint:
Red + Green = Brown
Blue + Yellow = Green
White + Blue = Light Blue
Red + White = Light Red
Lights:
Red + Green = Yellow
Blue + Yellow = White
White + Blue = Light Blue
Red + White = Yellow
This difference significantly impacts how colored lights interact with colored objects in OpenGL.
Usage
OpenGL allows us to control how materials interact with lights through properties such as diffuse, specular, and emissive lighting. Additionally, the shininess factor defines the reflectivity of an object.
Here’s an overview of key material properties:
– **Diffuse:** Determines the base color of the object when exposed to direct light.
– **Specular:** Controls the shininess and the amount of light reflection.
– **Emissive:** Adds self-illumination, making the object appear as if it’s glowing.
The shininess factor ranges from 0 to 128, where 0 is the shiniest.
Coding
To start, let’s define the colors and properties for materials and lights:
GLfloat redDiffuseMaterial[] = {1.0, 0.0, 0.0}; // Red material GLfloat whiteSpecularMaterial[] = {1.0, 1.0, 1.0}; // White specular material GLfloat greenEmissiveMaterial[] = {0.0, 1.0, 0.0}; // Green emissive material GLfloat whiteSpecularLight[] = {1.0, 1.0, 1.0}; // White light specular GLfloat blackAmbientLight[] = {0.0, 0.0, 0.0}; // Ambient light (black) GLfloat whiteDiffuseLight[] = {1.0, 1.0, 1.0}; // White diffuse light GLfloat blankMaterial[] = {0.0, 0.0, 0.0}; // Blank material for reset GLfloat mShininess[] = {128}; // Maximum shininess
Now, let’s assign these properties to lights and materials in OpenGL:
glLightfv(GL_LIGHT0, GL_SPECULAR, whiteSpecularLight); glLightfv(GL_LIGHT0, GL_AMBIENT, blackAmbientLight); glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteDiffuseLight); // Set materials dynamically glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, whiteSpecularMaterial); glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mShininess); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, redDiffuseMaterial); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, greenEmissiveMaterial);
Tutorial Code
Here’s the full code for setting up lights, materials, and keyboard interactions:
#include <GL/gl.h> #include <GL/glut.h> GLfloat angle = 0.0; GLfloat redDiffuseMaterial[] = {1.0, 0.0, 0.0}; // Red material GLfloat whiteSpecularMaterial[] = {1.0, 1.0, 1.0}; // White material GLfloat greenEmissiveMaterial[] = {0.0, 1.0, 0.0}; // Green material GLfloat whiteSpecularLight[] = {1.0, 1.0, 1.0}; // White light specular GLfloat blackAmbientLight[] = {0.0, 0.0, 0.0}; // Black ambient light GLfloat whiteDiffuseLight[] = {1.0, 1.0, 1.0}; // White diffuse light GLfloat blankMaterial[] = {0.0, 0.0, 0.0}; // Blank material GLfloat mShininess[] = {128}; // Maximum shininess bool diffuse = false; bool emissive = false; bool specular = false; void init() { glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); } void light() { glLightfv(GL_LIGHT0, GL_SPECULAR, whiteSpecularLight); glLightfv(GL_LIGHT0, GL_AMBIENT, blackAmbientLight); glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteDiffuseLight); } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); light(); glTranslatef(0, 0, -5); glRotatef(angle, 1, 1, 1); glutSolidTeapot(2); glutSwapBuffers(); 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 == 's') { if (!specular) { specular = true; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, whiteSpecularMaterial); glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mShininess); } else { specular = false; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, blankMaterial); glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, blankMaterial); } } if (key == 'd') { if (!diffuse) { diffuse = true; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, redDiffuseMaterial); } else { diffuse = false; glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, blankMaterial); } } if (key == 'e') { if (!emissive) { emissive = true; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, greenEmissiveMaterial); } else { emissive = false; glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, blankMaterial); } } } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow("A basic OpenGL Window"); init(); glutDisplayFunc(display); glutIdleFunc(display); glutKeyboardFunc(keyboard); glutReshapeFunc(reshape); glutMainLoop(); return 0; }
If you have any questions or issues with this tutorial, feel free to email me at swiftless@gmail.com. Happy coding!
sir everything is just working fine but my keyboard function only detecting the key which is responsible for specularity and it is not detecting the other two keys …. i tried printing out in output window and the specularity key is printing but not he other two key which is diffuse and emission
Im obliged for the blog.Much thanks again. Fantastic.
I was wondering is it just me or does the red diffuse material not do anything? I have the code written properly as I’ve checked and triple checked, but when I press d, nothing happens. Isn’t the color of the object supposed to change red or something? It remains white when I press d.
Thanks for the tutorials; lighting & materials helped a lot in my graphics class.