Distance-based fog shader?

Is there a way of having fog based on distance rather than depth? I have no idea how to write a shader like this, but I’m trying to avoid having fog affect the color of things when viewed at certain angles: admiredlatekingsnake

I believe it is because of the depth method of performing fog that causes this, and it needs to be done on distance. Is this possible?

The solution for a fully custom shader is relatively simple to implement, since you have control over everything, but that’s not really a lot of fun.

If you’re aiming for desktop or OpenGLES 3.0, you can add this to a Surface Shader to get more what you want.

    CGINCLUDE
      #include "UnityCG.cginc"
      #if !defined(UNITY_PASS_META) && (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2))
        #ifdef UNITY_APPLY_FOG_COLOR
         #undef UNITY_APPLY_FOG_COLOR
      #endif

        #define UNITY_APPLY_FOG_COLOR(coord,col,fogCol) \
            float unityFogFactor = saturate(exp2(unity_FogParams.y * -length(worldPos - _WorldSpaceCameraPos))); \
            UNITY_FOG_LERP_COLOR(col.rgb, unityFogFactor, fogCol)
      #endif
    ENDCG

This works because the worldPos value happens to exist in the place Surface Shaders call the fog macro, so this won’t work on any other type of shader. I also use a replacement Standard shader that has a similar bit of code, but with worldPos - _WorldSpaceCameraPos replaced with i.eyeVec because, again, it happens to be a value that exists for that shader.

There’s not a really good universal way to fix it though, even with modifying the UnityCG.cginc file that most of the fog code exists in because there are several places where it’s assumed the “fog factor” passed from the vertex to the fragment is a single float, and that’s just not an option for distance based fog while still having it work properly.

Ironically, the built in VertexLit shaders do use distance based fog already, but it calculates the distance per vertex which means it only works well on dense mesh geometry. Otherwise it has weird visual artifacts.

Also note that code only supports exp2 fog, since that’s all my project uses. More work would be needed to support other fog types.

Thanks, really appreciate the info! It’s a shame Unity still won’t let us tweak fog even more out of the box, it seems like there’s so much room for tweaking and improvement.