15. OpenGL Fog Types (Version 2.0)
Exploring Different Types of OpenGL Fog
In the last tutorial, we introduced the basics of fog in OpenGL, focusing on how to set up fog with a specific mode and density. Now it’s time to expand on that by exploring the different types of fog OpenGL supports.
Fog is a powerful tool for adding atmosphere to your scenes, but the way it looks depends heavily on the type of fog you choose. OpenGL provides three options:
– GL_EXP: Exponential fog, where the density increases exponentially as the distance increases.
– GL_EXP2: Exponential squared fog, which increases more rapidly than GL_EXP and often produces a softer, more realistic effect.
– GL_LINEAR: Linear fog, where the density increases linearly between specified start and end distances.
Choosing the right type of fog for your scene often comes down to trial and error, but as you get familiar with these modes, you’ll start to anticipate how each will look in your application.
Review: GL_EXP2
In the last tutorial, we used GL_EXP2. It’s my personal favorite because it creates smooth, natural-looking fog that blends beautifully with most scenes. Here’s the code we used to set it up:
glFogi(GL_FOG_MODE, GL_EXP2); // Exponential squared fog
If you liked how GL_EXP2 looked, great! But let’s dive into the other options to see what they bring to the table.
Other Fog Modes
GL_EXP:
This mode uses a basic exponential formula for fog density, which results in a lighter effect compared to GL_EXP2. It’s great for scenes where you want fog to increase gradually without overwhelming the visuals.
glFogi(GL_FOG_MODE, GL_EXP); // Exponential fog
GL_LINEAR:
Unlike the exponential modes, GL_LINEAR fog is predictable and straightforward. You define a start distance and an end distance, and the fog density increases linearly between these two points. This mode is especially useful for creating a clear boundary where objects fade into fog.
glFogi(GL_FOG_MODE, GL_LINEAR); // Linear fog glFogf(GL_FOG_START, 1.0); // Fog starts 1 unit into the screen glFogf(GL_FOG_END, 10.0); // Fog ends 10 units into the screen
The start and end distances give you precise control over how the fog behaves, making this mode a good choice for scenes with specific depth requirements.
Fog Rendering Quality
Another important aspect of fog in OpenGL is rendering quality, controlled by the `glHint` function. OpenGL provides three quality settings:
– GL_NICEST: Maximizes visual quality but may reduce performance.
– GL_FASTEST: Prioritizes performance, sacrificing visual fidelity.
– GL_DONT_CARE: Leaves the decision to the graphics driver, which may choose either quality or performance based on hardware capabilities.
Here’s how you set it:
glHint(GL_FOG_HINT, GL_NICEST); // Best quality
For this tutorial, we’ll stick with `GL_NICEST` to make the fog look as smooth and polished as possible. If performance is a concern, you can experiment with `GL_FASTEST`.
Switching Fog Modes Dynamically
To help you experiment with these fog modes, I’ve added keyboard controls to switch between them:
– Press A to enable GL_EXP.
– Press S to enable GL_EXP2.
– Press D to enable GL_LINEAR.
Here’s the relevant keyboard handling code:
void keyboard(unsigned char key, int x, int y) { if (key == 'a') { glFogi(GL_FOG_MODE, GL_EXP); // Switch to GL_EXP } if (key == 's') { glFogi(GL_FOG_MODE, GL_EXP2); // Switch to GL_EXP2 } if (key == 'd') { glFogi(GL_FOG_MODE, GL_LINEAR); // Switch to GL_LINEAR } }
This makes it easy to test how each fog type looks in your scene.
The Full Code
Below is the complete code for this tutorial. It includes the fog setup, rendering quality settings, and keyboard controls for switching modes.
#include <GL/gl.h> #include <GL/glut.h> GLfloat angle = 0.0; GLfloat density = 0.3; // Fog density GLfloat fogColor[4] = {0.5, 0.5, 0.5, 1.0}; // Fog color: 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_LINEAR); // Default fog mode: Linear glFogfv(GL_FOG_COLOR, fogColor); // Set fog color glFogf(GL_FOG_DENSITY, density); // Set fog density glFogf(GL_FOG_START, 1.0); // Fog starts 1 unit in glFogf(GL_FOG_END, 10.0); // Fog ends 10 units in 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); } // Keyboard controls for fog modes void keyboard(unsigned char key, int x, int y) { if (key == 'a') { glFogi(GL_FOG_MODE, GL_EXP); // Switch to GL_EXP } if (key == 's') { glFogi(GL_FOG_MODE, GL_EXP2); // Switch to GL_EXP2 } if (key == 'd') { glFogi(GL_FOG_MODE, GL_LINEAR); // Switch to GL_LINEAR } } // 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 Modes Example"); // Window title init(); // Initialize fog and settings glutDisplayFunc(display); // Render function glutIdleFunc(display); // Animation glutReshapeFunc(reshape); // Handle window resizing glutKeyboardFunc(keyboard); // Keyboard controls glutMainLoop(); // Enter the event loop return 0; }
If you have any questions, feel free to email me at swiftless@gmail.com. Happy coding!
GL_DONT_CARE is the initial value for each target. Practically, it means no preferences.
Hi, great job with all the tutorials Swiftless. I’ve been reading through all the tutorials before this and wanted to suggest that you include pictures to show the differences
between different light settings and/or fog settings. I actually havent been using C/C++ to program with OpenGL, I’m using JOGL (Java bindings to OpenGL), and everything in your tutorials are helping me! 🙂 Just that I have to set up a window and other similar things without using GLUT. Perhaps you can add further tutorials on some of the things in JOGL that differ from OpenGL. Two things off the top of head would include double-buffering and fullscreen antialiasing. But anyways, keep up the great work, and I’ll be looking through the rest of the tutorials!
This post explains what options OpenGL gives, but not what these options are, what fog model they represent.
Here is some more on how fog affects final color and what calculus is behind GL_EXP, GL_EXP2 and GL_LINEAR: http://www.opengl.org/resources/code/samples/advanced/advanced97/notes/node122.html
hi,
tutorial is very simple and easy, however I put the fog start and end lines with a limit between 2 and -2 , i was expecting some part of cube in the fog but it didnt change anything, i put these lines in the init() functoin just after glEnable(GL_FOG);