Open GL Super Bible

Previous Table of Contents Next


Fog

OpenGL provides depth-cueing (shading based upon distance) and atmospheric effects through the glFog function. Essentially, fog provides a way of adding (mixing) a predefined color with each vertex or texture image based upon the distance from the user. Fog is often used in flight simulators and animation packages to provide the final real-world look to computer graphics.

OpenGL supports three kinds of fog: GL_LINEAR for depth-cueing, GL_EXP for heavy fog or clouds, and GL_EXP2 for smoke and weather haze. Figure 16-3 shows GL_LINEAR fog; later, in Figure 16-5, you can see the effect of GL_EXP fog.


Figure 16-3  Depth-cued teapots using glFog

You choose the type of fog (or fog mode) using glFogi:

glFogi(GL_FOG_MODE, GL_LINEAR);

glFogi(GL_FOG_MODE, GL_EXP);

glFogi(GL_FOG_MODE, GL_EXP2);

Once you have chosen the fog type, you must choose a fog color that will be mixed with your scene using the glFogfv or glFogiv functions:

GLfloat fog_color[4] = { r, g, b, a };
glFogfv(GL_FOG_COLOR, fog_color);

GLint fog_color[4] = { r, g, b, a };
glFogiv(GL_FOG_COLOR, fog_color);

For depth-cueing, you’ll generally want to make the fog color the same as the background (black, in Figure 16-3). This will make the depth-cueing look “correct” to the eye—that is, objects farther away will appear to fade into the background. For some applications, you might want to give the fog a bright color such as yellow, instead, so that things stand out more against the background.

Drawing Depth-Cued Teapots

Listing 16-3 draws two teapots using depth-cueing. The draw_scene function handles all graphics drawing and starts by setting the fog color to black and the fog mode to GL_LINEAR.

static float   fog_color[4] = { 0.0, 0.0, 0.0, 0.0 };

glEnable(GL_FOG);
glFogf(GL_FOG_MODE, GL_LINEAR);
glFogfv(GL_FOG_COLOR, fog_color);

Finally, it draws both teapots at different distances from the viewer. The results are visibly obvious.

Listing 16-3 FOGPOT.C: Depth-cued teapots using glFog

#include <GL/glaux.h>

/*
 * These #define constants are provided for compatibility between MS
 * Windows and the rest of the world.
 *
 * CALLBACK and APIENTRY are function modifiers under MS Windows.
 */

#ifndef WIN32
#  define CALLBACK
#  define APIENTRY
#endif /* !WIN32 */

GLfloat rotation = 0.0;

/*
 * 'reshape_scene()' - Change the size of the scene…
 */

void CALLBACK
reshape_scene(GLsizei width,   /* I - Width of the window in pixels */
              GLsizei height)  /* I - Height of the window in pixels */
{
 /*
  * Reset the current viewport and perspective transformation…
  */

  glViewport(0, 0, width, height);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(22.5, (float)width / (float)height, 0.1, 1000.0);

  glMatrixMode(GL_MODELVIEW);
}

/*
 * 'draw_scene()' - Draw a scene containing a cube with a sphere in front
 *                  of it.
 */

void CALLBACK
draw_scene(void)
{
  static float   red_light[4] = { 1.0, 0.0, 0.0, 1.0 };
  static float   red_pos[4] = { 1.0, 1.0, 1.0, 0.0 };
  static float   blue_light[4] = { 0.0, 0.0, 1.0, 1.0 };
  static float   blue_pos[4] = { -1.0, -1.0, -1.0, 0.0 };
  static float   fog_color[4] = { 0.0, 0.0, 0.0, 0.0 };

 /*
  * Enable drawing features that we need…
  */

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHT1);

  glShadeModel(GL_SMOOTH);

 /*
  * Clear the color and depth buffers…
  */

  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 /*
  * Draw the cube and sphere in different colors…
  *
  * We have positioned two lights in this scene.  The first is red and
  * located above, to the right, and behind the viewer.  The second is
  * blue and located below, to the left, and in front of the viewer.
  */

  glLightfv(GL_LIGHT0, GL_DIFFUSE, red_light);
  glLightfv(GL_LIGHT0, GL_POSITION, red_pos);

  glLightfv(GL_LIGHT1, GL_DIFFUSE, blue_light);
  glLightfv(GL_LIGHT1, GL_POSITION, blue_pos);

  glEnable(GL_COLOR_MATERIAL);

  glEnable(GL_FOG);
  glFogf(GL_FOG_MODE, GL_LINEAR);
  glFogfv(GL_FOG_COLOR, fog_color);

  glPushMatrix();
    glTranslatef(-1.0, 0.0, -15.0);
    glRotatef(-rotation, 0.0, 1.0, 0.0);

    glColor3f(1.0, 1.0, 0.0);
    auxSolidTeapot(1.0);
  glPopMatrix();

  glPushMatrix();
    glTranslatef(1.0, 0.0, -10.0);
    glRotatef(rotation, 0.0, 1.0, 0.0);

    glColor3f(0.0, 1.0, 1.0);
    auxSolidTeapot(1.0);
  glPopMatrix();

  auxSwapBuffers();
}

/*
 * 'rotate_objects()' - Rotate while we are idle…
 */

void CALLBACK
rotate_objects(void)
{
  rotation += 2.0;
  if (rotation >= 360.0)
    rotation -= 360.0;

  draw_scene();
}

/*
 * 'main()' - Initialize the window and display the scene until the user
 *            presses the ESCape key.
 */

void
main(void)
{
  auxInitDisplayMode(AUX_RGB | AUX_DOUBLE | AUX_DEPTH);
  auxInitWindow("Fogged Teapots");

  auxReshapeFunc(reshape_scene);
  auxIdleFunc(rotate_objects);

  auxMainLoop(draw_scene);
}


Previous Table of Contents Next