14. OpenGL Fog (Version 2.0)

Introduction to OpenGL Fog

Fog is a fantastic visual effect that helps add depth and realism to your 3D scenes. It’s a staple in games and simulations, often used to suggest vast distances, obscure distant objects, or create an atmospheric mood. In this tutorial, we’ll cover the basics of creating fog in OpenGL, keeping things simple and easy to understand.

There are a few key steps to setting up fog:
1. Enable depth testing to ensure the fog interacts correctly with 3D objects.
2. Enable fog in OpenGL.
3. Choose a fog mode.
4. Set the fog color.
5. Define the fog density.
6. Optionally, specify how smooth or optimized the fog effect should appear.

We’ll stick to the essentials for now, but you’ll see how to tweak these parameters to get the best results for your scene.

Getting Started: Fog Variables

Before we start coding, we need to define a couple of variables for the fog’s properties. Here’s what I’ve used:

GLfloat density = 0.3; // Fog density: how thick the fog is
GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1.0}; // Fog color: a medium grey

What does this mean?
– The fog color is defined using four components: red, green, blue, and alpha (opacity). In this case, I’ve set it to a neutral grey (`R = 0.5, G = 0.5, B = 0.5`).
– The density controls how thick or intense the fog is. A value of `0.3` is relatively thick, as you’ll see when we run the application.

Enabling Fog in OpenGL

Once we’ve defined the fog properties, we can set it up in OpenGL. Here are the steps:

1. **Enable fog**
Use `glEnable(GL_FOG)` to turn on OpenGL’s fog functionality.

   glEnable(GL_FOG);
   

2. **Set the fog mode**
OpenGL supports several fog modes:
– `GL_LINEAR`: Fog increases linearly between the start and end distances.
– `GL_EXP`: Fog increases exponentially based on distance.
– `GL_EXP2`: Fog increases exponentially with a squared factor for a more natural look.

For this tutorial, I’ve chosen `GL_EXP2` because it often looks the best:

   glFogi(GL_FOG_MODE, GL_EXP2);
   

3. **Set the fog color**
This determines the color of the fog and how it blends with the objects in the scene.

   glFogfv(GL_FOG_COLOR, fogColor);
   

4. **Set the fog density**
Control how quickly the fog becomes opaque:

   glFogf(GL_FOG_DENSITY, density);
   

5. **Optimize fog rendering**
The `glHint` function lets you balance quality and performance. For the best visual results, use `GL_NICEST`:

   glHint(GL_FOG_HINT, GL_NICEST);
   

What Does It Look Like?

With this setup, the fog will gradually thicken as objects move further away from the camera. The density of `0.3` creates a noticeable effect, but you can experiment with higher or lower values to suit your scene. For example:
– `0.1`: Very light fog, barely noticeable.
– `0.5`: Dense fog, obscuring objects quickly.

The Full Code

Here’s the complete code for a simple OpenGL application that demonstrates fog on a rotating cube. Paste this into your project to see it in action:

#include <GL/gl.h>
#include <GL/glut.h>

GLfloat angle = 0.0;

GLfloat density = 0.3; // Fog density: relatively thick
GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1.0}; // Fog color: medium grey

// Draw a rotating cube
void cube(void) {
    glRotatef(angle, 1.0, 0.0, 0.0); // Rotate on X-axis
    glRotatef(angle, 0.0, 1.0, 0.0); // Rotate on Y-axis
    glRotatef(angle, 0.0, 0.0, 1.0); // Rotate on Z-axis
    glColor3f(1.0, 0.0, 0.0); // Cube color: red
    glutSolidCube(2);
}

// Initialize fog and OpenGL settings
void init(void) {
    glEnable(GL_DEPTH_TEST); // Enable depth testing
    glEnable(GL_FOG); // Enable fog
    glFogi(GL_FOG_MODE, GL_EXP2); // Fog mode: exponential squared
    glFogfv(GL_FOG_COLOR, fogColor); // Set fog color
    glFogf(GL_FOG_DENSITY, density); // Set fog density
    glHint(GL_FOG_HINT, GL_NICEST); // Optimize fog appearance
}

// Render the scene
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();
    gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // Camera setup
    cube();
    glutSwapBuffers();
    angle++; // Increment rotation angle
}

// Handle window resizing
void reshape(int w, int h) {
    glViewport(0, 0, (GLsizei)w, (GLsizei)h); // Set viewport
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0); // Perspective projection
    glMatrixMode(GL_MODELVIEW);
}

// Main function
int main(int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(500, 500); // Window size
    glutInitWindowPosition(100, 100); // Window position
    glutCreateWindow("OpenGL Fog Example"); // Window title
    init(); // Initialize fog and settings
    glutDisplayFunc(display); // Render function
    glutIdleFunc(display); // Animation
    glutReshapeFunc(reshape); // Handle window resizing
    glutMainLoop(); // Enter the event loop
    return 0;
}

What’s Next?

This tutorial covered the basics of OpenGL fog, but there’s a lot more you can do. For example:
– Set start and end distances for linear fog.
– Experiment with different fog colors and densities.
– Use fog to simulate weather effects like mist, haze, or smog.

I’ll dive into these advanced topics in the next fog tutorial. For now, experiment with the parameters and see what works best for your scenes.

If you run into any issues, feel free to email me at swiftless@gmail.com. Happy coding!

  • March 25, 2010
  • 12