1 Shader "Hidden/GlobalFog" {
2 Properties {
3     _MainTex (
"Base (RGB)", 2D) = "black" {}
4 }
5
6 CGINCLUDE
7
8     #include
"UnityCG.cginc"
9
10     uniform sampler2D _MainTex;
11     uniform sampler2D_float _CameraDepthTexture;
12     
13     
// x = fog height
14     
// y = FdotC (CameraY-FogHeight)
15     
// z = k (FdotC > 0.0)
16     
// w = a/2
17     uniform float4 _HeightParams;
18     
19     
// x = start distance
20     uniform float4 _DistanceParams;
21     
22     int4 _SceneFogMode;
// x = fog mode, y = use radial flag
23     float4 _SceneFogParams;
24     #ifndef UNITY_APPLY_FOG
25     half4 unity_FogColor;
26     half4 unity_FogDensity;
27     #endif
28
29     uniform float4 _MainTex_TexelSize;
30     
31     
// for fast world space reconstruction
32     uniform float4x4 _FrustumCornersWS;
33     uniform float4 _CameraWS;
34
35     
struct v2f {
36         float4 pos : SV_POSITION;
37         float2 uv : TEXCOORD0;
38         float2 uv_depth : TEXCOORD1;
39         float4 interpolatedRay : TEXCOORD2;
40     };
41     
42     v2f vert (appdata_img v)
43     {
44         v2f o;
45         half index = v.vertex.z;
46         v.vertex.z =
0.1;
47         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
48         o.uv = v.texcoord.xy;
49         o.uv_depth = v.texcoord.xy;
50         
51         #
if UNITY_UV_STARTS_AT_TOP
52         
if (_MainTex_TexelSize.y < 0)
53             o.uv.y =
1-o.uv.y;
54         #endif
55         
56         o.interpolatedRay = _FrustumCornersWS[(
int)index];
57         o.interpolatedRay.w = index;
58         
59         
return o;
60     }
61     
62     
// Applies one of standard fog formulas, given fog coordinate (i.e. distance)
63     half ComputeFogFactor (
float coord)
64     {
65         
float fogFac = 0.0;
66         
if (_SceneFogMode.x == 1) // linear
67         {
68             
// factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start))
69             fogFac = coord * _SceneFogParams.z + _SceneFogParams.w;
70         }
71         
if (_SceneFogMode.x == 2) // exp
72         {
73             
// factor = exp(-density*z)
74             fogFac = _SceneFogParams.y * coord; fogFac = exp2(-fogFac);
75         }
76         
if (_SceneFogMode.x == 3) // exp2
77         {
78             
// factor = exp(-(density*z)^2)
79             fogFac = _SceneFogParams.x * coord; fogFac = exp2(-fogFac*fogFac);
80         }
81         
return saturate(fogFac);
82     }
83
84     
// Distance-based fog
85     
float ComputeDistance (float3 camDir, float zdepth)
86     {
87         
float dist;
88         
if (_SceneFogMode.y == 1)
89             dist = length(camDir);
90         
else
91             dist = zdepth * _ProjectionParams.z;
92         
// Built-in fog starts at near plane, so match that by
93         
// subtracting the near value. Not a perfect approximation
94         
// if near plane is very large, but good enough.
95         dist -= _ProjectionParams.y;
96         
return dist;
97     }
98
99     
// Linear half-space fog, from https://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf
100     
float ComputeHalfSpace (float3 wsDir)
101     {
102         float3 wpos = _CameraWS + wsDir;
103         
float FH = _HeightParams.x;
104         float3 C = _CameraWS;
105         float3 V = wsDir;
106         float3 P = wpos;
107         float3 aV = _HeightParams.w * V;
108         
float FdotC = _HeightParams.y;
109         
float k = _HeightParams.z;
110         
float FdotP = P.y-FH;
111         
float FdotV = wsDir.y;
112         
float c1 = k * (FdotP + FdotC);
113         
float c2 = (1-2*k) * FdotP;
114         
float g = min(c2, 0.0);
115         g = -length(aV) * (c1 - g * g / abs(FdotV+
1.0e-5f));
116         
return g;
117     }
118
119     half4 ComputeFog (v2f i,
bool distance, bool height) : SV_Target
120     {
121         half4 sceneColor = tex2D(_MainTex, i.uv);
122         
123         
// Reconstruct world space position & direction
124         
// towards this screen pixel.
125         
float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);
126         
float dpth = Linear01Depth(rawDepth);
127         float4 wsDir = dpth * i.interpolatedRay;
128         float4 wsPos = _CameraWS + wsDir;
129
130         
// Compute fog distance
131         
float g = _DistanceParams.x;
132         
if (distance)
133             g += ComputeDistance (wsDir, dpth);
134         
if (height)
135             g += ComputeHalfSpace (wsDir);
136
137         
// Compute fog amount
138         half fogFac = ComputeFogFactor (max(
0.0,g));
139         
// Do not fog skybox
140         
if (rawDepth >= 0.999999)
141             fogFac =
1.0;
142         
//return fogFac; // for debugging
143         
144         
// Lerp between fog color & original scene color
145         
// by fog amount
146         
return lerp (unity_FogColor, sceneColor, fogFac);
147     }
148
149 ENDCG
150
151 SubShader
152 {
153     ZTest Always Cull Off ZWrite Off Fog { Mode Off }
154
155     
// 0: distance + height
156     Pass
157     {
158         CGPROGRAM
159         #pragma vertex vert
160         #pragma fragment frag
161         half4 frag (v2f i) : SV_Target {
return ComputeFog (i, true, true); }
162         ENDCG
163     }
164     
// 1: distance
165     Pass
166     {
167         CGPROGRAM
168         #pragma vertex vert
169         #pragma fragment frag
170         half4 frag (v2f i) : SV_Target {
return ComputeFog (i, true, false); }
171         ENDCG
172     }
173     
// 2: height
174     Pass
175     {
176         CGPROGRAM
177         #pragma vertex vert
178         #pragma fragment frag
179         half4 frag (v2f i) : SV_Target {
return ComputeFog (i, false, true); }
180         ENDCG
181     }
182 }
183
184 Fallback off
185
186 }


Gõ tìm kiếm nhanh...