Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Changing Unity´s fog (realistic fog)

Discussion in 'Shaders' started by NekrosArts, Nov 21, 2019.

  1. NekrosArts

    NekrosArts

    Joined:
    Nov 3, 2019
    Posts:
    18
    Hey folks,
    I´m currently working on an image effect shader that should modify Unitys normal fog.
    My problem is that I have a dark scene with many lightsources. The fog lights up the whole scene and is applied everywhere. But it´s more realistic that everything get´s a little darker and you can only see the fog where light is. (see pic)

    Do you have an idea how to solve this problem and apply it so and image effect shader? :)

    Here is what I tried. Whole idea: the brighter the background the more fogcolor I want to add.
    Fog absorbs light so must the scenecolor (b) the highest value. The darker "b" gets the more would fog darken it. On the other hand will a bright "b" not get darkend much by a bright "a".

    Code (CSharp):
    1.  
    2.             fixed4 frag (v2f i) : SV_Target
    3.             {
    4.                 float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);    //get depth-information from the CameraDepthTexture for the current fragment
    5.                 depth = Linear01Depth(depth);    //raw-data are lon-linear values 0-1. We want to convert them to linear values
    6.                 float viewDistance = depth * _ProjectionParams.z -_ProjectionParams.y; //scale by the parameter "far clip plane" distance (also Sichtweite der Kamera)
    7.                 //subtract the near clip plane
    8.  
    9.                 UNITY_CALC_FOG_FACTOR_RAW(viewDistance); //calculated fog-density and stores value in unityFogFactor
    10.                 unityFogFactor = saturate(unityFogFactor);    //need to be clamped to 0-1
    11.                
    12.                 float3 b = tex2D(_MainTex, i.uv).rgb;
    13.                 float3 a = unity_FogColor;  
    14.                 float w = unityFogFactor;
    15.                 float3 foggedColor = float3(1,1,1);
    16.                
    17.                 float3 diff = sqrt( pow( b-a, 2));
    18.                 b = b - diff;
    19.                 a = a - diff;
    20.                 foggedColor = saturate(lerp(a,b,1-w));
    21.  
    22.                 float4 finalColor = float4(foggedColor, 1);
    23.                 return finalColor;
    24.             }
    Without Shader: upload_2019-11-21_18-30-20.png

    With Shader: upload_2019-11-21_18-29-30.png
     
    Lars-Steenhoff likes this.
  2. NekrosArts

    NekrosArts

    Joined:
    Nov 3, 2019
    Posts:
    18
    Update: I tried a different approch (seventh try).
    Normally Unity calculates fog usig lerp(a,b,w) like this
    Code (CSharp):
    1. float3 b = tex2D(_MainTex, i.uv).rgb;
    2.                 float3 a = unity_FogColor;   //Color which is set in Lighting tab
    3.                 float w = unityFogFactor;    //calculated from distance
    4.                 float3 foggedColor = float3(1,1,1);
    5.                 float3 foggedColor = lerp(a,b,w);
    6. return foggedColor
    7.  
    Now I had the idea to lerp two times. (See code below) First I lerp between the fogColor (a) and background color (b) and us as weight "b". The darker (low value) the more it will mix the Color toward the backgroundcolor (b), which means that a dark area will have a dark color as result (new_a). This is my new fogcolor for this special pixel. The second time I lerp the neu fogcolor (new_a) with b, based on the distance (w), just like Unity does it normally. In theory it should apply more fog to lighter areas and less fog to darker areas. It works, yes. But there is no "depth"-fog as you may see in the pictures.

    Code (CSharp):
    1. fixed4 frag (v2f i) : SV_Target
    2.             {
    3.                 float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);    //get depth-information from the CameraDepthTexture for the current fragment
    4.                 depth = Linear01Depth(depth);    //raw-data are lon-linear values 0-1. We want to convert them to linear values
    5.                 float viewDistance = depth * _ProjectionParams.z -_ProjectionParams.y; //scale by the parameter "far clip plane" distance (also Sichtweite der Kamera)
    6.                 //subtract the near clip plane
    7.  
    8.                 UNITY_CALC_FOG_FACTOR_RAW(viewDistance); //calculated fog-density and stores value in unityFogFactor
    9.                 unityFogFactor = saturate(unityFogFactor);    //need to be clamped to 0-1
    10.                
    11.                 float3 b = tex2D(_MainTex, i.uv).rgb;
    12.                 float3 a = unity_FogColor;  
    13.                 float w = unityFogFactor;
    14.                 float3 foggedColor = float3(1,1,1);
    15.                
    16.                 float3 new_a = lerp(b,a,b*4);
    17.                 foggedColor = lerp(new_a,b,w);
    18.                
    19.                 float4 finalColor = float4(foggedColor, 1);
    20.                 return finalColor;
    21.             }
    22.             ENDCG
    Scene without fog shader
    upload_2019-11-22_14-46-31.png

    Current shader: (fog is red for visualisation) It gets applied more to areas where light is, but there no denser-getting fog in the distance
    upload_2019-11-22_14-45-30.png

    Unitys standard fog via lerp
    upload_2019-11-22_14-48-25.png
     
    protopop likes this.
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,256
  4. NekrosArts

    NekrosArts

    Joined:
    Nov 3, 2019
    Posts:
    18
    Thanks for the hint. Unfortunely I have to create my own shader since it´s a task for university. That´s why buying an asset is not an option :/ I need to solve this problem in someway
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,256
  6. NekrosArts

    NekrosArts

    Joined:
    Nov 3, 2019
    Posts:
    18
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,256
    Define better?

    Is the volumetric approach more realistic and less manual work to have it interact properly with arbitrary scenes? Yes. Much, much more expensive to render, and significantly more code to implement? Also yes.

    Sticking a cone mesh with an view angle and distance fading shader on each light is a ton less work overall for a single scene.
     
    NekrosArts likes this.