Search Unity

Screen Space Multiple Scattering

Discussion in 'Works In Progress' started by OCASM, Dec 17, 2016.

  1. id0

    id0

    Joined:
    Nov 23, 2012
    Posts:
    199
    Hello OCASM. I have strange glitchy lines when I look on the sky with this settings (height fog)

     

    Attached Files:

  2. OCASM

    OCASM

    Joined:
    Jan 12, 2011
    Posts:
    211
    Maybe other effects are interfering with it, like the Nightvision script seen in that screenshot?
     
  3. id0

    id0

    Joined:
    Nov 23, 2012
    Posts:
    199
    No, I turn off all of them and still the same. You can try yourself with this settings (you must stay inside height fog)
     
  4. OCASM

    OCASM

    Joined:
    Jan 12, 2011
    Posts:
    211
    Mhh, I'm afraid I can't do any testing right now because my computer is busted. Does it happen in an empty scene?
     
  5. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    441
    Could you improve the script ? I mean new version with new features.
     
  6. OCASM

    OCASM

    Joined:
    Jan 12, 2011
    Posts:
    211
    Probably but don't expect anything soon.
     
  7. xrooshka

    xrooshka

    Joined:
    Mar 5, 2014
    Posts:
    43
    Hello guys! I found a problem with semitransparent objects: fog just don't affect them. My friend just fixed it by commenting the line "[ImageEffectOpaque]" and objects,that lying right on the opaque surface start look good. But not the semitransparent objects far from opaque: now fog is drawing right on top of everything.

    Can anyone fix that problem?
     
  8. olix4242

    olix4242

    Joined:
    Jul 21, 2013
    Posts:
    1,258
    Simple yet great effect. Did some tests today:
     
    wetcircuit, hopeful, ftejada and 8 others like this.
  9. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    441
    I really hope someone will improve this Global Fog effect.
     
    Lohrion, Alverik and ftejada like this.
  10. konsic

    konsic

    Joined:
    Oct 19, 2015
    Posts:
    484
    Could you put this on asset store as plugin ?
     
  11. Lars-Steenhoff

    Lars-Steenhoff

    Joined:
    Aug 7, 2007
    Posts:
    1,944
    I think its fine on GitHub :)
     
    dadude123, Mauri and Lysander like this.
  12. Apposl

    Apposl

    Joined:
    Nov 27, 2017
    Posts:
    35
    This is really incredible. Can anyone suggest a way to make the fog *not* go inside buildings? I know it's attached to the camera so...maybe not?
     
  13. Elecman

    Elecman

    Joined:
    May 5, 2011
    Posts:
    1,307
    Any progress on the fog noise feature?
     
  14. zmaxz

    zmaxz

    Joined:
    Sep 26, 2012
    Posts:
    139
    It doesn't seem to be working with "Enviro - Sky and Weather".It's too bad !!
     
  15. karmakat

    karmakat

    Joined:
    Jul 25, 2013
    Posts:
    2
    Hi All,

    I have nearly completed porting this effect from a camera component to the Post-Processing Stack v2. However, I have a few small stumbling blocks and thought I'd share my work so far to see if I could get any feedback from the community to help troubleshoot the remaining issues.

    I have two major issues to solve still:
    • I did manage to get the fog mostly working, but the vertical fog is behaving a bit strangely. It looks like it is actually working on the X axis instead of the Y. Any feedback on what I have done so far would be much appreciated if anything jumps out at people.

    • I got most of the refactoring complete for the SMSS effect, but I am stumbling with problems with the following: The C# BlitFullscreenTriangle method is markedly different from the Graphics.Blit method in that it uses a RenderTargetIdentifier object instead of a Texture object. I was able to totally replace the Graphics.Blit method successfully in the PostProcessFog shader, but not the ScreenSpaceMultiScatter shader, where around lines 230, 240, 257, and 264-268 of ScreenSpaceMultiScatter.cs, my refactoring starts to break down.

    I am still fairly new to both C# and shader development, so please excuse any naivety in my work.

    A few points to consider:
    • I am using this for forward rendering, and using single-pass stereo. I put the call to enable the depth pass on the camera inside the PostProcessFog.cs script.
    • The postprocess stack v2 uses a full-screen triangle instead of quad and positions that triangle in front of the camera in a particular way using the TransformTriangleVertexToUV method. However, because there are duplicate declarations in the "StdLib.hlsl" and "UnityCG.cginc", I ported the methods from "StdLib.hlsl"
      into my own shader and cg include file to avoid conflicts and still be able to use needed items from "UnityCG.cginc"
    The main fog shader :

    Code (csharp):
    1. Shader "PostProcessFog"
    2. {
    3.     Properties
    4.     {
    5.         //_MainTex("Base (RGB)", 2D) = "black" {}
    6.         _CameraDepthTexture ("Depth", 2D) = "blue" {}
    7.  
    8.     }
    9.  
    10.     HLSLINCLUDE
    11.  
    12.         //#include "Assets/PostProcessing/Shaders/StdLib.hlsl"
    13.         #include "UnityCG.cginc"
    14.  
    15.         uniform sampler2D _MainTex;
    16.         uniform sampler2D_float _CameraDepthTexture;
    17.  
    18.         uniform float4 _HeightParams;
    19.         uniform float4 _DistanceParams;
    20.  
    21.         int4 _SceneFogMode; // x = fog mode, y = use radial flag
    22.         float4 _SceneFogParams;
    23.  
    24.         float _EnLoss;
    25.         float _MaxValue;
    26.         float4 _FogTint;
    27.  
    28.  
    29.         #ifndef UNITY_APPLY_FOG
    30.             half4 unity_FogColor;
    31.             half4 unity_FogDensity;
    32.         #endif
    33.  
    34.         uniform float4 _MainTex_TexelSize;
    35.  
    36.         // for fast world space reconstruction
    37.         uniform float4x4 _FrustumCornersWS;
    38.         uniform float4 _CameraWS;
    39.  
    40.         float LinearEyeDepth135( float z )
    41.         {
    42.             return LinearEyeDepth( z );
    43.         }
    44.         // Vertex manipulation
    45.         float2 TransformTriangleVertexToUV(float2 vertex)
    46.         {
    47.             float2 uv = (vertex + 1.0) * 0.5;
    48.             return uv;
    49.         }
    50.         //-----------------------------------------------------------------------------
    51.         //Default vertex shaders
    52.  
    53.         struct AttributesDefault
    54.         {
    55.             float3 vertex : POSITION;
    56.             half2 texcoord : TEXCOORD0;
    57.         };
    58.  
    59.         struct VaryingsDefault
    60.         {
    61.             float4 pos : SV_POSITION;
    62.             float2 uv : TEXCOORD0;
    63.             //float2 uvStereo : TEXCOORD1;
    64.             float2 uv_depth : TEXCOORD1;
    65.             float4 interpolatedRay : TEXCOORD2;
    66.         };
    67.  
    68.         VaryingsDefault VertDefault(AttributesDefault v  )
    69.         {
    70.             VaryingsDefault o;
    71.             v.vertex.z = 0.1;
    72.             o.pos = float4(v.vertex.xy, 0.0, 1.0);
    73.             o.uv = TransformTriangleVertexToUV(v.vertex.xy);
    74.             o.uv_depth = v.texcoord.xy;
    75.  
    76.             #if UNITY_UV_STARTS_AT_TOP
    77.                 o.uv = o.uv * float2(1.0, -1.0) + float2(0.0, 1.0);
    78.             #endif
    79.          
    80.             //o.uvStereo = TransformStereoScreenSpaceTex(o.uv, 1.0);
    81.  
    82.             #if UNITY_UV_STARTS_AT_TOP
    83.                 if (_MainTex_TexelSize.y < 0)
    84.                     o.uv.y = 1 - o.uv.y;
    85.             #endif
    86.  
    87.             int frustumIndex = v.texcoord.x + (2 * o.uv.y);
    88.             o.interpolatedRay = _FrustumCornersWS[frustumIndex];
    89.             o.interpolatedRay.w = frustumIndex;
    90.  
    91.             return o;
    92.         }
    93.      
    94.         // Applies one of standard fog formulas, given fog coordinate (i.e. distance)
    95.         half ComputeFogFactor(float coord)    {
    96.  
    97.             float fogFac = 0.0;
    98.             if (_SceneFogMode.x == 1) // linear
    99.             {
    100.                 // factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start))
    101.                 fogFac = coord * _SceneFogParams.z + _SceneFogParams.w;
    102.             }
    103.             if (_SceneFogMode.x == 2) // exp
    104.             {
    105.                 // factor = exp(-density*z)
    106.                 fogFac = _SceneFogParams.y * coord; fogFac = exp2(-fogFac);
    107.             }
    108.             if (_SceneFogMode.x == 3) // exp2
    109.             {
    110.                 // factor = exp(-(density*z)^2)
    111.                 fogFac = _SceneFogParams.x * coord; fogFac = exp2(-fogFac*fogFac);
    112.             }
    113.             return saturate(fogFac);
    114.         }
    115.  
    116.         // Distance-based fog
    117.         float ComputeDistance(float3 camDir, float zdepth)
    118.         {
    119.  
    120.             float dist;
    121.             if (_SceneFogMode.y == 1)
    122.                 dist = length(camDir);
    123.             else
    124.                 dist = zdepth * _ProjectionParams.z;
    125.             // Built-in fog starts at near plane, so match that by
    126.             // subtracting the near value. Not a perfect approximation
    127.             // if near plane is very large, but good enough.
    128.             dist -= _ProjectionParams.y;
    129.             return dist;
    130.         }
    131.  
    132.         // Linear half-space fog, from https://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf
    133.         float ComputeHalfSpace(float3 wsDir)
    134.         {
    135.  
    136.             float3 wpos = _CameraWS + wsDir;
    137.             float FH = _HeightParams.x;
    138.             float3 C = _CameraWS;
    139.             float3 V = wsDir;
    140.             float3 P = wpos;
    141.             float3 aV = _HeightParams.w * V;
    142.             float FdotC = _HeightParams.y;
    143.             float k = _HeightParams.z;
    144.             float FdotP = P.y - FH;
    145.             float FdotV = wsDir.y;
    146.             float c1 = k * (FdotP + FdotC);
    147.             float c2 = (1 - 2 * k) * FdotP;
    148.             float g = min(c2, 0.0);
    149.             g = -length(aV) * (c1 - g * g / abs(FdotV + 1.0e-5f));
    150.             return g;
    151.  
    152.         }
    153.  
    154.         half4 ComputeFog( VaryingsDefault i, bool distance, bool height) : SV_Target
    155.         {
    156.             half4 sceneColor = tex2D(_MainTex, UnityStereoTransformScreenSpaceTex(i.uv));
    157.  
    158.             // Reconstruct world space position & direction
    159.             // towards this screen pixel.
    160.             float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoTransformScreenSpaceTex(i.uv ));
    161.  
    162.             float dpth = Linear01Depth(rawDepth);
    163.             float4 wsDir = dpth * i.interpolatedRay;
    164.             float4 wsPos = _CameraWS + wsDir;
    165.  
    166.             // Compute fog distance
    167.             float g = _DistanceParams.x;
    168.             if (distance)
    169.                 g += ComputeDistance(wsDir, dpth);
    170.             if (height)
    171.                 g += ComputeHalfSpace(wsDir);
    172.  
    173.             // Compute fog amount
    174.             half fogFac = ComputeFogFactor(max(0.0,g));
    175.             // Do not fog skybox
    176.             if (dpth == _DistanceParams.y)
    177.                 fogFac = 1.0;
    178.             //return fogFac; // for debugging
    179.  
    180.             // Lerp between fog color & original scene color
    181.             // by fog amount
    182.             half4 sceneColorDark = sceneColor * pow(fogFac, clamp(_EnLoss,0.001,100));
    183.             return lerp(unity_FogColor * half4(_FogTint.rgb,1), lerp(sceneColor, sceneColorDark, _MaxValue),  clamp(fogFac, 1 - _MaxValue ,1));
    184.         }
    185.  
    186.         half4 ComputeFogB( VaryingsDefault i, bool distance, bool height) : SV_Target
    187.         {
    188.             // Reconstruct world space position & direction
    189.             // towards this screen pixel.
    190.             float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoTransformScreenSpaceTex(i.uv ));
    191.          
    192.             float dpth = Linear01Depth(rawDepth);
    193.             float4 wsDir = dpth * i.interpolatedRay;
    194.             float4 wsPos = _CameraWS + wsDir;
    195.  
    196.             // Compute fog distance
    197.             float g = _DistanceParams.x;
    198.             if (distance)
    199.                 g += ComputeDistance(wsDir, dpth);
    200.             if (height)
    201.                 g += ComputeHalfSpace(wsDir);
    202.  
    203.             // Compute fog amount
    204.             half fogFac = ComputeFogFactor(max(0.0,g));
    205.             // Do not fog skybox
    206.             if (dpth == _DistanceParams.y)
    207.                 fogFac = 1.0;
    208.             //return fogFac; // for debugging
    209.  
    210.             // Lerp between fog color & original scene color
    211.             // by fog amount
    212.             unity_FogColor = (unity_FogColor.r + unity_FogColor.y + unity_FogColor.z) / 3;
    213.             unity_FogColor = unity_FogColor * (1 / unity_FogColor);
    214.             return unity_FogColor * (1 - fogFac);
    215.         }
    216.  
    217.     ENDHLSL
    218.  
    219.     SubShader
    220.     {
    221.         ZTest Always Cull Off ZWrite Off Fog{ Mode Off }
    222.  
    223.         // 0: distance + height
    224.         Pass
    225.         {
    226.             HLSLPROGRAM
    227.                 #pragma vertex VertDefault
    228.                 #pragma fragment frag
    229.                 half4 frag(VaryingsDefault i) : SV_Target{ return ComputeFog(i, true, true); }
    230.             ENDHLSL
    231.         }
    232.      
    233.         // 1: distance
    234.         Pass
    235.         {
    236.             HLSLPROGRAM
    237.                 #pragma vertex VertDefault
    238.                 #pragma fragment frag
    239.                 half4 frag(VaryingsDefault i) : SV_Target{ return ComputeFog(i, true, false); }
    240.             ENDHLSL
    241.         }
    242.      
    243.         // 2: height
    244.         Pass
    245.         {
    246.             HLSLPROGRAM
    247.                 #pragma vertex VertDefault
    248.                 #pragma fragment frag
    249.                 half4 frag(VaryingsDefault i) : SV_Target{ return ComputeFog(i, false, true); }
    250.             ENDHLSL
    251.         }
    252.            
    253.         // Only outputs fog color
    254.         // 3: distance + height
    255.         Pass
    256.         {
    257.             HLSLPROGRAM
    258.                 #pragma vertex VertDefault
    259.                 #pragma fragment frag
    260.                 half4 frag(VaryingsDefault i) : SV_Target{ return ComputeFogB(i, true, true); }
    261.             ENDHLSL
    262.         }
    263.  
    264.         // 4: distance
    265.         Pass
    266.         {
    267.             HLSLPROGRAM
    268.                 #pragma vertex VertDefault
    269.                 #pragma fragment frag
    270.             half4 frag(VaryingsDefault i) : SV_Target{ return ComputeFogB(i, true, false); }
    271.             ENDHLSL
    272.         }
    273.  
    274.         // 5: height
    275.         Pass
    276.         {
    277.             HLSLPROGRAM
    278.                 #pragma vertex VertDefault
    279.                 #pragma fragment frag
    280.                 half4 frag(VaryingsDefault i) : SV_Target{ return ComputeFogB(i, false, true); }
    281.             ENDHLSL
    282.         }
    283.  
    284.      } // End SubShader
    285.  
    286. } // End Shader

    The Post-Processing C# for the fog and stack rollout:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Rendering.PostProcessing;
    4. using System.Collections;
    5.  
    6. namespace UnityEngine.Rendering.PostProcessing
    7. {
    8.  
    9.     [Serializable]
    10.     public sealed class FogModeParameter : ParameterOverride<FogMode> { }
    11.  
    12.     [Serializable]
    13.     [PostProcess(typeof(PostProcessFogRenderer), PostProcessEvent.AfterStack, "PostProcessFog")]
    14.     public sealed class PostProcessFog : PostProcessEffectSettings
    15.     {
    16.        
    17.  
    18.         [Tooltip("Apply distance-based fog?")]
    19.         public BoolParameter distanceFog = new BoolParameter { value = true };
    20.  
    21.         [Tooltip("Exclude far plane pixels from distance-based fog? (Skybox or clear color)")]
    22.         public BoolParameter excludeFarPixels = new BoolParameter { value = true };
    23.  
    24.         [Tooltip("Distance fog is based on radial distance from camera when checked")]
    25.         public BoolParameter useRadialDistance = new BoolParameter { value = false };
    26.  
    27.         [Tooltip("Apply height-based fog?")]
    28.         public BoolParameter heightFog = new BoolParameter { value = true };
    29.  
    30.         [Tooltip("Fog top Y coordinate")]
    31.         public FloatParameter height = new FloatParameter { value = 1.0f };
    32.  
    33.         [Range(0.001f, 100.0f)]
    34.         public FloatParameter heightDensity = new FloatParameter { value = 2.0f };
    35.  
    36.         [Tooltip("Push fog away from the camera by this amount")]
    37.         public FloatParameter startDistance = new FloatParameter { value = 0.0f };
    38.  
    39.         [Tooltip("Clips max fog value. Allows bright lights to shine through.")]
    40.         [Range(0, 1)]
    41.         public FloatParameter maxDensity = new FloatParameter { value = 0.999f };
    42.  
    43.         [Tooltip("How much light is absorbed by the fog. Not physically correct at all.")]
    44.         [Range(0, 100)]
    45.         public FloatParameter energyLoss = new FloatParameter { value = 0f };
    46.  
    47.         [Tooltip("Tints the color of this instance of Global Fog.")]
    48.         public ColorParameter fogTint = new ColorParameter { value = Color.white };
    49.  
    50.         [Header("Global Fog Settings")]
    51.         [Tooltip("Overrides global settings.")]
    52.         public BoolParameter setGlobalSettings = new BoolParameter { value = false };
    53.  
    54.         //
    55.         public ColorParameter fogColor = new ColorParameter { value = Color.white };
    56.  
    57.         //
    58.         public FogModeParameter fogMode = new FogModeParameter { value = FogMode.Linear };
    59.  
    60.         [Tooltip("For exponential modes only.")]
    61.         [Range(0, 1)]
    62.         public FloatParameter fogDensity = new FloatParameter { value = 0f };
    63.  
    64.         [Tooltip("For linear mode only.")]
    65.         public FloatParameter fogStart = new FloatParameter { value = 0f };
    66.  
    67.         [Tooltip("For linear mode only.")]
    68.         public FloatParameter fogEnd = new FloatParameter { value = 0f };
    69.  
    70.         public Shader fogShader = null;
    71.         public Material fogMaterial = null;
    72.  
    73.         public BoolParameter saveFogRT = new BoolParameter { value = true };
    74.  
    75.         [HideInInspector]
    76.         public RenderTexture fogRT;
    77.  
    78.         //
    79.         public DepthTextureMode GetCameraFlags()
    80.         {
    81.             return DepthTextureMode.Depth; //| DepthTextureMode.DepthNormals;
    82.         }
    83.     }
    84.  
    85.     [ExecuteInEditMode]
    86.     public sealed class PostProcessFogRenderer : PostProcessEffectRenderer<PostProcessFog>
    87.     {
    88.  
    89.         public override void Render(PostProcessRenderContext context)
    90.         {
    91.             //VRTK_Orientation.Up
    92.  
    93.             var sheet = context.propertySheets.Get( Shader.Find( "PostProcessFog" ) );
    94.  
    95.             // Global fog settings
    96.  
    97.             if ( settings.setGlobalSettings.value )
    98.             {
    99.                 if (settings.fogStart.value < 0) { settings.fogStart.value = 0.0f; }
    100.                 if (settings.fogEnd.value < 0) { settings.fogEnd.value = 0.0f; }
    101.  
    102.                 RenderSettings.fogColor = settings.fogColor.value;
    103.                 RenderSettings.fogMode = settings.fogMode;
    104.                 RenderSettings.fogDensity = settings.fogDensity;
    105.                 RenderSettings.fogStartDistance = settings.fogStart;
    106.                 RenderSettings.fogEndDistance = settings.fogEnd;
    107.             }
    108.  
    109.             if (/*CheckResources() == false ||*/ (!settings.distanceFog && !settings.heightFog))
    110.             {
    111.                 context.command.BlitFullscreenTriangle(context.source, context.destination, sheet, 0);
    112.                 return;
    113.             }
    114.  
    115.             RenderTexture fogRenderTexture;
    116.  
    117.             if ( settings.saveFogRT.value && settings.fogRT == null )
    118.             {
    119.                 fogRenderTexture = new RenderTexture( context.width, context.height, 0, RenderTextureFormat.Default);
    120.             }
    121.             else
    122.             {
    123.                 fogRenderTexture = settings.fogRT;
    124.             }
    125.  
    126.             Camera cam = context.camera;
    127.  
    128.             Transform camtr = cam.transform;
    129.  
    130.             Vector3[] frustumCorners = new Vector3[4];
    131.             cam.CalculateFrustumCorners( new Rect(0, 0, 1, 1), cam.farClipPlane, cam.stereoActiveEye, frustumCorners );
    132.             var bottomLeft = camtr.TransformVector( frustumCorners[0] );
    133.             var topLeft = camtr.TransformVector( frustumCorners[1] );
    134.             var topRight = camtr.TransformVector( frustumCorners[2] );
    135.             var bottomRight = camtr.TransformVector( frustumCorners[3] );
    136.  
    137.             Matrix4x4 frustumCornersArray = Matrix4x4.identity;
    138.             frustumCornersArray.SetRow(0, bottomLeft);
    139.             frustumCornersArray.SetRow(1, bottomRight);
    140.             frustumCornersArray.SetRow(2, topLeft);
    141.             frustumCornersArray.SetRow(3, topRight);
    142.  
    143.             var camPos = camtr.position;
    144.             float FdotC = camPos.y - settings.height.value;
    145.             float paramK = (FdotC <= 0.0f ? 1.0f : 0.0f);
    146.             float excludeDepth = ( settings.excludeFarPixels.value ? 1.0f : 2.0f );
    147.  
    148.             sheet.properties.SetMatrix( "_FrustumCornersWS", frustumCornersArray );
    149.             sheet.properties.SetVector( "_CameraWS", camPos );
    150.             sheet.properties.SetVector( "_HeightParams", new Vector4( settings.height.value, FdotC, paramK, settings.heightDensity.value * 0.5f ) );
    151.             sheet.properties.SetVector( "_DistanceParams", new Vector4( -Mathf.Max(settings.startDistance.value, 0.0f ), excludeDepth, 0, 0 ) );
    152.  
    153.             var sceneMode = RenderSettings.fogMode;
    154.             var sceneDensity = RenderSettings.fogDensity;
    155.             var sceneStart = RenderSettings.fogStartDistance;
    156.             var sceneEnd = RenderSettings.fogEndDistance;
    157.  
    158.             Vector4 sceneParams;
    159.             bool linear = (sceneMode == FogMode.Linear);
    160.             float diff = linear ? sceneEnd - sceneStart : 0.0f;
    161.             float invDiff = Mathf.Abs(diff) > 0.0001f ? 1.0f / diff : 0.0f;
    162.  
    163.             sceneParams.x = sceneDensity * 1.2011224087f; // density / sqrt(ln(2)), used by Exp2 fog mode
    164.             sceneParams.y = sceneDensity * 1.4426950408f; // density / ln(2), used by Exp fog mode
    165.             sceneParams.z = linear ? -invDiff : 0.0f;
    166.             sceneParams.w = linear ? sceneEnd * invDiff : 0.0f;
    167.  
    168.             sheet.properties.SetVector( "_SceneFogParams", sceneParams );
    169.             sheet.properties.SetVector( "_SceneFogMode", new Vector4((int)sceneMode, settings.useRadialDistance.value ? 1 : 0, 0, 0 ) );
    170.  
    171.             sheet.properties.SetColor( "_FogTint", settings.fogTint.value );
    172.             sheet.properties.SetFloat( "_MaxValue", settings.maxDensity.value );
    173.             sheet.properties.SetFloat( "_EnLoss", settings.energyLoss.value );
    174.  
    175.             int pass = 0;
    176.             if ( settings.distanceFog.value && settings.heightFog.value )
    177.             {
    178.  
    179.                 pass = 0; // distance + height
    180.  
    181.                 if ( settings.saveFogRT.value )
    182.                 {
    183.                     context.command.BlitFullscreenTriangle( context.source, context.destination, sheet, 3 );
    184.                 }
    185.  
    186.             }
    187.             else if ( settings.distanceFog.value )
    188.             {
    189.  
    190.                 pass = 1; // distance only
    191.  
    192.                 if ( settings.saveFogRT.value )
    193.                 {
    194.                     context.command.BlitFullscreenTriangle( context.source, context.destination, sheet, 4 );
    195.                 }
    196.  
    197.             }
    198.             else
    199.             {
    200.  
    201.                 pass = 2; // height only
    202.  
    203.                 if ( settings.saveFogRT.value )
    204.                 {
    205.                     context.command.BlitFullscreenTriangle( context.source, context.destination, sheet, 5 );
    206.                 }
    207.  
    208.             }
    209.  
    210.             //Graphics.Blit(context.source, context.destination, settings.fogMaterial, pass);
    211.             context.command.BlitFullscreenTriangle( context.source, context.destination, sheet, pass );
    212.  
    213.             Shader.SetGlobalTexture( "_FogTex", settings.fogRT );
    214.  
    215.             if ( !settings.saveFogRT && settings.fogRT != null )
    216.             {
    217.                 settings.fogRT.Release();
    218.             }
    219.          
    220.         }
    221.  
    222.     }
    223. }
    The SMSS shader:

    Code (CSharp):
    1. // Screen Space Multiple Scattering for Unity
    2. //
    3. // Copyright (C) 2015, 2016 Keijiro Takahashi, OCASM
    4. //
    5. // Permission is hereby granted, free of charge, to any person obtaining a copy
    6. // of this software and associated documentation files (the "Software"), to deal
    7. // in the Software without restriction, including without limitation the rights
    8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    9. // copies of the Software, and to permit persons to whom the Software is
    10. // furnished to do so, subject to the following conditions:
    11. //
    12. // The above copyright notice and this permission notice shall be included in
    13. // all copies or substantial portions of the Software.
    14. //
    15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    21. // THE SOFTWARE.
    22. //
    23. Shader "ScreenSpaceMultiScatter"
    24. {
    25.     Properties
    26.     {
    27.         _MainTex("", 2D) = "" {}
    28.         _BaseTex("", 2D) = "" {}
    29.     }
    30.  
    31.     SubShader
    32.     {
    33.  
    34.         // 0: Prefilter
    35.         Pass
    36.         {
    37.             ZTest Always Cull Off ZWrite Off
    38.             HLSLPROGRAM
    39.                 #pragma multi_compile _ UNITY_COLORSPACE_GAMMA
    40.                 #include "SHDINC-shd_screenSpaceMultiScatter-default.cginc"
    41.                 #pragma vertex VertDefault
    42.                 #pragma fragment frag_prefilter
    43.                 #pragma target 3.0
    44.             ENDHLSL
    45.         }
    46.  
    47.         // 1: Prefilter with anti-flicker
    48.         Pass
    49.         {
    50.             ZTest Always Cull Off ZWrite Off
    51.  
    52.             HLSLPROGRAM
    53.                 #define ANTI_FLICKER 1
    54.                 #pragma multi_compile _ UNITY_COLORSPACE_GAMMA
    55.                 #include "SHDINC-shd_screenSpaceMultiScatter-default.cginc"
    56.                 #pragma vertex VertDefault
    57.                 #pragma fragment frag_prefilter
    58.                 #pragma target 3.0
    59.             ENDHLSL
    60.         }
    61.  
    62.         // 2: First level downsampler
    63.         Pass
    64.         {
    65.             ZTest Always Cull Off ZWrite Off
    66.  
    67.             HLSLPROGRAM
    68.                 #include "SHDINC-shd_screenSpaceMultiScatter-default.cginc"
    69.                 #pragma vertex VertDefault
    70.                 #pragma fragment frag_downsample1
    71.                 #pragma target 3.0
    72.             ENDHLSL
    73.         }
    74.  
    75.         // 3: First level downsampler with anti-flicker
    76.         Pass
    77.         {
    78.             ZTest Always Cull Off ZWrite Off
    79.          
    80.             HLSLPROGRAM
    81.                 #define ANTI_FLICKER 1
    82.                 #include "SHDINC-shd_screenSpaceMultiScatter-default.cginc"
    83.                 #pragma vertex VertDefault
    84.                 #pragma fragment frag_downsample1
    85.                 #pragma target 3.0
    86.             ENDHLSL
    87.         }
    88.  
    89.         // 4: Second level downsampler
    90.         Pass
    91.         {
    92.             ZTest Always Cull Off ZWrite Off
    93.  
    94.             HLSLPROGRAM
    95.                 #include "SHDINC-shd_screenSpaceMultiScatter-default.cginc"
    96.                 #pragma vertex VertDefault
    97.                 #pragma fragment frag_downsample2
    98.                 #pragma target 3.0
    99.             ENDHLSL
    100.         }
    101.  
    102.         // 5: Upsampler
    103.         Pass
    104.         {
    105.             ZTest Always Cull Off ZWrite Off
    106.  
    107.             HLSLPROGRAM
    108.                 #include "SHDINC-shd_screenSpaceMultiScatter-default.cginc"
    109.                 //#pragma vertex vert_multitex
    110.                 #pragma vertex VertDefault
    111.                 #pragma fragment frag_upsample
    112.                 #pragma target 3.0
    113.             ENDHLSL
    114.         }
    115.  
    116.         // 6: High quality upsampler
    117.         Pass
    118.         {
    119.             ZTest Always Cull Off ZWrite Off
    120.  
    121.             HLSLPROGRAM
    122.                 #define HIGH_QUALITY 1
    123.                 #include "SHDINC-shd_screenSpaceMultiScatter-default.cginc"
    124.                 //#pragma vertex vert_multitex
    125.                 #pragma vertex VertDefault
    126.                 #pragma fragment frag_upsample
    127.                 #pragma target 3.0
    128.             ENDHLSL
    129.         }
    130.  
    131.         // 7: Combiner
    132.         Pass
    133.         {
    134.             ZTest Always Cull Off ZWrite Off
    135.  
    136.             HLSLPROGRAM
    137.                 #pragma multi_compile _ UNITY_COLORSPACE_GAMMA
    138.                 #include "SHDINC-shd_screenSpaceMultiScatter-default.cginc"
    139.                 //#pragma vertex vert_multitex
    140.                 #pragma vertex VertDefault
    141.                 #pragma fragment frag_upsample_final
    142.                 #pragma target 3.0
    143.             ENDHLSL
    144.         }
    145.  
    146.         // 8: High quality combiner
    147.         Pass
    148.         {
    149.             ZTest Always Cull Off ZWrite Off
    150.  
    151.             HLSLPROGRAM
    152.                 #define HIGH_QUALITY 1
    153.                 #pragma multi_compile _ UNITY_COLORSPACE_GAMMA
    154.                 #include "SHDINC-shd_screenSpaceMultiScatter-default.cginc"
    155.                 //#pragma vertex vert_multitex
    156.                 #pragma vertex VertDefault
    157.                 #pragma fragment frag_upsample_final
    158.                 #pragma target 3.0
    159.             ENDHLSL
    160.         }
    161.     }
    162. }
    The CG include for the SMSS shader:

    Code (CSharp):
    1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    2.  
    3. // Screen Space Multiple Scattering for Unity
    4. //
    5. // Copyright (C) 2015, 2016 Keijiro Takahashi, OCASM
    6. //
    7. // Permission is hereby granted, free of charge, to any person obtaining a copy
    8. // of this software and associated documentation files (the "Software"), to deal
    9. // in the Software without restriction, including without limitation the rights
    10. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11. // copies of the Software, and to permit persons to whom the Software is
    12. // furnished to do so, subject to the following conditions:
    13. //
    14. // The above copyright notice and this permission notice shall be included in
    15. // all copies or substantial portions of the Software.
    16. //
    17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23. // THE SOFTWARE.
    24. //
    25.  
    26. #include "UnityCG.cginc"
    27.  
    28. // Mobile: use RGBM instead of float/half RGB
    29. #define USE_RGBM defined(SHADER_API_MOBILE)
    30.  
    31. sampler2D _MainTex;
    32. sampler2D _BaseTex;
    33. float2 _MainTex_TexelSize;
    34. float2 _BaseTex_TexelSize;
    35. half4 _MainTex_ST;
    36. half4 _BaseTex_ST;
    37.  
    38. float _PrefilterOffs;
    39. half _Threshold;
    40. half3 _Curve;
    41. float _SampleScale;
    42. half _Intensity;
    43.  
    44. // SMSS
    45. sampler2D _CameraDepthTexture;
    46. sampler2D _FadeTex;
    47. sampler2D _FogTex;
    48. float _Radius;
    49. half4 _BlurTint;
    50. half _BlurWeight;
    51.  
    52. // Brightness function
    53. half Brightness(half3 c)
    54. {
    55.     return max(max(c.r, c.g), c.b);
    56. }
    57.  
    58. // 3-tap median filter
    59. half3 Median(half3 a, half3 b, half3 c)
    60. {
    61.     return a + b + c - min(min(a, b), c) - max(max(a, b), c);
    62. }
    63.  
    64. // Clamp HDR value within a safe range
    65. half3 SafeHDR(half3 c) { return min(c, 65000); }
    66. half4 SafeHDR(half4 c) { return min(c, 65000); }
    67.  
    68. // RGBM encoding/decoding
    69. half4 EncodeHDR(float3 rgb)
    70. {
    71. #if USE_RGBM
    72.     rgb *= 1.0 / 8;
    73.     float m = max(max(rgb.r, rgb.g), max(rgb.b, 1e-6));
    74.     m = ceil(m * 255) / 255;
    75.     return half4(rgb / m, m);
    76. #else
    77.     return half4(rgb, 0);
    78. #endif
    79. }
    80.  
    81. float3 DecodeHDR(half4 rgba)
    82. {
    83. #if USE_RGBM
    84.     return rgba.rgb * rgba.a * 8;
    85. #else
    86.     return rgba.rgb;
    87. #endif
    88. }
    89.  
    90. // Downsample with a 4x4 box filter
    91. half3 DownsampleFilter(float2 uv)
    92. {
    93.     float4 d = _MainTex_TexelSize.xyxy * float4(-1, -1, +1, +1);
    94.  
    95.     half3 s;
    96.     s = DecodeHDR(tex2D(_MainTex, uv + d.xy));
    97.     s += DecodeHDR(tex2D(_MainTex, uv + d.zy));
    98.     s += DecodeHDR(tex2D(_MainTex, uv + d.xw));
    99.     s += DecodeHDR(tex2D(_MainTex, uv + d.zw));
    100.  
    101.     return s * (1.0 / 4);
    102. }
    103.  
    104. // Downsample with a 4x4 box filter + anti-flicker filter
    105. half3 DownsampleAntiFlickerFilter(float2 uv)
    106. {
    107.     float4 d = _MainTex_TexelSize.xyxy * float4(-1, -1, +1, +1);
    108.  
    109.     half3 s1 = DecodeHDR(tex2D(_MainTex, uv + d.xy));
    110.     half3 s2 = DecodeHDR(tex2D(_MainTex, uv + d.zy));
    111.     half3 s3 = DecodeHDR(tex2D(_MainTex, uv + d.xw));
    112.     half3 s4 = DecodeHDR(tex2D(_MainTex, uv + d.zw));
    113.  
    114.     // Karis's luma weighted average (using brightness instead of luma)
    115.     half s1w = 1 / (Brightness(s1) + 1);
    116.     half s2w = 1 / (Brightness(s2) + 1);
    117.     half s3w = 1 / (Brightness(s3) + 1);
    118.     half s4w = 1 / (Brightness(s4) + 1);
    119.     half one_div_wsum = 1 / (s1w + s2w + s3w + s4w);
    120.  
    121.     return (s1 * s1w + s2 * s2w + s3 * s3w + s4 * s4w) * one_div_wsum;
    122. }
    123.  
    124. half3 UpsampleFilter(float2 uv)
    125. {
    126. #if HIGH_QUALITY
    127.     // 9-tap bilinear upsampler (tent filter)
    128.     float4 d = _MainTex_TexelSize.xyxy * float4(1, 1, -1, 0) * _SampleScale;
    129.  
    130.     half3 s;
    131.     s = DecodeHDR(tex2D(_MainTex, uv - d.xy));
    132.     s += DecodeHDR(tex2D(_MainTex, uv - d.wy)) * 2;
    133.     s += DecodeHDR(tex2D(_MainTex, uv - d.zy));
    134.  
    135.     s += DecodeHDR(tex2D(_MainTex, uv + d.zw)) * 2;
    136.     s += DecodeHDR(tex2D(_MainTex, uv)) * 4;
    137.     s += DecodeHDR(tex2D(_MainTex, uv + d.xw)) * 2;
    138.  
    139.     s += DecodeHDR(tex2D(_MainTex, uv + d.zy));
    140.     s += DecodeHDR(tex2D(_MainTex, uv + d.wy)) * 2;
    141.     s += DecodeHDR(tex2D(_MainTex, uv + d.xy));
    142.  
    143.     return s * (1.0 / 16);
    144. #else
    145.     // 4-tap bilinear upsampler
    146.     float4 d = _MainTex_TexelSize.xyxy * float4(-1, -1, +1, +1) * (_SampleScale * 0.5);
    147.  
    148.     half3 s;
    149.     s = DecodeHDR(tex2D(_MainTex, uv + d.xy));
    150.     s += DecodeHDR(tex2D(_MainTex, uv + d.zy));
    151.     s += DecodeHDR(tex2D(_MainTex, uv + d.xw));
    152.     s += DecodeHDR(tex2D(_MainTex, uv + d.zw));
    153.  
    154.     return s * (1.0 / 4);
    155. #endif
    156. }
    157.  
    158. // Vertex manipulation
    159. float2 TransformTriangleVertexToUV(float2 vertex)
    160. {
    161.     float2 uv = (vertex + 1.0) * 0.5;
    162.     return uv;
    163. }
    164. //
    165. // Vertex shader
    166. //
    167.  
    168. v2f_img vert(appdata_img v)
    169. {
    170.     v2f_img o;
    171.     #if UNITY_VERSION >= 540
    172.         o.pos = UnityObjectToClipPos(v.vertex);
    173.         o.uv = UnityStereoScreenSpaceUVAdjust(v.texcoord, _MainTex_ST);
    174.     #else
    175.         o.pos = UnityObjectToClipPos(v.vertex);
    176.         o.uv = v.texcoord;
    177.     #endif
    178.     return o;
    179. }
    180.  
    181. struct v2f_multitex
    182. {
    183.     float4 pos : SV_POSITION;
    184.     float2 uvMain : TEXCOORD0;
    185.     float2 uvBase : TEXCOORD1;
    186. };
    187.  
    188. v2f_multitex vert_multitex(appdata_img v)
    189. {
    190.     v2f_multitex o;
    191.  
    192.     o.pos = UnityObjectToClipPos(v.vertex);
    193.     o.uvMain = v.texcoord;
    194.     o.uvBase = v.texcoord;
    195.  
    196.     #if UNITY_UV_STARTS_AT_TOP
    197.         if (_BaseTex_TexelSize.y < 0.0)
    198.             o.uvBase.y = 1.0 - v.texcoord.y;
    199.     #endif
    200.     return o;
    201. }
    202.  
    203. struct AttributesDefault
    204. {
    205.     float3 vertex : POSITION;
    206.     half2 texcoord : TEXCOORD0;
    207. };
    208.  
    209. struct VaryingsDefault
    210. {
    211.     float4 pos : SV_POSITION;
    212.     float2 uvMain : TEXCOORD0;
    213.     float2 uvBase : TEXCOORD1;
    214. };
    215.  
    216. VaryingsDefault VertDefault(AttributesDefault v)
    217. {
    218.     VaryingsDefault o;
    219.     v.vertex.z = 0.1;
    220.     o.pos = float4(v.vertex.xy, 0.0, 1.0);
    221.     o.uvMain = TransformTriangleVertexToUV(v.vertex.xy);
    222.     o.uvBase = v.texcoord.xy;
    223.  
    224.     #if UNITY_UV_STARTS_AT_TOP
    225.         o.uv = o.uv * float2(1.0, -1.0) + float2(0.0, 1.0);
    226.     #endif
    227.  
    228.     #if UNITY_UV_STARTS_AT_TOP
    229.         if (_MainTex_TexelSize.y < 0)
    230.             o.uv.y = 1 - o.uv.y;
    231.     #endif
    232.  
    233.     return o;
    234. }
    235.  
    236. //
    237. // fragment shader
    238. //
    239.  
    240. // SMSS
    241. half AdjustDepth(half d) {
    242.     d = tex2D(_FadeTex, half2(d, 0.5));
    243.     return saturate(d);
    244. }
    245.  
    246. half4 frag_prefilter(VaryingsDefault i) : SV_Target
    247. {
    248.     float2 uv = i.uvMain + _MainTex_TexelSize.xy * _PrefilterOffs;
    249.  
    250.     #if ANTI_FLICKER
    251.         float3 d = _MainTex_TexelSize.xyx * float3(1, 1, 0);
    252.         half4 s0 = SafeHDR(tex2D(_MainTex, uv));
    253.         half3 s1 = SafeHDR(tex2D(_MainTex, uv - d.xz).rgb);
    254.         half3 s2 = SafeHDR(tex2D(_MainTex, uv + d.xz).rgb);
    255.         half3 s3 = SafeHDR(tex2D(_MainTex, uv - d.zy).rgb);
    256.         half3 s4 = SafeHDR(tex2D(_MainTex, uv + d.zy).rgb);
    257.         half3 m = Median(Median(s0.rgb, s1, s2), s3, s4);
    258.     #else
    259.         half4 s0 = SafeHDR(tex2D(_MainTex, uv));
    260.         half3 m = s0.rgb;
    261.     #endif
    262.  
    263.     #if UNITY_COLORSPACE_GAMMA
    264.         m = GammaToLinearSpace(m);
    265.     #endif
    266.     // Pixel brightness
    267.     half br = Brightness(m);
    268.  
    269.     // Under-threshold part: quadratic curve
    270.     half rq = clamp(br - _Curve.x, 0, _Curve.y);
    271.     rq = _Curve.z * rq * rq;
    272.  
    273.     // Combine and apply the brightness response curve.
    274.     m *= max(rq, br - _Threshold) / max(br, 1e-5);
    275.  
    276.     // SMSS
    277.     //half depth = tex2D(_FogTex, i.uv); // Deferred
    278.     half depth = tex2D(_FogTex, float2(i.uv.x, 1 - i.uv.y)); // Forward
    279.     depth = AdjustDepth(depth);
    280.  
    281.     return EncodeHDR(m * depth) * _BlurTint;
    282. }
    283.  
    284. half4 frag_downsample1(VaryingsDefault i) : SV_Target
    285. {
    286.     #if ANTI_FLICKER
    287.         return EncodeHDR(DownsampleAntiFlickerFilter(i.uvMain));
    288.     #else
    289.         return EncodeHDR(DownsampleFilter(i.uvMain));
    290.     #endif
    291. }
    292.  
    293. half4 frag_downsample2(VaryingsDefault i) : SV_Target
    294. {
    295.     return EncodeHDR(DownsampleFilter(i.uvMain));
    296. }
    297.  
    298. half4 frag_upsample(VaryingsDefault i) : SV_Target
    299. {
    300.     half3 base = DecodeHDR(tex2D(_BaseTex, i.uvBase));
    301.     half3 blur = UpsampleFilter(i.uvMain);
    302.  
    303.     return EncodeHDR(base + blur * (1 + _BlurWeight)) / (1 + (_BlurWeight * 0.735));
    304. }
    305.  
    306. half4 frag_upsample_final(VaryingsDefault i) : SV_Target
    307. {
    308.     half4 base = tex2D(_BaseTex, i.uvBase);
    309.     half3 blur = UpsampleFilter(i.uvMain);
    310.  
    311.     #if UNITY_COLORSPACE_GAMMA
    312.         base.rgb = GammaToLinearSpace(base.rgb);
    313.     #endif
    314.  
    315.     // SMSS
    316.     //half depth = tex2D(_FogTex, i.uvBase); // Deferred
    317.     //half depth = tex2D(_FogTex, i.uvBase); // Deferred
    318.     half depth = tex2D(_FogTex, float2(i.uvBase.x, 1 - i.uvMain.y)); // Forward
    319.     depth = AdjustDepth(depth);
    320.  
    321.     return lerp(base, half4(blur,1) * (1 / _Radius), clamp(depth ,0,_Intensity));
    322. }
    The Post Process C# and stack rollout for the SMSS effect:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Rendering.PostProcessing;
    4.  
    5. namespace UnityEngine.Rendering.PostProcessing
    6. {
    7.     [Serializable]
    8.     [PostProcess(typeof(ScreenSpaceMultiScatterRenderer), PostProcessEvent.AfterStack, "ScreenSpaceMultiScatter")]
    9.     public sealed class ScreenSpaceMultiScatter : PostProcessEffectSettings
    10.     {
    11.         public static float LinearToGamma(float x)
    12.         {
    13.             #if UNITY_5_3_OR_NEWER
    14.                 return Mathf.LinearToGammaSpace(x);
    15.             #else
    16.                 if (x <= 0.0031308f)
    17.                     return 12.92f * x;
    18.                 else
    19.                     return 1.055f * Mathf.Pow(x, 1 / 2.4f) - 0.055f;
    20.             #endif
    21.         }
    22.  
    23.         public static float GammaToLinear(float x)
    24.         {
    25.             #if UNITY_5_3_OR_NEWER
    26.                     return Mathf.GammaToLinearSpace(x);
    27.             #else
    28.                 if (x <= 0.04045f)
    29.                     return x / 12.92f;
    30.                 else
    31.                     return Mathf.Pow((x + 0.055f) / 1.055f, 2.4f);
    32.             #endif
    33.         }
    34.  
    35.         /// Prefilter threshold (gamma-encoded)
    36.         /// Filters out pixels under this level of brightness.
    37.         public static float thresholdGamma
    38.         {
    39.             get { return Mathf.Max(_threshold, 0); }
    40.             set { _threshold = value; }
    41.         }
    42.  
    43.         /// Prefilter threshold (linearly-encoded)
    44.         /// Filters out pixels under this level of brightness.
    45.         public static float _threshold = 0f;
    46.         public static float thresholdLinear
    47.         {
    48.             get { return GammaToLinear(thresholdGamma); }
    49.             set { _threshold = LinearToGamma(value); }
    50.         }
    51.  
    52.         [SerializeField]
    53.         [Tooltip("Filters out pixels under this level of brightness.")]
    54.         public FloatParameter ThresholdLinear = new FloatParameter { value = thresholdLinear };
    55.  
    56.  
    57.         /// Soft-knee coefficient
    58.         /// Makes transition between under/over-threshold gradual.
    59.         public static float _softKnee = 0.5f;
    60.         public static float softKnee
    61.         {
    62.             get { return _softKnee; }
    63.             set { _softKnee = value; }
    64.         }
    65.  
    66.         [SerializeField, Range(0, 1)]
    67.         [Tooltip("Makes transition between under/over-threshold gradual.")]
    68.         public FloatParameter SoftKnee = new FloatParameter { value = softKnee };
    69.  
    70.         /// Bloom radius
    71.         /// Changes extent of veiling effects in a screen
    72.         /// resolution-independent fashion.
    73.         public static float _radius = 7f;
    74.         public static float radius
    75.         {
    76.             get { return _radius; }
    77.             set { _radius = value; }
    78.         }
    79.         public FloatParameter Radius = new FloatParameter { value = radius };
    80.  
    81.         [Header("Scattering")]
    82.         [SerializeField, Range(1, 7)]
    83.         [Tooltip("Changes extent of veiling effects\n" +
    84.                  "in a screen resolution-independent fashion.")]
    85.  
    86.         /// Blur Weight
    87.         /// Gives more strength to the blur texture during the combiner loop.
    88.         public static float _blurWeight = 1f;
    89.         public static float blurWeight
    90.         {
    91.             get { return _blurWeight; }
    92.             set { _blurWeight = value; }
    93.         }
    94.  
    95.         [SerializeField, Range(0.1f, 100)]
    96.         [Tooltip("Higher number creates a softer look but artifacts are more pronounced.")] // TODO Better description.
    97.         public FloatParameter BlurWeight = new FloatParameter { value = blurWeight };
    98.  
    99.         /// Bloom intensity
    100.         /// Blend factor of the result image.
    101.         public static float _intensity = 1f;
    102.         public static float intensity
    103.         {
    104.             get { return Mathf.Max(_intensity, 0); }
    105.             set { _intensity = value; }
    106.         }
    107.  
    108.         [SerializeField]
    109.         [Tooltip("Blend factor of the result image.")]
    110.         [Range(0, 1)]
    111.         public FloatParameter Intensity = new FloatParameter { value = intensity };
    112.  
    113.         /// High quality mode
    114.         /// Controls filter quality and buffer resolution.
    115.         public static bool _highQuality = true;
    116.         public static bool highQuality
    117.         {
    118.             get { return _highQuality; }
    119.             set { _highQuality = value; }
    120.         }
    121.  
    122.         [Tooltip("Controls filter quality and buffer resolution.")]
    123.         public BoolParameter HighQuality = new BoolParameter { value = highQuality };
    124.         /// Anti-flicker filter
    125.         /// Reduces flashing noise with an additional filter.
    126.         public static bool _antiFlicker = true;
    127.         public static bool antiFlicker
    128.         {
    129.             get { return _antiFlicker; }
    130.             set { _antiFlicker = value; }
    131.         }
    132.  
    133.         [SerializeField]
    134.         [Tooltip("Reduces flashing noise with an additional filter.")]
    135.         public BoolParameter AntiFlicker = new BoolParameter { value = antiFlicker };
    136.  
    137.         /// Distribution texture
    138.         public static Texture2D _fadeRamp;
    139.         public static Texture2D fadeRamp
    140.         {
    141.             get { return _fadeRamp; }
    142.             set { _fadeRamp = value; }
    143.         }
    144.  
    145.         [Tooltip("1D gradient. Determines how the effect fades across distance.")]
    146.         public TextureParameter FadeRamp = new TextureParameter { value = fadeRamp };
    147.  
    148.         /// Blur tint
    149.         public static Color _blurTint = Color.white;
    150.         public static Color blurTint
    151.         {
    152.             get { return _blurTint; }
    153.             set { _blurTint = value; }
    154.         }
    155.         [SerializeField]
    156.         [Tooltip("Tints the resulting blur. ")]
    157.         public ColorParameter BlurTint = new ColorParameter { value = blurTint };
    158.  
    159.      
    160.     }
    161.  
    162.     [ExecuteInEditMode]
    163.     public sealed class ScreenSpaceMultiScatterRenderer : PostProcessEffectRenderer<ScreenSpaceMultiScatter>
    164.     {
    165.  
    166.         public override void Render(PostProcessRenderContext context)
    167.         {
    168.  
    169.             Camera cam = context.camera;
    170.             const int kMaxIterations = 16;
    171.             RenderTexture[] _blurBuffer1 = new RenderTexture[kMaxIterations];
    172.             RenderTexture[] _blurBuffer2 = new RenderTexture[kMaxIterations];
    173.             //RenderTexture Source;
    174.  
    175.             RenderTexture Source = new RenderTexture(context.width, context.height, 16, RenderTextureFormat.Default);
    176.  
    177.             if (settings.FadeRamp == null)
    178.             {
    179.                 ScreenSpaceMultiScatter._fadeRamp = Resources.Load("Assets/__Content__/Shaders/ScreenSpaceMultiScatter/Textures/nonLinear2", typeof(Texture2D)) as Texture2D;
    180.             };
    181.  
    182.          
    183.             var sheet = context.propertySheets.Get( Shader.Find( "ScreenSpaceMultiScatter" ) );
    184.  
    185.             var useRGBM = Application.isMobilePlatform;
    186.  
    187.             // source texture size
    188.             var tw = context.width;
    189.             var th = context.height;
    190.  
    191.             // halve the texture size for the low quality mode
    192.             if (!settings.HighQuality)
    193.             {
    194.                 tw /= 2;
    195.                 th /= 2;
    196.             }
    197.  
    198.             // blur buffer format
    199.             var rtFormat = useRGBM ?
    200.                 RenderTextureFormat.Default : RenderTextureFormat.DefaultHDR;
    201.  
    202.             // determine the iteration count
    203.             var logh = Mathf.Log(th, 2) + settings.Radius - 8;
    204.             var logh_i = (int)logh;
    205.             var iterations = Mathf.Clamp(logh_i, 1, kMaxIterations);
    206.  
    207.             // update the shader properties
    208.             var lthresh = settings.ThresholdLinear;
    209.             sheet.properties.SetFloat("_Threshold", lthresh);
    210.  
    211.             var knee = lthresh * settings.SoftKnee + 1e-5f;
    212.             var curve = new Vector3(lthresh - knee, knee * 2, 0.25f / knee);
    213.             sheet.properties.SetVector("_Curve", curve);
    214.  
    215.             var pfo = !settings.HighQuality && settings.AntiFlicker;
    216.             sheet.properties.SetFloat("_PrefilterOffs", pfo ? -0.5f : 0.0f);
    217.  
    218.             sheet.properties.SetFloat("_SampleScale", 0.5f + logh - logh_i);
    219.             sheet.properties.SetFloat("_Intensity", settings.Intensity);
    220.  
    221.             sheet.properties.SetTexture("_FadeTex", settings.FadeRamp);
    222.             sheet.properties.SetFloat("_BlurWeight", settings.BlurWeight);
    223.             sheet.properties.SetFloat("_Radius", settings.Radius);
    224.             sheet.properties.SetColor("_BlurTint", settings.BlurTint);
    225.  
    226.             // prefilter pass
    227.             var prefiltered = RenderTexture.GetTemporary(tw, th, 0, rtFormat);
    228.             var pass = settings.AntiFlicker ? 1 : 0;
    229.             //Graphics.Blit(source, prefiltered, _material, pass);
    230.             context.command.BlitFullscreenTriangle(context.source, prefiltered, sheet, pass);
    231.  
    232.             // construct a mip pyramid
    233.             var last = prefiltered;
    234.             for (var level = 0; level < iterations; level++)
    235.             {
    236.                 _blurBuffer1[level] = RenderTexture.GetTemporary( last.width / 2, last.height / 2, 0, rtFormat );
    237.  
    238.                 pass = (level == 0) ? (settings.AntiFlicker ? 3 : 2) : 4;
    239.                 //Graphics.Blit(last, _blurBuffer1[level], _material, pass);
    240.                 context.command.BlitFullscreenTriangle(context.source, _blurBuffer1[level], sheet, pass);
    241.  
    242.                 last = _blurBuffer1[level];
    243.             }
    244.  
    245.             // upsample and combine loop
    246.             for (var level = iterations - 2; level >= 0; level--)
    247.             {
    248.                 var basetex = _blurBuffer1[level];
    249.                 sheet.properties.SetTexture("_BaseTex", basetex);
    250.  
    251.                 _blurBuffer2[level] = RenderTexture.GetTemporary(
    252.                     basetex.width, basetex.height, 0, rtFormat
    253.                 );
    254.  
    255.                 pass = settings.HighQuality ? 6 : 5;
    256.                 //Graphics.Blit(last, _blurBuffer2[level], _material, pass);
    257.                 context.command.BlitFullscreenTriangle(context.source, _blurBuffer2[level], sheet, pass);
    258.  
    259.                 last = _blurBuffer2[level];
    260.             }
    261.  
    262.             // finish process
    263.             //sheet.properties.SetTexture( "_BaseTex", context.source );
    264.             //sheet.properties.SetTexture("_BaseTex", Source);
    265.  
    266.             pass = settings.HighQuality ? 8 : 7;
    267.             //Graphics.Blit(last, destination, _material, pass);
    268.             context.command.BlitFullscreenTriangle(last, context.destination, sheet, pass);
    269.  
    270.             // release the temporary buffers
    271.             for (var i = 0; i < kMaxIterations; i++)
    272.             {
    273.                 if (_blurBuffer1[i] != null)
    274.                     RenderTexture.ReleaseTemporary(_blurBuffer1[i]);
    275.  
    276.                 if (_blurBuffer2[i] != null)
    277.                     RenderTexture.ReleaseTemporary(_blurBuffer2[i]);
    278.  
    279.                 _blurBuffer1[i] = null;
    280.                 _blurBuffer2[i] = null;
    281.             }
    282.  
    283.             RenderTexture.ReleaseTemporary(prefiltered);
    284.         }
    285.     }
    286. }
    287.  
    288.  
    289.  
     
    Alverik, eDmitriy, transat and 13 others like this.
  16. matteumayo

    matteumayo

    Joined:
    Jul 25, 2016
    Posts:
    166
    @karmakat Awesome! I wish I could help, but I haven't delved into shaders much - hopefully someone else following this thread can take a look at it. Best of luck!
     
    Quast likes this.
  17. id0

    id0

    Joined:
    Nov 23, 2012
    Posts:
    199
    @karmakat that's great somebody do something with this fog. I'm using this fog all the time, but unfortunately I'm also not a shader guy.
     
    Last edited: Dec 9, 2017
  18. OCASM

    OCASM

    Joined:
    Jan 12, 2011
    Posts:
    211
    You know, I think it would be easier to take the bloom from the PPS and mod it into SSMS than port SSMS into the PPS framework since that effect is actually the latest version of the one I used as a base and really the changes I made to it are fairly superficial: passing an extra texture, funging a few numbers and change the blending at the end.

    EDIT: well except that bloom is now an intermediary effect in the whole chain so probably you'd have to create the RTs and an extra pass at the end to do the blending. Not too complicated but something to keep in mind.
     
    Last edited: Dec 10, 2017
    ledbetterman likes this.
  19. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    441
    C'mon man, update that fog. Or give us something new.
     
  20. OCASM

    OCASM

    Joined:
    Jan 12, 2011
    Posts:
    211
    It's open source, an opportunity to get your hands dirty xD.
     
  21. karmakat

    karmakat

    Joined:
    Jul 25, 2013
    Posts:
    2
    Thanks OCASM for the tips! I will look into taking the Bloom in the PPS and modifying it as you suggest.

    Any body have any idea why the vertical fog in my shader is horizontal?
     
  22. OCASM

    OCASM

    Joined:
    Jan 12, 2011
    Posts:
    211
    You should ask in the Shaders sub-forum. Maybe someome there can help.
     
    konsic likes this.
  23. hsxtreme

    hsxtreme

    Joined:
    Apr 14, 2017
    Posts:
    55
  24. akareactor

    akareactor

    Joined:
    Apr 6, 2015
    Posts:
    57
    SSMS is exactly what I was looking for the Titan atmosphere. Awesome!

    SMSS test 2018-01-09_14-44-59.jpg
     
    Last edited: Jan 9, 2018
  25. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    441
    Yes, you right. And think if the maker update it now. How will be ?
     
  26. akareactor

    akareactor

    Joined:
    Apr 6, 2015
    Posts:
    57
    Slam dunk, will be more awesomeness!
    .
     
  27. TerriblyCharismaticDuck

    TerriblyCharismaticDuck

    Joined:
    Feb 7, 2018
    Posts:
    1
    Unfortunately I seem to be having a memory leak problem with this, after working with it for a few minutes the memory usage suddenly begins to increase rapidly until is crashes my computer. Is this a known issue and is there a known workaround or fix? Using 2017.2.1f1.
     
  28. id0

    id0

    Joined:
    Nov 23, 2012
    Posts:
    199
    You can just turn off effect in the scene view, comment the line in scripts [ImageEffectAllowedInSceneView] In game everything is ok.
     
    Editali and OCASM like this.
  29. piegaro

    piegaro

    Joined:
    May 17, 2017
    Posts:
    7
    Thank you very very much OCASM, this looks absolutely gorgeous on our game!

    Unfortunately, the SSMS script is fine in the Editor, but does not work on latest iOS (Metal / tested on Unity 2017.3.1f1).

    Xcode 9.2 give this following message:

    WARNING: Shader Unsupported: 'Hidden/SSMS' - Pass '' has no vertex shader
    ERROR: Shader Shader is not supported on this GPU (none of subshaders/fallbacks are suitable)WARNING: Shader Unsupported: 'Hidden/SSMS' - Setting to default shader.

    Invalid pass number (1) for Graphics.Blit (Material "Hidden/SSMS" with 1 passes)
    UnityEngine.Graphics:INTERNAL_CALL_Internal_BlitMaterial(Texture, RenderTexture, Material, Int32, Boolean, Vector2&, Vector2&)
    UnityEngine.Graphics:Internal_BlitMaterial(Texture, RenderTexture, Material, Int32, Boolean, Vector2, Vector2)
    UnityEngine.Graphics:Blit(Texture, RenderTexture, Material, Int32)
    SSMS.SSMS:OnRenderImage(RenderTexture, RenderTexture)

    [/Users/builduser/buildslave/unity/build/Runtime/Camera/ImageFilters.cpp line 767]
    (Filename: /Users/builduser/buildslave/unity/build/Runtime/Camera/ImageFilters.cpp Line: 767)

    Invalid pass number (3) for Graphics.Blit (Material "Hidden/SSMS" with 1 passes)
    UnityEngine.Graphics:INTERNAL_CALL_Internal_BlitMaterial(Texture, RenderTexture, Material, Int32, Boolean, Vector2&, Vector2&)
    UnityEngine.Graphics:Internal_BlitMaterial(Texture, RenderTexture, Material, Int32, Boolean, Vector2, Vector2)
    UnityEngine.Graphics:Blit(Texture, RenderTexture, Material, Int32)
    SSMS.SSMS:OnRenderImage(RenderTexture, RenderTexture)

    [/Users/builduser/buildslave/unity/build/Runtime/Camera/ImageFilters.cpp line 767]
    (Filename: /Users/builduser/buildslave/unity/build/Runtime/Camera/ImageFilters.cpp Line: 767)

    Invalid pass number (4) for Graphics.Blit (Material "Hidden/SSMS" with 1 passes)
    UnityEngine.Graphics:INTERNAL_CALL_Internal_BlitMaterial(Texture, RenderTexture, Material, Int32, Boolean, Vector2&, Vector2&)
    UnityEngine.Graphics:Internal_BlitMaterial(Texture, RenderTexture, Material, Int32, Boolean, Vector2, Vector2)
    UnityEngine.Graphics:Blit(Texture, RenderTexture, Material, Int32)
    SSMS.SSMS:OnRenderImage(RenderTexture, RenderTexture)


    Anyway you guys could help fix this?
     
    Last edited: Mar 13, 2018
  30. OCASM

    OCASM

    Joined:
    Jan 12, 2011
    Posts:
    211
    To be honest, I don't have any experience with iOS/Metal. I recommend you ask in the Shaders sub-forum. Probably somebody there can help.
     
  31. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    939
    This is absolutely great, thanks a lot!

    I will try it in my game with the Enviro asset :)
     
    OCASM likes this.
  32. TheWanderingBen

    TheWanderingBen

    Joined:
    Nov 3, 2015
    Posts:
    50
    Hey karmakat, did you ever get SSMS working with the new Post Processing stack? I was going to try to port it this weekend, but if you already have it working, I'd love to save some time! Otherwise I'll post my progress back here!
     
    transat, christoph_r, Alverik and 5 others like this.
  33. ken1nil

    ken1nil

    Joined:
    Sep 16, 2018
    Posts:
    1
    Any update on your progress? Would love to see this work with the new Processing Stack and Unity 2018
     
  34. Pourya-MDP

    Pourya-MDP

    Joined:
    May 18, 2017
    Posts:
    33
    HI there every one
    I wolud love to know how to make unity default lights working along with ssms
    I need to have some spot light shafts as a flash light simillar to inside's jungle scene
    Any help will be appreciated
     
  35. Adam-Bailey

    Adam-Bailey

    Joined:
    Feb 17, 2015
    Posts:
    200
    If you're after volumetric lighting for spotlights you could either fake it using a particle effect or use a package like Aura.

    https://assetstore.unity.com/packages/vfx/shaders/aura-volumetric-lighting-111664
     
    OCASM and chingwa like this.
  36. Pourya-MDP

    Pourya-MDP

    Joined:
    May 18, 2017
    Posts:
    33
    Hi there i tried to add volu