UnderWaterFog.shader 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. Shader "Hidden/UnderWaterFog" {
  2. Properties {
  3. _MainTex ("Base (RGB)", 2D) = "black" {}
  4. }
  5. CGINCLUDE
  6. #include "UnityCG.cginc"
  7. uniform sampler2D _MainTex;
  8. UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
  9. // x = fog height
  10. // y = FdotC (CameraY-FogHeight)
  11. // z = k (FdotC > 0.0)
  12. // w = a/2
  13. uniform float4 _HeightParams;
  14. // x = start distance
  15. uniform float4 _DistanceParams;
  16. int4 _SceneFogMode; // x = fog mode, y = use radial flag
  17. float4 _SceneFogParams;
  18. #ifndef UNITY_APPLY_FOG
  19. half4 unity_FogColor;
  20. half4 unity_FogDensity;
  21. #endif
  22. uniform float4 _MainTex_TexelSize;
  23. uniform fixed4 _Color;
  24. // for fast world space reconstruction
  25. uniform float4x4 _FrustumCornersWS;
  26. uniform float4 _CameraWS;
  27. struct v2f {
  28. float4 pos : SV_POSITION;
  29. float2 uv : TEXCOORD0;
  30. float2 uv_depth : TEXCOORD1;
  31. float4 interpolatedRay : TEXCOORD2;
  32. };
  33. v2f vert (appdata_img v)
  34. {
  35. v2f o;
  36. half index = v.vertex.z;
  37. v.vertex.z = 0.1;
  38. o.pos = UnityObjectToClipPos(v.vertex);
  39. o.uv = v.texcoord.xy;
  40. o.uv_depth = v.texcoord.xy;
  41. #if UNITY_UV_STARTS_AT_TOP
  42. if (_MainTex_TexelSize.y < 0)
  43. o.uv.y = 1-o.uv.y;
  44. #endif
  45. o.interpolatedRay = _FrustumCornersWS[(int)index];
  46. o.interpolatedRay.w = index;
  47. return o;
  48. }
  49. // Applies one of standard fog formulas, given fog coordinate (i.e. distance)
  50. half ComputeFogFactor (float coord)
  51. {
  52. float fogFac = 0.0;
  53. fogFac = coord * _SceneFogParams.z + _SceneFogParams.w;
  54. return saturate(fogFac);
  55. }
  56. // Distance-based fog
  57. float ComputeDistance (float3 camDir, float zdepth)
  58. {
  59. float dist;
  60. if (_SceneFogMode.y == 1)
  61. dist = length(camDir);
  62. else
  63. dist = zdepth * _ProjectionParams.z;
  64. // Built-in fog starts at near plane, so match that by
  65. // subtracting the near value. Not a perfect approximation
  66. // if near plane is very large, but good enough.
  67. dist -= _ProjectionParams.y;
  68. return dist;
  69. }
  70. // Linear half-space fog, from https://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf
  71. float ComputeHalfSpace (float3 wsDir)
  72. {
  73. float3 wpos = _CameraWS + wsDir;
  74. float FH = _HeightParams.x;
  75. float3 C = _CameraWS;
  76. float3 V = wsDir;
  77. float3 P = wpos;
  78. float3 aV = _HeightParams.w * V;
  79. float FdotC = _HeightParams.y;
  80. float k = _HeightParams.z;
  81. float FdotP = P.y-FH;
  82. float FdotV = wsDir.y;
  83. float c1 = k * (FdotP + FdotC);
  84. float c2 = (1-2*k) * FdotP;
  85. float g = min(c2, 0.0);
  86. g = -length(aV) * (c1 - g * g / abs(FdotV+1.0e-5f));
  87. return g;
  88. }
  89. half4 ComputeFog (v2f i, bool distance, bool height) : SV_Target
  90. {
  91. half4 sceneColor = tex2D(_MainTex, i.uv);
  92. // Reconstruct world space position & direction
  93. // towards this screen pixel.
  94. float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);
  95. float dpth = Linear01Depth(rawDepth);
  96. float4 wsDir = dpth * i.interpolatedRay;
  97. float4 wsPos = _CameraWS + wsDir;
  98. half fogMask = ComputeHalfSpace (wsDir);
  99. half fogFac = ComputeFogFactor (max(0.0,fogMask + _DistanceParams.x));
  100. // Do not fog skybox
  101. if (rawDepth == _DistanceParams.y){
  102. fogMask = 0.0;
  103. }
  104. fixed4 fogColor = lerp(_Color,sceneColor * _Color,fogFac);
  105. return lerp(sceneColor,fogColor,saturate(fogMask * _Color.a));
  106. }
  107. ENDCG
  108. SubShader
  109. {
  110. ZTest Always Cull Off ZWrite Off Fog { Mode Off }
  111. // 0: distance + height
  112. Pass
  113. {
  114. CGPROGRAM
  115. #pragma vertex vert
  116. #pragma fragment frag
  117. #define DISTANCE
  118. #define HEIGHT
  119. half4 frag (v2f i) : SV_Target { return ComputeFog (i, true, true); }
  120. ENDCG
  121. }
  122. }
  123. Fallback off
  124. }