123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- Shader "Hidden/UnderWaterFog" {
- Properties {
- _MainTex ("Base (RGB)", 2D) = "black" {}
- }
- CGINCLUDE
- #include "UnityCG.cginc"
- uniform sampler2D _MainTex;
- UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
-
- // x = fog height
- // y = FdotC (CameraY-FogHeight)
- // z = k (FdotC > 0.0)
- // w = a/2
- uniform float4 _HeightParams;
-
- // x = start distance
- uniform float4 _DistanceParams;
-
- int4 _SceneFogMode; // x = fog mode, y = use radial flag
- float4 _SceneFogParams;
- #ifndef UNITY_APPLY_FOG
- half4 unity_FogColor;
- half4 unity_FogDensity;
- #endif
- uniform float4 _MainTex_TexelSize;
- uniform fixed4 _Color;
-
- // for fast world space reconstruction
- uniform float4x4 _FrustumCornersWS;
- uniform float4 _CameraWS;
- struct v2f {
- float4 pos : SV_POSITION;
- float2 uv : TEXCOORD0;
- float2 uv_depth : TEXCOORD1;
- float4 interpolatedRay : TEXCOORD2;
- };
-
- v2f vert (appdata_img v)
- {
- v2f o;
- half index = v.vertex.z;
- v.vertex.z = 0.1;
- o.pos = UnityObjectToClipPos(v.vertex);
- o.uv = v.texcoord.xy;
- o.uv_depth = v.texcoord.xy;
-
- #if UNITY_UV_STARTS_AT_TOP
- if (_MainTex_TexelSize.y < 0)
- o.uv.y = 1-o.uv.y;
- #endif
-
- o.interpolatedRay = _FrustumCornersWS[(int)index];
- o.interpolatedRay.w = index;
-
- return o;
- }
-
- // Applies one of standard fog formulas, given fog coordinate (i.e. distance)
- half ComputeFogFactor (float coord)
- {
- float fogFac = 0.0;
- fogFac = coord * _SceneFogParams.z + _SceneFogParams.w;
- return saturate(fogFac);
- }
- // Distance-based fog
- float ComputeDistance (float3 camDir, float zdepth)
- {
- float dist;
- if (_SceneFogMode.y == 1)
- dist = length(camDir);
- else
- dist = zdepth * _ProjectionParams.z;
- // Built-in fog starts at near plane, so match that by
- // subtracting the near value. Not a perfect approximation
- // if near plane is very large, but good enough.
- dist -= _ProjectionParams.y;
- return dist;
- }
- // Linear half-space fog, from https://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf
- float ComputeHalfSpace (float3 wsDir)
- {
- float3 wpos = _CameraWS + wsDir;
- float FH = _HeightParams.x;
- float3 C = _CameraWS;
- float3 V = wsDir;
- float3 P = wpos;
- float3 aV = _HeightParams.w * V;
- float FdotC = _HeightParams.y;
- float k = _HeightParams.z;
- float FdotP = P.y-FH;
- float FdotV = wsDir.y;
- float c1 = k * (FdotP + FdotC);
- float c2 = (1-2*k) * FdotP;
- float g = min(c2, 0.0);
- g = -length(aV) * (c1 - g * g / abs(FdotV+1.0e-5f));
- return g;
- }
- half4 ComputeFog (v2f i, bool distance, bool height) : SV_Target
- {
- half4 sceneColor = tex2D(_MainTex, i.uv);
-
- // Reconstruct world space position & direction
- // towards this screen pixel.
- float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);
- float dpth = Linear01Depth(rawDepth);
- float4 wsDir = dpth * i.interpolatedRay;
- float4 wsPos = _CameraWS + wsDir;
- half fogMask = ComputeHalfSpace (wsDir);
- half fogFac = ComputeFogFactor (max(0.0,fogMask + _DistanceParams.x));
- // Do not fog skybox
- if (rawDepth == _DistanceParams.y){
- fogMask = 0.0;
- }
- fixed4 fogColor = lerp(_Color,sceneColor * _Color,fogFac);
- return lerp(sceneColor,fogColor,saturate(fogMask * _Color.a));
- }
- ENDCG
- SubShader
- {
- ZTest Always Cull Off ZWrite Off Fog { Mode Off }
- // 0: distance + height
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- #define DISTANCE
- #define HEIGHT
- half4 frag (v2f i) : SV_Target { return ComputeFog (i, true, true); }
- ENDCG
- }
- }
- Fallback off
- }
|