Search Unity

[Official] Changing how Fog is done in Unity shaders?

Discussion in 'Shaders' started by Aras, Aug 8, 2014.

  1. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    We're thinking about changing the way Fog is done in Unity shaders (for Unity 5 or so).

    Right now, fog calculations are "patched into" actual shaders, at runtime, on demand.
    Advantage: avoids situation of "ship 4x more shader variants" (none, linear, exp, exp2 fog types).
    Disadvantages: lots of complicated code implemented for each platform (d3d9, d3d11, opengl, gles); and some other platforms don't support fog at all (all consoles, WinPhone, iOS8 Metal).

    We'd like to change it so that fog calculations are done directly in shader code. Good things out of that:
    • Fog starts working on WinPhone, Metal, consoles.
    • Makes it easier to add better fog modes (like height-based fog).

    Practical implications for users / shader writers:
    • Fog command in shaderlab would stop working, except for cases like "Fog { Mode Off }" (which just disabled fog for this shader). In all other cases, most likely result is that fog as specified in render settings will be used. TLDR: no changing of fog modes / parameters per-shader, unless you're willing to implement your own fog calculations.
    • For vertex+fragment program shaders (i.e. not surface shaders), you'll have to add some macros / function calls to make fog work.
    • In order to avoid "well now you ship & load 4x more shader variants", we'll probably look at which fog modes are used in the scenes, and only include these shader variants into build.
      • Which would mean, don't change fog modes at runtime.
      • In case you do need that, we'll provide some UI somewhere to explicitly tell "hey I'll need these fog modes in the game".

    Does that make sense? Any comments?
     
  2. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    This makes a lot of sense. It'll be good to have a fog implementation that isn't opaque (lol) to the user.
     
  3. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Not much activity here, but quite some discussion (& approval) on the beta testing list. So here's the current plan; quite likely to become reality in Unity 5.0:
    1. For surface shaders, nothing needs to be done; fog variants & code will be generated. You can add "nofog" to #pragma surface line, if you really don't want fog.
    2. For vertex/fragment shaders, if you want fog you have to do this:
      1. Add #pragma multi_compile_fog
      2. Add UNITY_FOG_COORDS(n) to your vertex-to-fragment struct
      3. Add UNITY_TRANSFER_FOG(o,o.vertex); to your vertex shader. "o" is output struct name, and "o.vertex" is position in clip space.
      4. Add UNITY_APPLY_FOG(i.fogCoord, col); to end of your pixel shader. "i" is input struct name, and "col" is the color computed in your pixel shader. This applies standard fog color; if you want custom fog color (as some particle/additive shaders do, for example), you can do UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(0,0,0,0)); to fog towards black for example.
    3. For fixed function shaders, nothing needs to be done. "Fog { ... }" command in shaderlab still works, but now it only affects fixed function shaders (for non-fixed function, see point 2 above).
    4. By default, fog modes used by scenes are included into game data build. If you know you'll want to change them at runtime, you can choose "Custom fog modes" (default is "automatic") under project's Graphics Settings, and tick checkboxes you need.
    I have all the above working, and now fog "just works" on WP8/WinRT/consoles. Also, Unity codebase got smaller by 3500 lines of code. So there, yay.
     
    codestage, twobob and shkar-noori like this.
  4. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    Thats just like light attenuation, kinda of a hassle the first time but then it's all gravy

    Does this means i can have different object getting affected by fog in a different way, say color for example? I can see some usefulness in there
     
  5. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    You can do that right now (using ShaderLab's "Fog" command - each shader can have totally arbitrary fog). The plan is to remove support for that. However, since fog would be done "manually", you could just as well do "whatever you want" calculations there. There's nothing stopping you from not using our built-in fog macros.
     
    shkar-noori likes this.
  6. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    i see, thx for the explanation, i've gotta say i never did anything serious with the current fog system, hence my confusion

    I've noticed this current system uses a textcoord, light attenuation already uses 2, aren't we getting a bit short on these? I remember having created a complex shader that used all of the available ones, does using arrays of them help or solve the problem?
     
  7. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    It sounds good, but the thing is there is not much to play with fog except what unity already provides, we just need an additional height based fog.
    While we can write our own, it would be nice to have an option on the editor for global settings rather than adjusting fog for individual materials.
    Soo, just add the height based macro there and thats done.
    Or, just expose a fog function somewhere which we can overwrite with our own(if needed)?
     
  8. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Like I said in the first post - this is a prerequisite for adding fancier (atmospheric/height) based fog modes.
     
    twobob and shkar-noori like this.
  9. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Ohh...this is interesting, so this will change/remove the FinalColor in surface shader??
     
  10. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    If you're using FinalColor in surface shader, then we'll assume you want 100% control over your, well, final color -- and will not generate any built-in fog code in that case.
     
  11. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    I see...Hmmm oh hey about changing the built in fog into the shader as long as it make it better then i vote yes.
    Sure we have to adapt and if it's give better result then why not...:)
     
  12. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    You can't change built-in fog "into" a shader, since it needs to be done as part of other shaders while rendering.

    Of course you can do fog as a post-processing effect, and do whatever fancy calculations you want there! In fact, that's exactly what GlobalFog effect does (which I'm also changing for 5.0 to do something more sensible - but anyone can do that at any time; it's just a script+shader with full source).
     
  13. Reanimate_L

    Reanimate_L

    Joined:
    Oct 10, 2009
    Posts:
    2,788
    Woops...i mean "in the shader" not "into the shader", sorry
    Problem with GlobalFog is it doesn't work well with some transparent object ,out of the box of course except it's already changed in 5 :).
    Alright i don't want to derail this thread into GlobalFog discussion .
    Except if it is included in this thread topic.
     
  14. pvloon

    pvloon

    Joined:
    Oct 5, 2011
    Posts:
    591
    Wooh seems like a great chance Aras, the less shader patching the better. What kind of unity specific shader patching is still being done? Any improvments to lower memory and prewarming times are very welcome (does 5.0 still store shaders in hex instead of binary format?)
     
  15. Smartwater3D

    Smartwater3D

    Joined:
    May 16, 2014
    Posts:
    64
    I do not agree with Aubergine, Fog also needs to be used as complex fog volume if we want to have a seamless transition between over the water to under the water the way Crytek and Ubi does it. What Aras proposes is a good thing in order to make fog matching any type of mesh for example.

     
  16. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    @Smartwater3D: I don't see how my proposed change helps with implementing fog volumes, to be honest...
     
  17. qornflex

    qornflex

    Joined:
    Dec 6, 2012
    Posts:
    36
    I just made some tests. It seems OK but Legacy Shaders should use the old way. Otherwise porting 4.x projects to 5.x will be a nightmare if we have to add these macros in every shader we've already created.
     
  18. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    If you're using surface shaders, then nothing needs to be done. If you aren't, then yes, you should now add these macros.

    The problem with "legacy shaders" - there's no good way of knowing if a shader is legacy or not.
     
  19. Smartwater3D

    Smartwater3D

    Joined:
    May 16, 2014
    Posts:
    64
    "It sounds good, but the thing is there is not much to play with fog except what unity already provides, we just need an additional height based fog.": Aubergine.

    I do not agree about the fact we "only need additional height based fog".. That's what I mean. Fog can be used in a lot of different ways, and if we want to have a fog matching a moving surface for example, we need to access to how the fog is calculated and possibly change it.
    Also having access to the Grabpass code and being able to modify it would be great (but it is another subject)
     
  20. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Well, I already do fog in shader as it's a lot faster and looks practically the same as Unity fog (we just do it per vert and pass in few floats globally).

    Since fog is the job of shaders, having it outside of shaders is just misleading at this point. We need less mystery and more tweakability :) just my two cents.

    5 will change a lot of things. Physics, code, shaders. This is the best time to make changes. Some people will moan about changing their shaders, but really is that more than 5 mins work? I don't see it as a reason to worry.

    I'd like it to be explicitly asked for in the shader via a macro or whatever to avoid shipping 4x the amount, of course since not all my shaders use fog. Obviously :)
     
  21. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    You can already do whatever you want, moving CUSTOM fog around surfaces is already possible as well as any type of fog.
     
  22. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    hi there,

    i am pretty glad that i have found this thread and the little and new #pragma nofog!
    using the new deferred rendering you have to add fog as global image effect as only objects using forward rendering will get fog applied to.
    so objects that are not transparent but still uses a forward shader (due to a custom lighting function e.g.) while the camera is set to deferred will get the double amount of fog: 1 x by shader + 1 x image effect.

    and to give a pretty realistic example: tree creator leaves would not render correctly without #pragma nofog!

    lars
     
  23. dskillsaw

    dskillsaw

    Joined:
    Apr 26, 2012
    Posts:
    13
    I just ran into the issue where, as of Unity 5, I cannot change fog modes at runtime. You mention:
    • In case you do need that, we'll provide some UI somewhere to explicitly tell "hey I'll need these fog modes in the game".
    But I can't find any reference to how this is actually done. Can someone point me in the right direction? Took me a long time to track down the source of this bug, and I'd really like to get it fixed. It's difficult because changing fog modes at runtime does work in the editor, just not the build. Very confusing.
     
  24. dskillsaw

    dskillsaw

    Joined:
    Apr 26, 2012
    Posts:
    13
    Nevermind! I found it under the "graphics settings". Thanks Aras!
     
  25. Thomas-Molby

    Thomas-Molby

    Joined:
    Jan 14, 2013
    Posts:
    1
    Does anyone know of a way to use a custom property value for the density of an exponential fog, while still using the macros?
    I don't really know the shader syntax yet, so I suppose I could learn that and write it explicitly. But i still don't know which calculations the macros do.
     
  26. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    Sorry for resurrecting this old thread but ive hit a wall regarding the fog.
    Ive a standard shader with an additional pass to add some detail as soft additive blending. Fog is applied to the 2nd pass and no fog in the first surface shader, but then fog color is also additively blending and it looks weird.
    I can solve the issue with a 3rd pass to only add fog, though is there a way to finish it with 2 passes only?
     
  27. Aldrick

    Aldrick

    Joined:
    Feb 19, 2014
    Posts:
    64
    One thing that I don't understand is why the default unity particle additive shader use "UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(0,0,0,0)); to fog towards black".
    In what circumstance would we need a black fog effects on the particle?
     
  28. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,735
    Since it’s additive, it practically means it fades out.
     
  29. Aldrick

    Aldrick

    Joined:
    Feb 19, 2014
    Posts:
    64
    Yeah,it makes sense.But sometimes particles are needed to be rendered to a gui RT image,so the RGB value extracted from the original render could be wrong(towards pure black or blackish),if using this black fade calculation,despite the alpha value would be right,I can change the RT cameras setting to deal with that although.
     
  30. swanijam

    swanijam

    Joined:
    Nov 14, 2016
    Posts:
    23
    Why is it that fog is computed per-object in forward and only as an image-effect in deffered, anyway? What limitations or advantages led per object fog, and why can't it apply to deferred rendering?