Fog GLSL Library for Materials

Adding fog to any material instantly gives depth to your horizon. It helps your eyes distinguish distance. In this case I decided to calculate the fog after the light calculation. It seemed to make more sense to me. Light is therefore not changed by the introduction of the fog. The fog, after all, is a result of the distance of the player to the object. The object itself hasn’t changed because we are closer, it just becomes less foggy. It also makes it very easy to throw the calculation right at the bottom after all the somewhat intimidating lighting calculations.

Using this workflow you should be able to add fog to any material in under 5 minutes.

Original Paper: http://in2gpu.com/2014/07/22/create-fog-shader/
More Reading: http://www.iquilezles.org/www/articles/fog/fog.htm

Note: I’ve used gl_FragColor in the fog method calls because it’s easier for the reader to understand where that color came from. I advise against changing the gl_FragColor variable once it’s set. Usually it would be set once and never again. For the purpose of this small document, I’ll ignore my own advice.

The lib is available on git: https://gist.github.com/jayfella/80817ebbc42b6ba85bbdd72609ff8f28

.vert

varying float dist; // define a distance variable that we'll use in the fragment shader.

void main() {
    // … the rest of your shader.
    // at the very bottom
    // get the distance of the pixel from the camera position
    dist = distance(g_CameraPosition, (g_WorldViewMatrix * modelSpacePos).xyz);
}

.frag

#include "Shaders/Lib/Fog.glsllib"

varying float dist; // get the distance output from the vert shader.

void main() {
    // … the rest of your shader
    // at the very bottom

    // set some parameters...
    
    // linear-based
    float start = 20.0;
    float end = 80.0;

    // exponential-based
    vec4 fogColor = vec4(0.5, 0.6, 0.7, 1.0);
    float fogDensity = 0.05;

    // pick one.    
    vec4 fogResult = getFogLinear(gl_FragColor, fogColor, start, end, dist); // cheapest (android/mobile)
    vec4 fogResult = getFogExp(gl_FragColor, fogColor, m_FogDensity, dist); // nicer/slower
    vec4 fogResult = getFogExpSquare(gl_FragColor, fogColor, m_FogDensity, dist); // best/slowest

    gl_FragColor.rgb = fogResult.rgb;
    gl_FragColor.a = alpha; // or whatever...

}

And the obligatory screenshots. Fog really needs tweaking to your liking to be honest. I can’t really show the actual difference without changing the shader to ignore height and show a birds-eye view. And the gamma or something seems to change from how it looks in-game. Pasting it into photoshop makes it look different, and then uploading it to imgur causes it to look different again. Anyway…

Linear

Exponential

Exponential Squared

10 Likes

Nice, but the license is missing :penguin:

Oops. Added.

1 Like

A screenshot would go a long way :wink:

2 Likes

Blimey. How crap was my homework on this one :confused: sorry. Added.