Daniel Gray

Thoughts, Notes, Ideas, Projects

Contact

Graphics Gems GLSL - Simulating Fog and Haze

Atmospheric effects like fog and haze are essential for creating depth, mood, and realism in 3D scenes. The technique from Graphics Gems I uses exponential density decay to simulate how light scatters through the atmosphere, creating the characteristic "fade to white" effect of distant objects.

Interactive Demo

Move your mouse to rotate the camera and explore the foggy landscape. Scroll to adjust fog density:

Mathematical Foundation

Fog and haze simulation is based on exponential density decay:

Exponential Fog Density

The density of fog increases exponentially with distance:

f(d)=1eρdαf(d) = 1 - e^{-\rho \cdot d^{\alpha}}

Where:

  • dd: Distance from camera
  • ρ\rho: Base fog density coefficient
  • α\alpha: Controls how quickly fog accumulates (typically 1.0-2.0)

The exponential form ensures smooth transitions and physically realistic scattering behavior.

Height-Based Haze

Haze often accumulates near the ground:

fh(p)=1eρhmax(0,h0py)f_h(\mathbf{p}) = 1 - e^{-\rho_h \cdot \max(0, h_0 - p_y)}

Where:

  • p\mathbf{p}: 3D position
  • h0h_0: Reference height (fog level)
  • ρh\rho_h: Height-based density coefficient

This creates realistic ground fog that's denser at lower elevations, simulating the natural behavior of atmospheric particles settling near the ground.

Implementation

Applying Fog to Objects

// Calculate fog factor based on distance
float fogFactor = fogDensity(distance, 0.05, 1.2);

// Blend object color with fog color
vec3 fogColor = vec3(0.7, 0.8, 0.9); // Sky color
vec3 finalColor = mix(objectColor, fogColor, fogFactor);

Atmospheric Perspective

Distant objects appear more foggy and less saturated:

cfinal=mix(cobj,cfog,fa(d)α)\mathbf{c}_{\text{final}} = \text{mix}(\mathbf{c}_{\text{obj}}, \mathbf{c}_{\text{fog}}, f_a(d) \cdot \alpha)

Where fa(d)=1eβdf_a(d) = 1 - e^{-\beta d} is the atmospheric fog factor and α\alpha controls the blending strength (typically 0.6).

Visual Effects

God Rays (Volumetric Lighting)

Add volumetric light rays by checking if the view direction aligns with the light:

float lightDot = dot(viewDir, lightDir);
if (lightDot > 0.9) {
    float rayIntensity = pow(lightDot, 8.0) * 0.3;
    color += lightColor * rayIntensity;
}

Layered Fog

Combine distance-based and height-based fog for realistic effects:

float distFog = fogDensity(t, 0.05, 1.2);
float heightFogDensity = heightFog(p, 2.0, 0.1);
float totalFog = mix(distFog, heightFogDensity, 0.5);

Applications

  • Landscapes: Create depth and atmosphere in outdoor scenes
  • Horror games: Use dense fog to limit visibility and create tension
  • Flight simulators: Realistic atmospheric scattering at altitude
  • Post-processing: Apply fog as a screen-space effect

Performance

Fog calculations are extremely efficient:

  • Single exponential function per pixel
  • No additional geometry required
  • Works perfectly in fragment shaders
  • Can be applied as post-processing effect

References

Related Articles

Related Content

Graphics Gems GLSL Series

Graphics Gems GLSL Series The Graphics Gems series (1990-1995) contains timeless algorithms and techniques that remain fundamental to computer graphics today. This series adapts these classic algorith...