Here we’ll look at an example of a simple light. We draw a static ball in the middle that will serve us as a background. Four small balls will move around the big one and represent different lights. These small balls are not actually lights, but are there to show the color and position of the light.
Read also: How to draw a Space Cube in OpenGL
To create different lights we operate with to the most important light types: diffuse and specular light.
GLfloat lightDiff0[] = { 1.0, 1.0, 1.0, 1.0 }; // 0 white
GLfloat lightSpec0[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lightDiff1[] = { 1.0, 0.0, 0.0, 1.0 }; // 1 red
GLfloat lightSpec1[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lightDiff2[] = { 0.0, 1.0, 0.0, 1.0 }; // 2 green
GLfloat lightSpec2[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lightDiff3[] = { 0.0, 0.0, 1.0, 1.0 }; // 3 blue
GLfloat lightSpec3[] = { 1.0, 1.0, 1.0, 1.0 };
Diffuse light gives color and is a directional light cast to the object. Diffuse light can be described as the light that has a position in space and comes from a single direction. Specular light is also a directional type of light. It comes from one particular direction. The difference between the two is that specular light reflects off the surface in a sharp and uniform way.
In order to see the light on the screen we need to enable it in our program:
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHT2);
Now it’s time to apply the light to our balls. To do that we choose a light position, define which light types we are going to use at each ball and translate it all together to the chosen positions. Here is how it is going to look in openGL:
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0); // position
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiff0); // diffuse light
glLightfv(GL_LIGHT0, GL_SPECULAR, lightDiff0); //specular light
glTranslatef(lightPos0[0], lightPos0[1], lightPos0[2]); //translate it all together to position lightPos0
glColor3fv(lightDiff0); //color
glutSolidSphere(0.1, 6, 6); //ball
After we’ve chosen the light and applied it to our balls we probably want them to move around that big ball in the middle. Since this is an ordinary ball we need to use a combination of cos and sin functions to force the small balls to move around the big one.
Read also: How to draw a robot hand in OpenGL
float x,y,z,len;
x = sin(a/17); y = sin(a/23), z = cos(-a/31); len = sqrt(x*x+y*y+z*z);
GLfloat lightPos0[] = {1.5*x/len, 1.5*y/len, 1.5*z/len, 1.0};
GLfloat lightPos1[] = {sin(a+18), sin(a+24)+cos(a+28), cos(-a+32), 1.0};
GLfloat lightPos2[] = {sin(a+19), sin(a+25)+cos(a+29), cos(-a+33), 1.0};
GLfloat lightPos3[] = {sin(a+20), sin(a+26)+cos(a+30), cos(-a+34), 1.0};
Complete source for this example
GLfloat lightDiff0[] = { 1.0, 1.0, 1.0, 1.0 }; // 0 white
GLfloat lightSpec0[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lightDiff1[] = { 1.0, 0.0, 0.0, 1.0 }; // 1 red
GLfloat lightSpec1[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lightDiff2[] = { 0.0, 1.0, 0.0, 1.0 }; // 2 green
GLfloat lightSpec2[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat lightDiff3[] = { 0.0, 0.0, 1.0, 1.0 }; // 3 blue
GLfloat lightSpec3[] = { 1.0, 1.0, 1.0, 1.0 };
float a=0; // counter
void display(void)
{
a+=0.1;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(5,0,5, 0,0,0, 0,1,0);
glDisable(GL_LIGHTING); // disable the light while setting it up
// calculate position of the light
float x,y,z,len;
x = sin(a/17); y = sin(a/23), z = cos(-a/31); len = sqrt(x*x+y*y+z*z);
GLfloat lightPos0[] = {1.5*x/len, 1.5*y/len, 1.5*z/len, 1.0};
GLfloat lightPos1[] = {sin(a+18), sin(a+24)+cos(a+28), cos(-a+32), 1.0};
GLfloat lightPos2[] = {sin(a+19), sin(a+25)+cos(a+29), cos(-a+33), 1.0};
GLfloat lightPos3[] = {sin(a+20), sin(a+26)+cos(a+30), cos(-a+34), 1.0};
glPushMatrix(); // white
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiff0);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightDiff0);
glTranslatef(lightPos0[0], lightPos0[1], lightPos0[2]);
glColor3fv(lightDiff0); glutSolidSphere(0.1, 6, 6);
glPopMatrix();
glPushMatrix(); // red
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDiff1);
glLightfv(GL_LIGHT1, GL_SPECULAR, lightSpec1);
glTranslatef(lightPos1[0], lightPos1[1], lightPos1[2]);
glColor3fv(lightDiff1); glutSolidSphere(0.1, 6, 6);
glPopMatrix();
glPushMatrix(); // green
glLightfv(GL_LIGHT2, GL_POSITION, lightPos2);
glLightfv(GL_LIGHT2, GL_DIFFUSE, lightDiff2);
glLightfv(GL_LIGHT2, GL_SPECULAR, lightSpec2);
glTranslatef(lightPos2[0], lightPos2[1], lightPos2[2]);
glColor3fv(lightDiff2); glutSolidSphere(0.1, 6, 6);
glPopMatrix();
glPushMatrix(); // blue
glLightfv(GL_LIGHT3, GL_POSITION, lightPos3);
glLightfv(GL_LIGHT3, GL_DIFFUSE, lightDiff3);
glLightfv(GL_LIGHT3, GL_SPECULAR, lightSpec3);
glTranslatef(lightPos3[0], lightPos3[1], lightPos3[2]);
glColor3fv(lightDiff3); glutSolidSphere(0.1, 6, 6);
glPopMatrix();
glEnable(GL_LIGHTING); // enable the light when drawing the big ball
// draw the big ball in the middle
glPushMatrix();
glColor3f(1, 1, 0.1);
glutSolidSphere(1, 16, 16);
glPopMatrix();
Sleep(9); glutSwapBuffers();
}
void reshape(int w, int h)
{
if (h == 0) h = 1;
GLdouble ratio = 1.0f * w / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45.0, ratio, 0.1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(640, 480);
glutCreateWindow("Lys og kuler");
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
// enable light
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHT2);
// set up callbacks
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(display);
// start the program
glutMainLoop();
}
See Also
- - compile_commands.json with CMake
- - Left Arrow Operator
- - Forward to fmt::format
- - Is C++ your favorite programing language?
- - Vcpkg and Cmake