11// This is a combination of linear interpolation and light version of cas
22
33//!MAGPIE EFFECT
4- //!VERSION 1
4+ //!VERSION 2
55
6- //!CONSTANT
7- //!VALUE INPUT_PT_X
8- float inputPtX;
9-
10- //!CONSTANT
11- //!VALUE INPUT_PT_Y
12- float inputPtY;
6+ //!PARAMETER
7+ //!DEFAULT 0.5
8+ //!MIN 0
9+ //!MAX 1
10+ float sharpness;
1311
1412//!TEXTURE
1513Texture2D INPUT;
@@ -18,55 +16,79 @@ Texture2D INPUT;
1816//!FILTER LINEAR
1917SamplerState sam;
2018
21- //!CONSTANT
22- //!DEFAULT 0.33
23- //!MIN 0
24- //!MAX 1
25- float sharpness;
19+ //!PASS 1
20+ //!IN INPUT
21+ //!BLOCK_SIZE 16
22+ //!NUM_THREADS 64
2623
27- //!CONSTANT
28- //!DEFAULT 0.2
29- //!MIN 0
30- //!MAX 1
31- float threshold;
24+ float3 LCAS (uint2 ip, float peak) {
3225
33- //!PASS 1
34- //!BIND INPUT
26+ float2 pos = (ip + 0.5f ) * GetOutputPt ();
27+ float2 inputPt = GetInputPt ();
3528
36- float4 Pass1 (float2 pos) {
37- // fetch a 4 neighborhood pixels around the pixel 'e',
38- // b
29+ // fetch a 3x3 neighborhood around the pixel 'e',
30+ // a b c
3931 // d(e)f
40- // h
41- float3 b = INPUT.Sample (sam, pos + float2 (0 , -inputPtY)).rgb;
42- float3 d = INPUT.Sample (sam, pos + float2 (-inputPtX, 0 )).rgb;
43- float3 e = INPUT.Sample (sam, pos).rgb;
44- float3 f = INPUT.Sample (sam, pos + float2 (inputPtX, 0 )).rgb;
45- float3 h = INPUT.Sample (sam, pos + float2 (0 , inputPtY)).rgb;
46-
47- // Edge checker
48- float edge = length (abs (d - f) + abs (b - h));
32+ // g h i
33+ float3 a = INPUT.SampleLevel (sam, pos + float2 (-inputPt.x, -inputPt.y), 0 ).rgb;
34+ float3 b = INPUT.SampleLevel (sam, pos + float2 (0 , -inputPt.y), 0 ).rgb;
35+ float3 c = INPUT.SampleLevel (sam, pos + float2 (inputPt.x, -inputPt.y), 0 ).rgb;
36+ float3 d = INPUT.SampleLevel (sam, pos + float2 (-inputPt.x, 0 ), 0 ).rgb;
37+ float3 f = INPUT.SampleLevel (sam, pos + float2 (inputPt.x, 0 ), 0 ).rgb;
38+ float3 g = INPUT.SampleLevel (sam, pos + float2 (-inputPt.x, inputPt.y), 0 ).rgb;
39+ float3 h = INPUT.SampleLevel (sam, pos + float2 (0 , inputPt.y), 0 ).rgb;
40+ float3 i = INPUT.SampleLevel (sam, pos + float2 (inputPt.x, inputPt.y), 0 ).rgb;
41+
42+ float3 x = a + c + g + i;
43+ float3 y = b + d + f + h;
4944
45+ float3 e = INPUT.SampleLevel (sam, pos + float2 (inputPt.x * 0.25 , inputPt.y * 0.5 ), 0 ).rgb;
46+ e += INPUT.SampleLevel (sam, pos + float2 (-inputPt.x * 0.25 , -inputPt.y * 0.5 ), 0 ).rgb;
47+ e += INPUT.SampleLevel (sam, pos + float2 (inputPt.x * 0.5 , -inputPt.y * 0.25 ), 0 ).rgb;
48+ e += INPUT.SampleLevel (sam, pos + float2 (-inputPt.x * 0.5 , inputPt.y * 0.25 ), 0 ).rgb;
49+ e /= 4 ;
50+
5051 // Soft min and max.
51- // b
52+ // a b c
5253 // d e f
53- // h
54-
55- float3 mnRGB = min (min (min (d, e), min (f, b)), h);
54+ // g h i
55+ float3 mnRGB = min (min (min (min (d, e), min (f, b)), h), min (min (a, i), min (c, g)));
5656
57- float3 mxRGB = max (max (max (d, e), max (f, b)), h);
57+ float3 mxRGB = max (max (max (max ( d, e), max (f, b)), h), max ( max (a, i), max (c, g)) );
5858
5959 // Shaping amount of sharpening.
60- float3 wRGB = sqrt (min (mnRGB, 1.0 - mxRGB) / mxRGB) * lerp (- 0.125 , - 0.2 , sharpness) ;
60+ float3 wRGB = sqrt (min (mnRGB, 1.0 - mxRGB) / mxRGB) * peak ;
6161
6262 // Filter shape.
63- // w
63+ // w w w
6464 // w 1 w
65- // w
66- // If is edge
67- if (edge >= threshold)
68- return float4 ((((b + d + f + h) * wRGB + (e * 2 - (b + d + f + h) * 0.25 )) / (1.0 + 4.0 * wRGB)).rgb, 1 );
69- else
70- return float4 ((((b + d + f + h) * wRGB + e) / (1.0 + 4.0 * wRGB)).rgb, 1 );
71- // If is not edge
65+ // w w w
66+ float3 color = ((x + y) * wRGB + (e * 5.0 - (x + y * 2.0 + e * 4.0 ) / 4.0 )) / (1.0 + 8.0 * wRGB);
67+ return (color + clamp (color, mnRGB, mxRGB) * 4.0 ) / 5.0 ;
68+ }
69+
70+ void Pass1 (uint2 blockStart, uint3 threadId) {
71+ uint2 gxy = blockStart + Rmp8x8 (threadId.x);
72+ if (!CheckViewport (gxy)) {
73+ return ;
74+ }
75+
76+ const float peak = lerp (0 , -0.1111111111111111 , sharpness);
77+
78+ WriteToOutput (gxy, LCAS (gxy, peak));
79+
80+ gxy.x += 8u;
81+ if (CheckViewport (gxy)) {
82+ WriteToOutput (gxy, LCAS (gxy, peak));
83+ }
84+
85+ gxy.y += 8u;
86+ if (CheckViewport (gxy)) {
87+ WriteToOutput (gxy, LCAS (gxy, peak));
88+ }
89+
90+ gxy.x -= 8u;
91+ if (CheckViewport (gxy)) {
92+ WriteToOutput (gxy, LCAS (gxy, peak));
93+ }
7294}
0 commit comments