Shader "Hidden/Post FX/Fog" { Properties { _MainTex("Main Texture", 2D) = "white" {} } CGINCLUDE #pragma multi_compile __ FOG_LINEAR FOG_EXP FOG_EXP2 #include "UnityCG.cginc" #include "Common.cginc" // Start: LuxWater #pragma multi_compile __ LUXWATER_DEFERREDFOG #if defined(LUXWATER_DEFERREDFOG) sampler2D _UnderWaterMask; float4 _LuxUnderWaterDeferredFogParams; // x: IsInsideWatervolume?, y: BelowWaterSurface shift, z: EdgeBlend #endif // End: LuxWater #define SKYBOX_THREASHOLD_VALUE 0.9999 struct Varyings { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; Varyings VertFog(AttributesDefault v) { Varyings o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = UnityStereoScreenSpaceUVAdjust(v.texcoord, _MainTex_ST); return o; } sampler2D _CameraDepthTexture; half4 _FogColor; float _Density; float _Start; float _End; half ComputeFog(float z) { half fog = 0.0; #if FOG_LINEAR fog = (_End - z) / (_End - _Start); #elif FOG_EXP fog = exp2(-_Density * z); #else // FOG_EXP2 fog = _Density * z; fog = exp2(-fog * fog); #endif return saturate(fog); } float ComputeDistance(float depth) { float dist = depth * _ProjectionParams.z; dist -= _ProjectionParams.y; return dist; } half4 FragFog(Varyings i) : SV_Target { half4 color = tex2D(_MainTex, i.uv); float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv); depth = Linear01Depth(depth); float dist = ComputeDistance(depth); half fog = 1.0 - ComputeFog(dist); // Start: LuxWater #if defined(LUXWATER_DEFERREDFOG) half4 fogMask = tex2D(_UnderWaterMask, UnityStereoTransformScreenSpaceTex(i.texcoordStereo)); float watersurfacefrombelow = DecodeFloatRG(fogMask.ba); // Get distance and lower it a bit in order to handle edge blending artifacts (edge blended parts would not get ANY fog) float ldist = (watersurfacefrombelow - depth) + _LuxUnderWaterDeferredFogParams.y * _ProjectionParams.w; // Fade fog from above water to below water float fogFactor = saturate ( 1.0 + _ProjectionParams.z * _LuxUnderWaterDeferredFogParams.z * ldist ); // 0.125 // Clamp above result to where water is actually rendered fogFactor = (fogMask.r == 1) ? fogFactor : 1.0; // Mask fog on underwarter parts - only if we are inside a volume (bool... :( ) if(_LuxUnderWaterDeferredFogParams.x) { fogFactor *= saturate( 1.0 - fogMask.g * 8.0); if (ldist < -_ProjectionParams.w * 4 && fogMask.r == 0 && fogMask.g < 1.0) { fogFactor = 1.0; } } // Tweak fog factor fog *= fogFactor; #endif // End: LuxWater return lerp(color, _FogColor, fog); } half4 FragFogExcludeSkybox(Varyings i) : SV_Target { half4 color = tex2D(_MainTex, i.uv); float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv); depth = Linear01Depth(depth); float skybox = depth < SKYBOX_THREASHOLD_VALUE; float dist = ComputeDistance(depth); half fog = 1.0 - ComputeFog(dist); // Start: LuxWater #if defined(LUXWATER_DEFERREDFOG) half4 fogMask = tex2D(_UnderWaterMask, UnityStereoTransformScreenSpaceTex(i.texcoordStereo)); float watersurfacefrombelow = DecodeFloatRG(fogMask.ba); // Get distance and lower it a bit in order to handle edge blending artifacts (edge blended parts would not get ANY fog) float ldist = (watersurfacefrombelow - depth) + _LuxUnderWaterDeferredFogParams.y * _ProjectionParams.w; // Fade fog from above water to below water float fogFactor = saturate ( 1.0 + _ProjectionParams.z * _LuxUnderWaterDeferredFogParams.z * ldist ); // 0.125 // Clamp above result to where water is actually rendered fogFactor = (fogMask.r == 1) ? fogFactor : 1.0; // Mask fog on underwarter parts - only if we are inside a volume (bool... :( ) if(_LuxUnderWaterDeferredFogParams.x) { fogFactor *= saturate( 1.0 - fogMask.g * 8.0); if (ldist < -_ProjectionParams.w * 4 && fogMask.r == 0 && fogMask.g < 1.0) { fogFactor = 1.0; } } // Tweak fog factor fog *= fogFactor; #endif // End: LuxWater return lerp(color, _FogColor, fog * skybox); } ENDCG SubShader { Cull Off ZWrite Off ZTest Always Pass { CGPROGRAM #pragma vertex VertFog #pragma fragment FragFog ENDCG } Pass { CGPROGRAM #pragma vertex VertFog #pragma fragment FragFogExcludeSkybox ENDCG } } }