Height/Distance based fog

Hi guys,

I’ve been adding a lot to my my world and of course frame rate starts to dip to things in different quads are getting drawn at lower detail and not at all in some cases which is mostly hidden in basic distance. Traditional stuff.

In the shader which combines all my buffers and various post processing stuff I just finish up with:

float fog = clamp((d - FogStart) / (FogEnd - FogStart), 0, 0.77);
OutputColor = lerp(OutputColor, fcolor, fog);

Looks decent enough but it hides the tops of distance mountainous terrain, which isn’t the end of the world but I’d rather keep the nice detailed look of the mountains in the distance.

I stumbled upon this article which looks great: https://iquilezles.org/www/articles/fog/fog.htm

The math is a bit beyond me but the explanation and shader make sense to me at least but not all of it. It doesn’t help that it’s OpenGL but I’ve done enough HLSL and WebGL to understand that (I think). I have the color of the pixel. I’ve got the distance already from my depth map (used for shadowing etc). I guess I can pass in the camera position and calculated the camera to point with position-cameraposition so I think I have all the input parameters covered.

In the final shader it seems like “b” controls how fast the fog fades away as it reaches the height threshold (althought I’m not sure what kind of value I should be setting it to) but what does c control and what should it be set to?

Or does anyone have a simpler solution to having the fogging effect calculated by distance and height?

Thanks guys!

normal fog (as you showed) is basically based on the far plane - fog increases with less distance to far plane.

so, when you base that all on heigh instead of farplane, you may get hard polygon cuts when the mountains hit the farplane. Just something you have to consider.

I haven’t looked at your link yet, but yes, if you want to alter the fog generated based on terrain heigh you have to get the world coordinates of that pixel. You can either collect it via a distinct buffer or you can reconstruct it from depth (this is where you use the viewspace.z multiplied with a viewdirection (eye -> pixel) from there you can get the heigh.

If this is a basic part of your engine, you could also just save the Y in some free part of a buffer (as you use deferred shading anyway I guess) - maybe some channel is free, you only need a single float to hold the world-height of a pixel