1
2 //
3 // modified and adapted DLAA code based
on Dmitry Andreev's
4 // Directionally Localized Anti-Aliasing (DLAA)
5 //
6 //
as seen in "The Force Unleashed 2"
7 //

8
9 Shader
"Hidden/DLAA" {
10 Properties {
11     _MainTex (
"Base (RGB)", 2D) = "white" {}
12 }
13
14 CGINCLUDE
15     
16     #include
"UnityCG.cginc"
17
18     uniform sampler2D _MainTex;
19     uniform float4 _MainTex_TexelSize;
20
21     
struct v2f {
22         float4 pos : SV_POSITION;
23         float2 uv : TEXCOORD0;
24     };
25     
26     #define LD( o, dx, dy ) o = tex2D( _MainTex, texCoord + float2( dx, dy ) * _MainTex_TexelSize.xy );
27     
28     
float GetIntensity( float3 col )
29     {
30         
return dot( col, float3( 0.33f, 0.33f, 0.33f ) );
31     }
32     
33     float4 highPassPre( float2 texCoord )
34     {
35         LD(float4 sCenter,
0.0,0.0)
36         LD(float4 sUpLeft, -
1.0,-1.0)
37         LD(float4 sUpRight,
1.0,-1.0)
38         LD(float4 sDownLeft, -
1.0,1.0)
39         LD(float4 sDownRight,
1.0,1.0)
40      
41         float4 diff =
4.0f * abs( (sUpLeft + sUpRight + sDownLeft + sDownRight) - 4.0f * sCenter );
42         
float edgeMask = GetIntensity(diff.xyz);
43     
44         
return float4(sCenter.rgb, edgeMask);
45     }
46     
47     
// Softer (5-pixel wide high-pass)
48     
/*
49     
void HighPassEdgeHV (out float4 edge_h, out float4 edge_v, float4 center, float4 w_h, float4 w_v, float2 texCoord) {
50         edge_h = abs( w_h -
4.0f * center ) / 4.0f;
51         edge_v = abs( w_v -
4.0f * center ) / 4.0f;
52     }
53
54     // Sharper (
3-pixel wide high-pass)
55     
void EdgeHV (out float4 edge_h, out float4 edge_v, float4 center, float2 texCoord) {
56         float4 left, right, top, bottom;
57
58         LD( left, -
1, 0 )
59         LD( right,
1, 0 )
60         LD( top,
0, -1 )
61         LD( bottom,
0, 1 )
62         
63         edge_h = abs( left + right -
2.0f * center ) / 2.0f;
64         edge_v = abs( top + bottom -
2.0f * center ) / 2.0f;
65     }
66     */

67     
68     float4 edgeDetectAndBlur( float2 texCoord )
69     {
70     
float lambda = 3.0f;
71     
float epsilon = 0.1f;
72     
73     
//
74     
// Short Edges
75     
//
76     
77     float4 center, left_01, right_01, top_01, bottom_01;
78
79     
// sample 5x5 cross
80     LD( center,
0, 0 )
81     LD( left_01, -
1.5, 0 )
82     LD( right_01,
1.5, 0 )
83     LD( top_01,
0,-1.5 )
84     LD( bottom_01,
0, 1.5 )
85
86
87     float4 w_h =
2.0f * ( left_01 + right_01 );
88     float4 w_v =
2.0f * ( top_01 + bottom_01 );
89
90     
91         
// Softer (5-pixel wide high-pass)
92         float4 edge_h = abs( w_h -
4.0f * center ) / 4.0f;
93         float4 edge_v = abs( w_v -
4.0f * center ) / 4.0f;
94         
95
96     float4 blurred_h = ( w_h +
2.0f * center ) / 6.0f;
97     float4 blurred_v = ( w_v +
2.0f * center ) / 6.0f;
98
99     
float edge_h_lum = GetIntensity( edge_h.xyz );
100     
float edge_v_lum = GetIntensity( edge_v.xyz );
101     
float blurred_h_lum = GetIntensity( blurred_h.xyz );
102     
float blurred_v_lum = GetIntensity( blurred_v.xyz );
103
104     
float edge_mask_h = saturate( ( lambda * edge_h_lum - epsilon ) / blurred_v_lum );
105     
float edge_mask_v = saturate( ( lambda * edge_v_lum - epsilon ) / blurred_h_lum );
106
107     float4 clr = center;
108     clr = lerp( clr, blurred_h, edge_mask_v );
109     clr = lerp( clr, blurred_v, edge_mask_h );
// blurrier version
110
111     
//
112     
// Long Edges
113     
//
114     
115     float4 h0, h1, h2, h3, h4, h5, h6, h7;
116     float4 v0, v1, v2, v3, v4, v5, v6, v7;
117
118     
// sample 16x16 cross (sparse-sample on X360, incremental kernel update on SPUs)
119     LD( h0,
1.5, 0 ) LD( h1, 3.5, 0 ) LD( h2, 5.5, 0 ) LD( h3, 7.5, 0 ) LD( h4, -1.5,0 ) LD( h5, -3.5,0 ) LD( h6, -5.5,0 ) LD( h7, -7.5,0 )
120     LD( v0,
0, 1.5 ) LD( v1, 0, 3.5 ) LD( v2, 0, 5.5 ) LD( v3, 0, 7.5 ) LD( v4, 0,-1.5 ) LD( v5, 0,-3.5 ) LD( v6, 0,-5.5 ) LD( v7, 0,-7.5 )
121
122     
float long_edge_mask_h = ( h0.a + h1.a + h2.a + h3.a + h4.a + h5.a + h6.a + h7.a ) / 8.0f;
123     
float long_edge_mask_v = ( v0.a + v1.a + v2.a + v3.a + v4.a + v5.a + v6.a + v7.a ) / 8.0f;
124
125     long_edge_mask_h = saturate( long_edge_mask_h *
2.0f - 1.0f );
126     long_edge_mask_v = saturate( long_edge_mask_v *
2.0f - 1.0f );
127
128         float4 left, right, top, bottom;
129
130         LD( left, -
1, 0 )
131         LD( right,
1, 0 )
132         LD( top,
0, -1 )
133         LD( bottom,
0, 1 )
134
135     
if ( long_edge_mask_h > 0 || long_edge_mask_v > 0 ) // faster but less resistant to noise (TFU2 X360)
136     
//if ( abs( long_edge_mask_h - long_edge_mask_v ) > 0.2f ) // resistant to noise (TFU2 SPUs)
137     {
138         float4 long_blurred_h = ( h0 + h1 + h2 + h3 + h4 + h5 + h6 + h7 ) /
8.0f;
139         float4 long_blurred_v = ( v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7 ) /
8.0f;
140
141         
float lb_h_lum = GetIntensity( long_blurred_h.xyz );
142         
float lb_v_lum = GetIntensity( long_blurred_v.xyz );
143
144         
float center_lum = GetIntensity( center.xyz );
145         
float left_lum = GetIntensity( left.xyz );
146         
float right_lum = GetIntensity( right.xyz );
147         
float top_lum = GetIntensity( top.xyz );
148         
float bottom_lum = GetIntensity( bottom.xyz );
149
150         float4 clr_v = center;
151         float4 clr_h = center;
152
153         
// we had to hack this because DIV by 0 gives some artefacts on different platforms
154         
float hx = center_lum == top_lum ? 0.0 : saturate( 0 + ( lb_h_lum - top_lum ) / ( center_lum - top_lum ) );
155         
float hy = center_lum == bottom_lum ? 0.0 : saturate( 1 + ( lb_h_lum - center_lum ) / ( center_lum - bottom_lum ) );
156         
float vx = center_lum == left_lum ? 0.0 : saturate( 0 + ( lb_v_lum - left_lum ) / ( center_lum - left_lum ) );
157         
float vy = center_lum == right_lum ? 0.0 : saturate( 1 + ( lb_v_lum - center_lum ) / ( center_lum - right_lum ) );
158
159         float4 vhxy = float4( vx, vy, hx, hy );
160         
//vhxy = vhxy == float4( 0, 0, 0, 0 ) ? float4( 1, 1, 1, 1 ) : vhxy;
161
162         clr_v = lerp( left , clr_v, vhxy.x );
163         clr_v = lerp( right , clr_v, vhxy.y );
164         clr_h = lerp( top , clr_h, vhxy.z );
165         clr_h = lerp( bottom, clr_h, vhxy.w );
166
167         clr = lerp( clr, clr_v, long_edge_mask_v );
168         clr = lerp( clr, clr_h, long_edge_mask_h );
169     }
170
171     
return clr;
172     }
173
174     float4 edgeDetectAndBlurSharper(float2 texCoord)
175     {
176     
float lambda = 3.0f;
177     
float epsilon = 0.1f;
178     
179     
//
180     
// Short Edges
181     
//
182     
183     float4 center, left_01, right_01, top_01, bottom_01;
184
185     
// sample 5x5 cross
186     LD( center,
0, 0 )
187     LD( left_01, -
1.5, 0 )
188     LD( right_01,
1.5, 0 )
189     LD( top_01,
0,-1.5 )
190     LD( bottom_01,
0, 1.5 )
191
192
193     float4 w_h =
2.0f * ( left_01 + right_01 );
194     float4 w_v =
2.0f * ( top_01 + bottom_01 );
195
196         
// Sharper (3-pixel wide high-pass)
197         float4 left, right, top, bottom;
198
199         LD( left, -
1, 0 )
200         LD( right,
1, 0 )
201         LD( top,
0, -1 )
202         LD( bottom,
0, 1 )
203         
204         float4 edge_h = abs( left + right -
2.0f * center ) / 2.0f;
205         float4 edge_v = abs( top + bottom -
2.0f * center ) / 2.0f;
206
207     float4 blurred_h = ( w_h +
2.0f * center ) / 6.0f;
208     float4 blurred_v = ( w_v +
2.0f * center ) / 6.0f;
209
210     
float edge_h_lum = GetIntensity( edge_h.xyz );
211     
float edge_v_lum = GetIntensity( edge_v.xyz );
212     
float blurred_h_lum = GetIntensity( blurred_h.xyz );
213     
float blurred_v_lum = GetIntensity( blurred_v.xyz );
214
215     
float edge_mask_h = saturate( ( lambda * edge_h_lum - epsilon ) / blurred_v_lum );
216     
float edge_mask_v = saturate( ( lambda * edge_v_lum - epsilon ) / blurred_h_lum );
217
218     float4 clr = center;
219     clr = lerp( clr, blurred_h, edge_mask_v );
220     clr = lerp( clr, blurred_v, edge_mask_h *
0.5f ); // TFU2 uses 1.0f instead of 0.5f
221
222     
//
223     
// Long Edges
224     
//
225     
226     float4 h0, h1, h2, h3, h4, h5, h6, h7;
227     float4 v0, v1, v2, v3, v4, v5, v6, v7;
228
229     
// sample 16x16 cross (sparse-sample on X360, incremental kernel update on SPUs)
230     LD( h0,
1.5, 0 ) LD( h1, 3.5, 0 ) LD( h2, 5.5, 0 ) LD( h3, 7.5, 0 ) LD( h4, -1.5,0 ) LD( h5, -3.5,0 ) LD( h6, -5.5,0 ) LD( h7, -7.5,0 )
231     LD( v0,
0, 1.5 ) LD( v1, 0, 3.5 ) LD( v2, 0, 5.5 ) LD( v3, 0, 7.5 ) LD( v4, 0,-1.5 ) LD( v5, 0,-3.5 ) LD( v6, 0,-5.5 ) LD( v7, 0,-7.5 )
232
233     
float long_edge_mask_h = ( h0.a + h1.a + h2.a + h3.a + h4.a + h5.a + h6.a + h7.a ) / 8.0f;
234     
float long_edge_mask_v = ( v0.a + v1.a + v2.a + v3.a + v4.a + v5.a + v6.a + v7.a ) / 8.0f;
235
236     long_edge_mask_h = saturate( long_edge_mask_h *
2.0f - 1.0f );
237     long_edge_mask_v = saturate( long_edge_mask_v *
2.0f - 1.0f );
238
239     
//if ( long_edge_mask_h > 0 || long_edge_mask_v > 0 ) // faster but less resistant to noise (TFU2 X360)
240     
if ( abs( long_edge_mask_h - long_edge_mask_v ) > 0.2f ) // resistant to noise (TFU2 SPUs)
241     {
242         float4 long_blurred_h = ( h0 + h1 + h2 + h3 + h4 + h5 + h6 + h7 ) /
8.0f;
243         float4 long_blurred_v = ( v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7 ) /
8.0f;
244
245         
float lb_h_lum = GetIntensity( long_blurred_h.xyz );
246         
float lb_v_lum = GetIntensity( long_blurred_v.xyz );
247
248         
float center_lum = GetIntensity( center.xyz );
249         
float left_lum = GetIntensity( left.xyz );
250         
float right_lum = GetIntensity( right.xyz );
251         
float top_lum = GetIntensity( top.xyz );
252         
float bottom_lum = GetIntensity( bottom.xyz );
253  
254         float4 clr_v = center;
255         float4 clr_h = center;
256
257         
// we had to hack this because DIV by 0 gives some artefacts on different platforms
258         
float hx = center_lum == top_lum ? 0.0 : saturate( 0 + ( lb_h_lum - top_lum ) / ( center_lum - top_lum ) );
259         
float hy = center_lum == bottom_lum ? 0.0 : saturate( 1 + ( lb_h_lum - center_lum ) / ( center_lum - bottom_lum ) );
260         
float vx = center_lum == left_lum ? 0.0 : saturate( 0 + ( lb_v_lum - left_lum ) / ( center_lum - left_lum ) );
261         
float vy = center_lum == right_lum ? 0.0 : saturate( 1 + ( lb_v_lum - center_lum ) / ( center_lum - right_lum ) );
262
263         float4 vhxy = float4( vx, vy, hx, hy );
264         
//vhxy = vhxy == float4( 0, 0, 0, 0 ) ? float4( 1, 1, 1, 1 ) : vhxy;
265
266         clr_v = lerp( left , clr_v, vhxy.x );
267         clr_v = lerp( right , clr_v, vhxy.y );
268         clr_h = lerp( top , clr_h, vhxy.z );
269         clr_h = lerp( bottom, clr_h, vhxy.w );
270
271         clr = lerp( clr, clr_v, long_edge_mask_v );
272         clr = lerp( clr, clr_h, long_edge_mask_h );
273     }
274
275     
return clr;
276     }
277
278
279     v2f vert( appdata_img v ) {
280         v2f o;
281         o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
282         
283         float2 uv = v.texcoord.xy;
284         o.uv.xy = uv;
285         
286         
return o;
287     }
288
289     half4 fragFirst (v2f i) : SV_Target {
290         
return highPassPre (i.uv);
291     }
292     
293     half4 fragSecond (v2f i) : SV_Target {
294         
return edgeDetectAndBlur( i.uv );
295     }
296
297     half4 fragThird (v2f i) : SV_Target {
298         
return edgeDetectAndBlurSharper( i.uv );
299     }
300             
301 ENDCG
302
303 SubShader {
304     Pass {
305         ZTest Always Cull Off ZWrite Off
306     
307         CGPROGRAM
308     
309         #pragma vertex vert
310         #pragma fragment fragFirst
311         #pragma exclude_renderers d3d11_9x
312         
313         ENDCG
314     }
315     
316     Pass {
317         ZTest Always Cull Off ZWrite Off
318     
319         CGPROGRAM
320     
321         #pragma vertex vert
322         #pragma fragment fragSecond
323         #pragma target
3.0
324         #pragma exclude_renderers d3d11_9x
325         
326         ENDCG
327     }
328
329     Pass {
330         ZTest Always Cull Off ZWrite Off
331     
332         CGPROGRAM
333     
334         #pragma vertex vert
335         #pragma fragment fragThird
336         #pragma target
3.0
337         
338         ENDCG
339     }
340 }
341
342 Fallback off
343
344 }


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