Kinesia Online Course
Computer Graphics
Kinesia LLC, 2003

    1. Introduction
    2. Line Drawing
    3. Drawing Objects
    4. More Drawing Tools
    5. Normal Vectors and Polygonal Models of Surfaces
    6. Viewing I -- Affine Transformations
    7. Viewing II -- Projections
    8. Color
    9. Lighting
    10. Blending, antialiasing, fog ..
    11. Display Lists, Bitmaps and Images
    12. Texture Mapping
    13. Curves and Surfaces
    14. Games and SDL

    Lighting

    1. Importance of Lighting

    2. lighting and shading are important tools for making graphics images appear more realistic and more understandable

    3. provides crucial visual cues about the curvature and orientation of surfaces

    4. makes three-dimensionality apparent in a graphics image

      Figure A lit and an unlit sphere

    5. A Hidden-Surface Removal Survival Kit

    6. With shaded polygons, it becomes very important to draw the objects that are closer to our viewing position and to eliminate objects obscured by others nearer to the eye.

    7. Consider:
        while (1) { 
           get_viewing_point_from_mouse_position(); 
           glClear(GL_COLOR_BUFFER_BIT); 
           draw_3d_object_A(); 
           draw_3d_object_B(); 
        }

    8. One object may obscure the other.

    9. hidden-surface removal -- the elimination of parts of solid objects that are obscured by others, easiest to be done by using depth buffer ( also called z-buffer )

    10. A depth buffer works by associating a depth from the view plane with each pixel

    11. glClear( GL_DEPTH_BUFFER_BIT ) sets all pixels to the largest possible distance

      Before each pixel is drawn, a comparison is done with the depth value already stored at the pixel. If the new pixel is closer ( smaller value ), the new pixel's color and depth values replace those that are currently written into the pixel.

    12. Example:
        glutInitDisplayMode (GLUT_DEPTH | .... );
        glEnable(GL_DEPTH_TEST); 
        ... 
        while (1) { 
           glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
           get_viewing_point_from_mouse_position(); 
           draw_3d_object_A(); 
           draw_3d_object_B(); 
        }

    13. The Phong Lighting Model

      Simplest and by far the most popular, lighting and shading model

    14. All light sources are modeled as point light sources

    15. Light is modeled as consisting of Red, Green, Blue

    16. Apply superposition principle to calculate light reflection intensities independently for each light source and for each of the 3 color components ( R, G, B ), e.g. R = R1 + R2

    17. Treats light or illumination as being of three distinct kinds:

      • Ambient Light -- light that arrives equally from all directions, i.e. light that has been scattered so much by its environment that it is impossible to determine its direction

      • Diffuse Light -- light from a point source that will be reflected diffusely ( i.e. refelected evenly in all directions away from the surface )

      • Specular Light -- light from a point source that will be reflected specularly ( i.e. reflected in a mirror-like fashion, as from a shinny surface )

    18. Gives material properties to each surface:

      • Ambient Reflection Properties

      • Diffuse Reflection Properties

      • Specular Reflection Properties

      • Emissive Properties -- The emissivity of a surface controls how much light the surface emits in the absence of any incident light. Light emitted from a surface does not act as light source that illuminates other surfaces; instead, it only affects the color seen by the observer

    19. Ambient Reflection and Emissivity

        Iain = total intensity of incoming ambient light

        ca = reflectivity coefficient

        The intensity of outgoing light is

          Ia = ca Iain

        In addition, a surface can also be given an emissive intensity constant Ie which is equal to the light emitted by the surface


          Sphere with only ambient light

    20. Diffuse Reflection

        The intensity of outgoing light is

          Id = cd Idin cos θ

        where cos θ = |L.N|


          Diffuse light distribution


          Sphere with only diffuse light

    21. Specular Reflection

        The intensity of outgoing light is

          Is = cs Isin (cos α) f

        where α = angle between perfect reflection and the observing reflection
                  f = experimentally adjusted positive constant


          Specular light distribution


          Sphere with only specular light

      • Multiple Lights and Colors

          I = Ia + Id + Is + Ie


            Phong Distribution


              Sphere with Phong lighting
    22. Summary of Lighting in OpenGL

    23. To enable Phong lighting calculation:
        glEnable ( GL_LIGHTING );

    24. OpenGL includes eight point sources, they could be "turned on" by
        glEnable ( GL_LIGHTi );     //i = 0, 1, 2, .. 7

    25. Gourand shading can be turned on ( default ) or off by
        glShadeModel ( GL_FLAT );     //off

        glShadeModel ( GL_SMOOTH );     //on

        ( see smooth.cpp example in previous chapater. Gouraud interpolation is named after H. Gourand, who proposed linear interpolation in 1971 as a method of blending coloars across polygons. )

    26. Can rednder both faces ( front and back ) or one face ( default ) of polygons.
        glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );

    27. Specifies normal at a vertex and material properties by
        	glNormal3f( x, y, z );	//(x, y, z) is the normal
        	glMaterial*(...);	//multiple glMaterial command O.K.
        	glVertex*(...);		//vertex position
        	

    28. Setting light properties by, for example,
        	float color[4] = { r, g, b, a };
        	glLightModelfv ( GL_LIGHT_MODEL_AMBIENT, color );
        	
        The alpha component is for blending ( see next chapter ), which is usually set to 1.

    29. Setting light position by
        	float pos[4] = { x, y, z, w };
        	glLightfv ( GL_LIGHTi, GL_POSITION, pos );
        	
        if w ≠ 0, => positional light at position ( x/w, y/w, z/w )

        if w = 0, => directional light ( light source at infinity ), (x, y, z ) is the direction of the source

    30. Setting light intensity values ( colors ) by, for example,
        	float color[4] = { r, g, b, a };
        	glLightfv( GL_LIGHTi, GL_AMBIENT, color );
        	

    31. Setting material properties by, for example,
        	float color[4] = {r, g, b, a};
        	glMaterialfv ( GL_FRONT, GL_AMBIENT, color };
        or
        	glEnable( GL_COLOR_MATERIAL );
        
        then the glColor*() will affect material properties. You then code as
        
        	glNormal3f( x, y, z );
        	glColor3f( r, g, b );	//change reflectivity parameters
        	glVertex* ( .... );	
        	
    32. Simple Example: Rendering a Lit Sphere

      1. Define normal vectors for each vertex of all the objects. These normals determine the orientation of the object relative to the light sources. ( In our example, the normals are defined as part of the glutSolidSphere() )

      2. Create, select, and position one or more light sources.

      3. Create and select a lighting model, which defines the level of global ambient light and the effective location of the viewpoint (for the purposes of lighting calculations).

      4. Define material properties for the objects in the scene.

      //light.cpp
      #include <GL/glut.h>
      #include <stdlib.h>
      
      /*  Initialize material property, light source, lighting model,
       *  and depth buffer.
       */
      void init(void) 
      {
         GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
         GLfloat mat_shininess[] = { 50.0 };
         GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
         GLfloat light[] = { 1.0, 0.2, 0.2 };
         GLfloat lmodel_ambient[] = { 0.1, 0.1, 0.1, 1.0 };
         glClearColor (0.0, 0.0, 0.0, 0.0);
         glShadeModel (GL_SMOOTH);
      
         glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
         glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
         glLightfv(GL_LIGHT0, GL_POSITION, light_position);
      
         glLightfv(GL_LIGHT0, GL_DIFFUSE, light );
         glLightfv(GL_LIGHT0, GL_SPECULAR, light );
         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
      
         glEnable(GL_LIGHTING);
         glEnable(GL_LIGHT0);
         glEnable(GL_DEPTH_TEST);
      }
      
      void display(void)
      {
         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         glutSolidSphere (1.0, 20, 16);
         glFlush ();
      }
      
      void reshape (int w, int h)
      {
         glViewport (0, 0, (GLsizei) w, (GLsizei) h);
         glMatrixMode (GL_PROJECTION);
         glLoadIdentity();
         if (w <= h)
            glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,
               1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
         else
            glOrtho (-1.5*(GLfloat)w/(GLfloat)h,
               1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);
         glMatrixMode(GL_MODELVIEW);
         glLoadIdentity();
      }
      
      int main(int argc, char** argv)
      {
         glutInit(&argc, argv);
         glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
         glutInitWindowSize (500, 500); 
         glutInitWindowPosition (100, 100);
         glutCreateWindow (argv[0]);
         init ();
         glutDisplayFunc(display); 
         glutReshapeFunc(reshape);
         glutMainLoop();
         return 0;
      }
        

      void glLight{if}(GLenum light, GLenum pname, TYPE param);
      void glLight{if}v(GLenum light, GLenum pname, TYPE *param);

      Creates the light specified by light, which can be GL_LIGHT0, GL_LIGHT1, ... , or GL_LIGHT7. The characteristic of the light being set is defined by pname, which specifies a named parameter (see Table below). param indicates the values to which the pname characteristic is set; it's a pointer to a group of values if the vector version is used, or the value itself if the nonvector version is used. The nonvector version can be used to set only single-valued light characteristics.

      Parameter Name Default Value Meaning
      GL_AMBIENT (0.0, 0.0, 0.0, 1.0) ambient RGBA intensity of light
      GL_DIFFUSE (1.0, 1.0, 1.0, 1.0) diffuse RGBA intensity of light
      GL_SPECULAR (1.0, 1.0, 1.0, 1.0)     specular RGBA intensity of light
      GL_POSITION (0.0, 0.0, 1.0, 0.0) (x, y, z, w) position of light
      GL_SPOT_DIRECTION (0.0, 0.0, -1.0) (x, y, z) direction of spotlight
      GL_SPOT_EXPONENT     0.0 spotlight exponent
      (how concentrated is the light)
      GL_SPOT_CUTOFF 180.0 spotlight cutoff angle
      GL_CONSTANT_ATTENUATION 1.0 constant attenuation factor
      GL_LINEAR_ATTENUATION 0.0 linear attenuation factor
      GL_QUADRATIC_ATTENUATION   0.0 quadratic attenuation factor

      Position

      Spotlights

        glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0);
        GLfloat spot_direction[] = { -1.0, -1.0, 0.0 };
        glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);

      Attenuation

      For real-world lights, the intensity of light decreases as distance from the light increases. Since a directional light is infinitely far away, it doesn't make sense to attenuate its intensity over distance, so attenuation is disabled for a directional light. However, you might want to attenuate the light from a positional light. OpenGL attenuates a light source by multiplying the contribution of that source by an attenuation factor:

        attenuation factor =           1          
          kc + kld + kqd2
      where
      d = distance between the light's position and the vertex
      
      kc = GL_CONSTANT_ATTENUATION
      
      kl = GL_LINEAR_ATTENUATION
      
      kq = GL_QUADRATIC_ATTENUATION
      

      By default, kc = 1.0, kl = kq = 0.0.
      You can give these parameters different values:

      glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 2.0);
      glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 1.0);
      glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.5);
      

      Multiple lights

      Can have up to 8 light sources.

      Example: Second light source
      GLfloat light1_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
      GLfloat light1_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
      GLfloat light1_specular[] = { 1.0, 1.0, 1.0, 1.0 };
      GLfloat light1_position[] = { -2.0, 2.0, 1.0, 1.0 };
      GLfloat spot_direction[] = { -1.0, -1.0, 0.0 };
      
      glLightfv(GL_LIGHT1, GL_AMBIENT, light1_ambient);
      glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
      glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
      glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
      glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.5);
      glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.5);
      glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.2);
      
      glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, 45.0);
      glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, spot_direction);
      glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 2.0);
      
      glEnable(GL_LIGHT1);
      

    33. Defining Material Properties

      glMaterial*()

      Example:Different Material Properties

         //material.cpp
         GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };
         GLfloat mat_ambient[] = { 0.7, 0.7, 0.7, 1.0 };
         GLfloat mat_ambient_color[] = { 0.8, 0.8, 0.2, 1.0 };
         GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8, 1.0 };
         GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
         GLfloat no_shininess[] = { 0.0 };
         GLfloat low_shininess[] = { 5.0 };
         GLfloat high_shininess[] = { 100.0 };
         GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0};
      
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      
      /*  draw sphere in first row, first column
       *  diffuse reflection only; no ambient or specular  
       */
         glPushMatrix();
         glTranslatef (-3.75, 3.0, 0.0);
         glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
         glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
         glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
         glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
         glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
         glutSolidSphere(1.0, 16, 16);
         glPopMatrix();
      
      /*  draw sphere in first row, second column
       *  diffuse and specular reflection; low shininess; no ambient
       */
         glPushMatrix();
         glTranslatef (-1.25, 3.0, 0.0);
         glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
         glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
         glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
         glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);
         glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
         glutSolidSphere(1.0, 16, 16);
         glPopMatrix();
      
      /*  draw sphere in first row, third column
       *  diffuse and specular reflection; high shininess; no ambient
       */
         glPushMatrix();
         glTranslatef (1.25, 3.0, 0.0);
         glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
         glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
         glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
         glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
         glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
         glutSolidSphere(1.0, 16, 16);
         glPopMatrix();
      
      /*  draw sphere in first row, fourth column
       *  diffuse reflection; emission; no ambient or specular refl.
       */
         glPushMatrix();
         glTranslatef (3.75, 3.0, 0.0);
         glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
         glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
         glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
         glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
         glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
         glutSolidSphere(1.0, 16, 16);
         glPopMatrix();
      

       
       
       
      No ambient reflection
       

       

      Grey ambient reflection
       

       

      Blue ambient reflection
       

      Figure column:

      1. blue diffuse material color with no specular properties
      2. adds white specular reflection with a low shininess exponent
      3. uses a high shininess exponent and thus a more concentrated light
      4. uses blue diffuse color and, instead of specular reflection, adds an emissive component

    34. Controlling a Light's Position and Direction

      A light source is subject to the same matrix transformations as a geometric primitive.

    35. Keeping the Light stationary

      Set the light position after whatever viewing and/or modeling transformations

      ....
      ....
      glViewport (0, 0, (GLsizei) w, (GLsizei) h);
      glMatrixMode (GL_PROJECTION);
      glLoadIdentity();
      if (w <= h) 
          glOrtho (-1.5, 1.5, -1.5*h/w, 1.5*h/w, -10.0, 10.0);
      else 
          glOrtho (-1.5*w/h, 1.5*w/h, -1.5, 1.5, -10.0, 10.0);
      glMatrixMode (GL_MODELVIEW);
      
      glLoadIdentity();
      GLfloat light_position[] = { 1.0, 1.0, 1.0, 1.0 };
      glLightfv(GL_LIGHT0, GL_POSITION, position);
      

      You may put the code in init() or reshape().

    36. Independently Moving the Light

      Set the position after the model transformations

      static GLdouble spin;
      
      void display(void)
      {
          GLfloat light_position[] = { 0.0, 0.0, 1.5, 1.0 };
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      
          glPushMatrix();
              gluLookAt (0.0, 0.0, 6.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
              glPushMatrix();
                  glRotated(spin, 1.0, 0.0, 0.0);
                  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
              glPopMatrix();
              glutSolidTorus (0.275, 0.85, 8, 15);
          glPopMatrix();
          glFlush();
      }
      

      //movelight.cpp
      #include <GL/gl.h>
      #include <GL/glu.h>
      
      static int spin = 0;
      
      void init(void) 
      {
         glClearColor (0.0, 0.0, 0.0, 0.0);
         glShadeModel (GL_SMOOTH);
         glEnable(GL_LIGHTING);
         glEnable(GL_LIGHT0);
         glEnable(GL_DEPTH_TEST);
      }
      
      /*  Here is where the light position is reset after the modeling
       *  transformation (glRotated) is called.  This places the
       *  light at a new position in world coordinates.  The cube
       *  represents the position of the light.
       */
      void display(void)
      {
         GLfloat position[] = { 0.0, 0.0, 1.5, 1.0 };
      
         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         glPushMatrix ();
         glTranslatef (0.0, 0.0, -5.0);
      
         glPushMatrix ();
         glRotated ((GLdouble) spin, 1.0, 0.0, 0.0);
         glLightfv (GL_LIGHT0, GL_POSITION, position);
      
         glTranslated (0.0, 0.0, 1.5);
         glDisable (GL_LIGHTING);
         glColor3f (0.0, 1.0, 1.0);
         glutWireCube (0.5);
         glEnable (GL_LIGHTING);
         glPopMatrix ();
      
         glutSolidTorus (0.275, 0.85, 8, 15);
         glPopMatrix ();
         glFlush ();
      }
      
      void reshape (int w, int h)
      {
         glViewport (0, 0, (GLsizei) w, (GLsizei) h);
         glMatrixMode (GL_PROJECTION);
         glLoadIdentity();
         gluPerspective(40.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
         glMatrixMode(GL_MODELVIEW);
         glLoadIdentity();
      }
      
      void mouse(int button, int state, int x, int y)
      {
         switch (button) {
            case GLUT_LEFT_BUTTON:
               if (state == GLUT_DOWN) {
                  spin = (spin + 30) % 360;
                  glutPostRedisplay();
               }
               break;
            default:
               break;
         }
      }
      int main(int argc, char** argv)
      {
         glutInit(&argc, argv);
         glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
         glutInitWindowSize (500, 500); 
         glutInitWindowPosition (100, 100);
         glutCreateWindow (argv[0]);
         init ();
         glutDisplayFunc(display); 
         glutReshapeFunc(reshape);
         glutMouseFunc(mouse);
         glutMainLoop();
         return 0;
      }
      

    37. Moving the Light Source together with the Viewpoint

      Set the light position before the viewing transformation. Then the viewing transformation affects both the light source and the viewpoint in the same way.

      GLfloat light_position() = { 0.0, 0.0, 0.0, 1.0 };
      
      glViewport(0, 0, (GLint) w, (GLint) h);
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(40.0, (GLfloat) w/(GLfloat) h, 1.0, 100.0);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glLightfv(GL_LIGHT0, GL_POSITION, light_position);
      

      If the viewpoint is now moved, the light will move along with it, maintaining (0, 0, 0) distance, relative to the eye. Suppose the global variables (ex, ey, ez) and (upx, upy, upz) control the position of the viewpoint and up vector. The display() routine that's called from the event loop to redraw the scene might be this:

      static GLdouble ex, ey, ez, upx, upy, upz;
      
      void display(void)
      {
          glClear(GL_COLOR_BUFFER_MASK | GL_DEPTH_BUFFER_MASK);
          glPushMatrix();
              gluLookAt (ex, ey, ez, 0.0, 0.0, 0.0, upx, upy, upz);
              glutSolidTorus (0.275, 0.85, 8, 15);	//inner radious, outer radius, nsides, rings
          glPopMatrix();
          glFlush();
      }