Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

How can I control fog color based on skybox color?

Discussion in 'General Graphics' started by Drewson, Mar 18, 2015.

  1. Drewson

    Drewson

    Joined:
    Apr 19, 2009
    Posts:
    168
    Hello - I have a gradient on a skybox, and I want the terminal fog color to be the same as the sky color behind the object that is being occluded. But it still needs to be fog and respect distance.

    I see one way of doing it without actually using fog, with a gradient of my choosing on a skybox. The skybox gets masked out by the depth map, and then overlaid onto the non-sky geometry. You would be able to look down into the depths, and the blackness below gets darker gradually like a "fog" because it is masked by the depth operation. Look up and see the same phenomenon with the lighter color. Basically control "fog" terminal color by camera angle.

    See a mockup below with grey cubes at various distances that I made in photoshop - note how the very distant cubes are getting fogged in a color that blends with the skybox:

    fog_plus_skybox.JPG

    What would be the best way to implement this, and could it be performant on mobile devices?

    Thanks :)
     
    Last edited: Mar 18, 2015
  2. Maxi77

    Maxi77

    Joined:
    Mar 3, 2015
    Posts:
    14
    I have been trying to solve the same problem.
    I am using the procedural skybox in unity 5, and would like the geometry to blend in based on distance from camera. The picture above is a great example.
     
  3. Drewson

    Drewson

    Joined:
    Apr 19, 2009
    Posts:
    168
    Thanks - yeah I'm not a master of rendering, got some shader skills but this stuff is over my head.
     
  4. Drewson

    Drewson

    Joined:
    Apr 19, 2009
    Posts:
    168
    Bumping my question.
     
  5. DragonRider

    DragonRider

    Joined:
    Jul 19, 2012
    Posts:
    9
    If all you need to do is change the fog color based on camera angle, it's fairly simple to script - lighten the fog when facing the sun, darken it when facing away - a rather cheap illusion that can work well in certain situations. But it's far from perfect.

    Using the skybox as render color for the fog is trickier, but certainly doable.

    My theory goes something like this:

    Render the skybox to a buffer.
    Render the depth map.
    Overlay skybox image onto main camera using depthmap as alpha ( would need to apply some maths to determine where fog starts and ends ).

    Far from elegant, but if you can figure out how to implement it, it might do the trick.
     
  6. Recluse

    Recluse

    Joined:
    May 16, 2010
    Posts:
    427
    Nice image! It would be brilliant if Unity's fog would do something like this out of the box, rather than just fading to a single colour. I'm wondering how to get the fog colour to match the constantly changing procedural skybox of a night-day cycle.

    Unity's procedural skybox shader looks lovely as the directional sun light rotates, but the effect is ruined by the global fog, which stands out against the horizon. Can we have a fog in Unity that fades objects out to transparency?
     
    Last edited: May 15, 2015
    gstarch likes this.
  7. Soul-Challenger

    Soul-Challenger

    Joined:
    Dec 30, 2010
    Posts:
    152
  8. Threepwood

    Threepwood

    Joined:
    Jul 23, 2009
    Posts:
    86
    Just looked at KinoFog above. It only works with cubemap skyboxes and not procedural ones.
     
  9. Discord

    Discord

    Joined:
    Mar 19, 2009
    Posts:
    1,002
    KinoFog worked perfectly with a cubemap, I really wish there was something comparable that worked with the procedural ones as well.
     
  10. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    6,691
    Discord likes this.
  11. Discord

    Discord

    Joined:
    Mar 19, 2009
    Posts:
    1,002
    Thanks for the tip! I was able to get it working by creating another skybox material, passing it the data from a reflection probe, and then passing that material to KinoFog. So a little silly having to use two different skybox materials, but it was a quick fix.
     
  12. jc_lvngstn

    jc_lvngstn

    Joined:
    Jul 19, 2006
    Posts:
    1,503
    So...I've been lurking in the forums for a while. Not active at all like I used to be, but I still love reading various forums. Especially the graphics/shader ones.
    And I just have to give some kudos and appreciation to bgolus. Man...you are incredibly helpful, thanks for sharing your knowledge in these areas, ESPECIALLY shaders. I see post after post where this helps MANY people. You are a huge positive in the Unity community.
     
    LightingBox2 likes this.
  13. LightingBox2

    LightingBox2

    Joined:
    Mar 31, 2015
    Posts:
    2,777
    bgolus help me a lot too. He is very helpful man and very clever in shader programing.
     
  14. andrew-lukasik

    andrew-lukasik

    Joined:
    Jan 31, 2013
    Posts:
    131
    I'm definitely not a shader wizard here (more of a noob really) but figured out a way to make a fog color match with skybox colors behind it (procedural too).
    I made a new Camera nearly identical and parented to to Main one. But this one renders ONLY skybox (but I can imagine some custom bg layer with fx meshes here too) to RenderTexture (fairly small in my case). Then after few changes in both GlobalFog.cs and GlobalFog.shader I feeded that RenderTexture as fog color :D



    Steps to follow:

    - import "Legacy Cinematic Image Effects" package https://www.assetstore.unity3d.com/en/#!/content/51515
    EDIT: proper link as suggested in post below: https://www.assetstore.unity3d.com/en/#!/content/83913

    GlobalFog.cs changes:
    - add new field somewhere at the beginning of this class:
    Code (CSharp):
    1. [SerializeField] RenderTexture _fogColorTexture;
    - setup feeding mechanism for render texture to GlobalFog shader
    Code (CSharp):
    1. public override bool CheckResources () {
    2.             /* some code here left unchanged */
    3.  
    4.            //insert code below after line that look like this: "fogMaterial = CheckShaderAndCreateMaterial(..."
    5.             if( _fogColorTexture!=null ) {
    6.                 fogMaterial.SetTexture( "_FogColorTexture" , _fogColorTexture );
    7.             }
    8.  
    9.             /* some code here left unchanged */
    10.         }
    GlobalFog.shader changes:

    - inside "Properties {}" add new line:
    Code (CSharp):
    1. _FogColorTexture ("Base (RGB)", 2D) = "white" {}
    - under "CGINCLUDE" add:
    Code (CSharp):
    1. uniform sampler2D _FogColorTexture;
    - find ComputeFog function and insert this in one the first lines there:
    Code (CSharp):
    1. half4 fogColor = tex2D( _FogColorTexture , UnityStereoTransformScreenSpaceTex(i.uv) );
    - change these lines:
    Code (CSharp):
    1. // Do not fog skybox
    2. if (dpth == _DistanceParams.y)
    3.     fogFac = 1.0;
    to:
    Code (CSharp):
    1. // draw skybox from my RenderTexture
    2. if (dpth == _DistanceParams.y)
    3.     return fogColor;
    - and lastly, replace ending of this function:
    Code (CSharp):
    1. return lerp ( unity_FogColor , sceneColor , fogFac );
    with:
    Code (CSharp):
    1. return lerp ( fogColor , sceneColor , fogFac );
    - create a new Camera nearly identical (same FOV etc) and parented to to your Main one. Set Culling Mask to Nothing and ClearFlags to Skybox

    - in Project window create new RenderTexture

    - set this new RenderTexture as Render Target for our new Camera

    - Add GlobalFog.cs script to MAIN camera and set this new RenderTexture there as Fog Color Texture

    - go to native fog setting in Lighting window, set everything like mode, start/end, density etc - ! BUT ! disable it when done

    - colored fog should be working now

    - in order to achieve perfect match between fog-sky colors (like in my case) you may want to change ClearFlag in your MAIN camera to DepthOnly. But beware that this will effectively draw RenderTexture as sky so setting proper resolution for it will be more important here
     
    Last edited: May 24, 2018
  15. kurt-at-stimulant

    kurt-at-stimulant

    Joined:
    Oct 25, 2017
    Posts:
    1
    Hey Andrew, great post, thanks for this. Totally got it working for me using this method.

    Small correction- you linked to "Legacy Cinematic Image Effects" which doesn't include GlobalFog.cs. The regular "Legacy Image Effects" is here: https://www.assetstore.unity3d.com/en/#!/content/83913
     
    Torbach78 and andrew-lukasik like this.
  16. sfrisby

    sfrisby

    Joined:
    Oct 12, 2014
    Posts:
    1
    Great solution Andrew, thanks for writing that out!
     
  17. andrew-lukasik

    andrew-lukasik

    Joined:
    Jan 31, 2013
    Posts:
    131
    You're welcome! But if you invent or came across any better solution - please let us know!
    I would love to see how can this effect be created in more compact and||or performant way. Or even how more up to date versions of unity can help. For example, will SRP be of any use here?