tree sway and shadow improvements
[WindSway-HDRP.git] / Library / PackageCache / com.unity.postprocessing@2.1.2 / PostProcessing / Shaders / Builtins / MotionBlur.shader
blob10d1cebc0598cf23b32c9091b60736d3c90b3b38
1 Shader "Hidden/PostProcessing/MotionBlur"
3     HLSLINCLUDE
5         #pragma target 3.0
6         #include "../StdLib.hlsl"
8         TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
9         float4 _MainTex_TexelSize;
11         // Camera depth texture
12         TEXTURE2D_SAMPLER2D(_CameraDepthTexture, sampler_CameraDepthTexture);
14         // Camera motion vectors texture
15         TEXTURE2D_SAMPLER2D(_CameraMotionVectorsTexture, sampler_CameraMotionVectorsTexture);
16         float4 _CameraMotionVectorsTexture_TexelSize;
18         // Packed velocity texture (2/10/10/10)
19         TEXTURE2D_SAMPLER2D(_VelocityTex, sampler_VelocityTex);
20         float2 _VelocityTex_TexelSize;
22         // NeighborMax texture
23         TEXTURE2D_SAMPLER2D(_NeighborMaxTex, sampler_NeighborMaxTex);
24         float2 _NeighborMaxTex_TexelSize;
26         // Velocity scale factor
27         float _VelocityScale;
29         // TileMax filter parameters
30         int _TileMaxLoop;
31         float2 _TileMaxOffs;
33         // Maximum blur radius (in pixels)
34         half _MaxBlurRadius;
35         float _RcpMaxBlurRadius;
37         // Filter parameters/coefficients
38         half _LoopCount;
40         // -----------------------------------------------------------------------------
41         // Prefilter
43         // Velocity texture setup
44         half4 FragVelocitySetup(VaryingsDefault i) : SV_Target
45         {
46             // Sample the motion vector.
47             float2 v = SAMPLE_TEXTURE2D(_CameraMotionVectorsTexture, sampler_CameraMotionVectorsTexture, i.texcoord).rg;
49             // Apply the exposure time and convert to the pixel space.
50             v *= (_VelocityScale * 0.5) * _CameraMotionVectorsTexture_TexelSize.zw;
52             // Clamp the vector with the maximum blur radius.
53             v /= max(1.0, length(v) * _RcpMaxBlurRadius);
55             // Sample the depth of the pixel.
56             half d = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, i.texcoord));
58             // Pack into 10/10/10/2 format.
59             return half4((v * _RcpMaxBlurRadius + 1.0) * 0.5, d, 0.0);
60         }
62         half2 MaxV(half2 v1, half2 v2)
63         {
64             return dot(v1, v1) < dot(v2, v2) ? v2 : v1;
65         }
67         // TileMax filter (2 pixel width with normalization)
68         half4 FragTileMax1(VaryingsDefault i) : SV_Target
69         {
70             float4 d = _MainTex_TexelSize.xyxy * float4(-0.5, -0.5, 0.5, 0.5);
72             half2 v1 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.xy).rg;
73             half2 v2 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.zy).rg;
74             half2 v3 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.xw).rg;
75             half2 v4 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.zw).rg;
77             v1 = (v1 * 2.0 - 1.0) * _MaxBlurRadius;
78             v2 = (v2 * 2.0 - 1.0) * _MaxBlurRadius;
79             v3 = (v3 * 2.0 - 1.0) * _MaxBlurRadius;
80             v4 = (v4 * 2.0 - 1.0) * _MaxBlurRadius;
82             return half4(MaxV(MaxV(MaxV(v1, v2), v3), v4), 0.0, 0.0);
83         }
85         // TileMax filter (2 pixel width)
86         half4 FragTileMax2(VaryingsDefault i) : SV_Target
87         {
88             float4 d = _MainTex_TexelSize.xyxy * float4(-0.5, -0.5, 0.5, 0.5);
90             half2 v1 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.xy).rg;
91             half2 v2 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.zy).rg;
92             half2 v3 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.xw).rg;
93             half2 v4 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.zw).rg;
95             return half4(MaxV(MaxV(MaxV(v1, v2), v3), v4), 0.0, 0.0);
96         }
98         // TileMax filter (variable width)
99         half4 FragTileMaxV(VaryingsDefault i) : SV_Target
100         {
101             float2 uv0 = i.texcoord + _MainTex_TexelSize.xy * _TileMaxOffs.xy;
103             float2 du = float2(_MainTex_TexelSize.x, 0.0);
104             float2 dv = float2(0.0, _MainTex_TexelSize.y);
106             half2 vo = 0.0;
108             UNITY_LOOP
109             for (int ix = 0; ix < _TileMaxLoop; ix++)
110             {
111                 UNITY_LOOP
112                 for (int iy = 0; iy < _TileMaxLoop; iy++)
113                 {
114                     float2 uv = uv0 + du * ix + dv * iy;
115                     vo = MaxV(vo, SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv).rg);
116                 }
117             }
119             return half4(vo, 0.0, 0.0);
120         }
122         // NeighborMax filter
123         half4 FragNeighborMax(VaryingsDefault i) : SV_Target
124         {
125             const half cw = 1.01; // Center weight tweak
127             float4 d = _MainTex_TexelSize.xyxy * float4(1.0, 1.0, -1.0, 0.0);
129             half2 v1 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord - d.xy).rg;
130             half2 v2 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord - d.wy).rg;
131             half2 v3 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord - d.zy).rg;
133             half2 v4 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord - d.xw).rg;
134             half2 v5 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord).rg * cw;
135             half2 v6 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.xw).rg;
137             half2 v7 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.zy).rg;
138             half2 v8 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.wy).rg;
139             half2 v9 = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord + d.xy).rg;
141             half2 va = MaxV(v1, MaxV(v2, v3));
142             half2 vb = MaxV(v4, MaxV(v5, v6));
143             half2 vc = MaxV(v7, MaxV(v8, v9));
145             return half4(MaxV(va, MaxV(vb, vc)) * (1.0 / cw), 0.0, 0.0);
146         }
148         // -----------------------------------------------------------------------------
149         // Reconstruction
151         // Returns true or false with a given interval.
152         bool Interval(half phase, half interval)
153         {
154             return frac(phase / interval) > 0.499;
155         }
157         // Jitter function for tile lookup
158         float2 JitterTile(float2 uv)
159         {
160             float rx, ry;
161             sincos(GradientNoise(uv + float2(2.0, 0.0)) * TWO_PI, ry, rx);
162             return float2(rx, ry) * _NeighborMaxTex_TexelSize.xy * 0.25;
163         }
165         // Velocity sampling function
166         half3 SampleVelocity(float2 uv)
167         {
168             half3 v = SAMPLE_TEXTURE2D_LOD(_VelocityTex, sampler_VelocityTex, uv, 0.0).xyz;
169             return half3((v.xy * 2.0 - 1.0) * _MaxBlurRadius, v.z);
170         }
172         // Reconstruction filter
173         half4 FragReconstruction(VaryingsDefault i) : SV_Target
174         {
175             // Color sample at the center point
176             const half4 c_p = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord);
178             // Velocity/Depth sample at the center point
179             const half3 vd_p = SampleVelocity(i.texcoord);
180             const half l_v_p = max(length(vd_p.xy), 0.5);
181             const half rcp_d_p = 1.0 / vd_p.z;
183             // NeighborMax vector sample at the center point
184             const half2 v_max = SAMPLE_TEXTURE2D(_NeighborMaxTex, sampler_NeighborMaxTex, i.texcoord + JitterTile(i.texcoord)).xy;
185             const half l_v_max = length(v_max);
186             const half rcp_l_v_max = 1.0 / l_v_max;
188             // Escape early if the NeighborMax vector is small enough.
189             if (l_v_max < 2.0) return c_p;
191             // Use V_p as a secondary sampling direction except when it's too small
192             // compared to V_max. This vector is rescaled to be the length of V_max.
193             const half2 v_alt = (l_v_p * 2.0 > l_v_max) ? vd_p.xy * (l_v_max / l_v_p) : v_max;
195             // Determine the sample count.
196             const half sc = floor(min(_LoopCount, l_v_max * 0.5));
198             // Loop variables (starts from the outermost sample)
199             const half dt = 1.0 / sc;
200             const half t_offs = (GradientNoise(i.texcoord) - 0.5) * dt;
201             half t = 1.0 - dt * 0.5;
202             half count = 0.0;
204             // Background velocity
205             // This is used for tracking the maximum velocity in the background layer.
206             half l_v_bg = max(l_v_p, 1.0);
208             // Color accumlation
209             half4 acc = 0.0;
211             UNITY_LOOP
212             while (t > dt * 0.25)
213             {
214                 // Sampling direction (switched per every two samples)
215                 const half2 v_s = Interval(count, 4.0) ? v_alt : v_max;
217                 // Sample position (inverted per every sample)
218                 const half t_s = (Interval(count, 2.0) ? -t : t) + t_offs;
220                 // Distance to the sample position
221                 const half l_t = l_v_max * abs(t_s);
223                 // UVs for the sample position
224                 const float2 uv0 = i.texcoord + v_s * t_s * _MainTex_TexelSize.xy;
225                 const float2 uv1 = i.texcoord + v_s * t_s * _VelocityTex_TexelSize.xy;
227                 // Color sample
228                 const half3 c = SAMPLE_TEXTURE2D_LOD(_MainTex, sampler_MainTex, uv0, 0.0).rgb;
230                 // Velocity/Depth sample
231                 const half3 vd = SampleVelocity(uv1);
233                 // Background/Foreground separation
234                 const half fg = saturate((vd_p.z - vd.z) * 20.0 * rcp_d_p);
236                 // Length of the velocity vector
237                 const half l_v = lerp(l_v_bg, length(vd.xy), fg);
239                 // Sample weight
240                 // (Distance test) * (Spreading out by motion) * (Triangular window)
241                 const half w = saturate(l_v - l_t) / l_v * (1.2 - t);
243                 // Color accumulation
244                 acc += half4(c, 1.0) * w;
246                 // Update the background velocity.
247                 l_v_bg = max(l_v_bg, l_v);
249                 // Advance to the next sample.
250                 t = Interval(count, 2.0) ? t - dt : t;
251                 count += 1.0;
252             }
254             // Add the center sample.
255             acc += half4(c_p.rgb, 1.0) * (1.2 / (l_v_bg * sc * 2.0));
257             return half4(acc.rgb / acc.a, c_p.a);
258         }
260     ENDHLSL
262     SubShader
263     {
264         Cull Off ZWrite Off ZTest Always
266         // (0) Velocity texture setup
267         Pass
268         {
269             HLSLPROGRAM
271                 #pragma vertex VertDefault
272                 #pragma fragment FragVelocitySetup
274             ENDHLSL
275         }
277         // (1) TileMax filter (2 pixel width with normalization)
278         Pass
279         {
280             HLSLPROGRAM
282                 #pragma vertex VertDefault
283                 #pragma fragment FragTileMax1
285             ENDHLSL
286         }
288         //  (2) TileMax filter (2 pixel width)
289         Pass
290         {
291             HLSLPROGRAM
293                 #pragma vertex VertDefault
294                 #pragma fragment FragTileMax2
296             ENDHLSL
297         }
299         // (3) TileMax filter (variable width)
300         Pass
301         {
302             HLSLPROGRAM
304                 #pragma vertex VertDefault
305                 #pragma fragment FragTileMaxV
307             ENDHLSL
308         }
310         // (4) NeighborMax filter
311         Pass
312         {
313             HLSLPROGRAM
315                 #pragma vertex VertDefault
316                 #pragma fragment FragNeighborMax
318             ENDHLSL
319         }
321         // (5) Reconstruction filter
322         Pass
323         {
324             HLSLPROGRAM
326                 #pragma vertex VertDefault
327                 #pragma fragment FragReconstruction
329             ENDHLSL
330         }
331     }