1/*
2	Scale3xSFX
3	by Sp00kyFox, 2015
4
5Filter:	Nearest
6Scale:	3x
7
8Scale3SFX improves upon the original Scale3x by avoiding the occurence of artifacts and smoothing out 45� edges.
9
10*/
11
12// Parameter lines go here:
13#pragma parameter YTR "SCALE2xSFX Y Threshold" 48.0 0.0 255.0 1.0
14#pragma parameter UTR "SCALE2xSFX U Threshold"  7.0 0.0 255.0 1.0
15#pragma parameter VTR "SCALE2xSFX V Threshold"  6.0 0.0 255.0 1.0
16
17#define saturate(c) clamp(c, 0.0, 1.0)
18#define lerp(a,b,c) mix(a,b,c)
19#define mul(a,b) (b*a)
20#define fmod(c,d) mod(c,d)
21#define frac(c) fract(c)
22#define tex2D(c,d) COMPAT_TEXTURE(c,d)
23#define float2 vec2
24#define float3 vec3
25#define float4 vec4
26#define int2 ivec2
27#define int3 ivec3
28#define int4 ivec4
29#define bool2 bvec2
30#define bool3 bvec3
31#define bool4 bvec4
32#define float2x2 mat2x2
33#define float3x3 mat3x3
34#define float4x4 mat4x4
35#define float4x3 mat4x3
36
37#define decal Source
38
39#if defined(VERTEX)
40
41#if __VERSION__ >= 130
42#define COMPAT_VARYING out
43#define COMPAT_ATTRIBUTE in
44#define COMPAT_TEXTURE texture
45#else
46#define COMPAT_VARYING varying
47#define COMPAT_ATTRIBUTE attribute
48#define COMPAT_TEXTURE texture2D
49#endif
50
51#ifdef GL_ES
52#define COMPAT_PRECISION mediump
53#else
54#define COMPAT_PRECISION
55#endif
56
57COMPAT_ATTRIBUTE vec4 VertexCoord;
58COMPAT_ATTRIBUTE vec4 COLOR;
59COMPAT_ATTRIBUTE vec4 TexCoord;
60COMPAT_VARYING vec4 COL0;
61COMPAT_VARYING vec4 TEX0;
62COMPAT_VARYING vec4 t1;
63COMPAT_VARYING vec4 t2;
64COMPAT_VARYING vec4 t3;
65COMPAT_VARYING vec4 t4;
66COMPAT_VARYING vec4 t5;
67
68uniform mat4 MVPMatrix;
69uniform COMPAT_PRECISION int FrameDirection;
70uniform COMPAT_PRECISION int FrameCount;
71uniform COMPAT_PRECISION vec2 OutputSize;
72uniform COMPAT_PRECISION vec2 TextureSize;
73uniform COMPAT_PRECISION vec2 InputSize;
74
75// vertex compatibility #defines
76#define vTexCoord TEX0.xy
77#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
78#define outsize vec4(OutputSize, 1.0 / OutputSize)
79
80void main()
81{
82    gl_Position = MVPMatrix * VertexCoord;
83    COL0 = COLOR;
84    TEX0.xy = TexCoord.xy;
85
86	float2 ps = float2(SourceSize.z, SourceSize.w);
87	float dx = ps.x;
88	float dy = ps.y;
89
90	t1 = TEX0.xxxy + float4(-dx,  0., dx,-dy);	// A, B, C
91	t2 = TEX0.xxxy + float4(-dx,  0., dx,  0.);	// D, E, F
92	t3 = TEX0.xxxy + float4(-dx,  0., dx, dy);	// G, H, I
93	t4 = TEX0.xyxy + float4(    0.,-2.*dy,-2.*dx,    0.);	// J, K
94	t5 = TEX0.xyxy + float4( 2.*dx,    0.,    0., 2.*dy);	// L, M
95}
96
97#elif defined(FRAGMENT)
98
99#if __VERSION__ >= 130
100#define COMPAT_VARYING in
101#define COMPAT_TEXTURE texture
102out vec4 FragColor;
103#else
104#define COMPAT_VARYING varying
105#define FragColor gl_FragColor
106#define COMPAT_TEXTURE texture2D
107#endif
108
109#ifdef GL_ES
110#ifdef GL_FRAGMENT_PRECISION_HIGH
111precision highp float;
112#else
113precision mediump float;
114#endif
115#define COMPAT_PRECISION mediump
116#else
117#define COMPAT_PRECISION
118#endif
119
120uniform COMPAT_PRECISION int FrameDirection;
121uniform COMPAT_PRECISION int FrameCount;
122uniform COMPAT_PRECISION vec2 OutputSize;
123uniform COMPAT_PRECISION vec2 TextureSize;
124uniform COMPAT_PRECISION vec2 InputSize;
125uniform sampler2D Texture;
126COMPAT_VARYING vec4 TEX0;
127COMPAT_VARYING vec4 t1;
128COMPAT_VARYING vec4 t2;
129COMPAT_VARYING vec4 t3;
130COMPAT_VARYING vec4 t4;
131COMPAT_VARYING vec4 t5;
132
133// fragment compatibility #defines
134#define Source Texture
135#define vTexCoord TEX0.xy
136
137#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
138#define outsize vec4(OutputSize, 1.0 / OutputSize)
139
140#ifdef PARAMETER_UNIFORM
141uniform COMPAT_PRECISION float YTR;
142uniform COMPAT_PRECISION float UTR;
143uniform COMPAT_PRECISION float VTR;
144#else
145#define YTR 48.0
146#define UTR 7.0
147#define VTR 6.0
148#endif
149
150const float3x3 YUV  = float3x3(0.299, -0.168736, 0.5, 0.587, -0.331264, -0.418688, 0.114, 0.5, -0.081312);	// transponed
151float3 thresh = float3(YTR, UTR, VTR)/255.0;
152
153bool3 eq(float3 A, float3 B){
154	return lessThanEqual(abs(A-B) , thresh);
155}
156
157bool3 neq(float3 A, float3 B){
158	return greaterThan(abs(A-B) , thresh);
159}
160
161void main()
162{
163	// subpixel determination
164	float2 fp = floor(2.0 * frac(vTexCoord*SourceSize.xy));
165
166	/*
167		    J
168		  A B C		E0 E1
169		K D E F L	E2 E3
170		  G H I
171		    M
172	*/
173
174	// reading the texels & colorspace conversion
175	float3 b = tex2D(decal, t1.yw).xyz;
176	float3 d = tex2D(decal, t2.xw).xyz;
177	float3 e = tex2D(decal, t2.yw).xyz;
178	float3 f = tex2D(decal, t2.zw).xyz;
179	float3 h = tex2D(decal, t3.yw).xyz;
180
181	float4x3 tmp = mul(float4x3(b,d,e,f), YUV);
182	float3 B = tmp[0], D = tmp[1], E = tmp[2], F = tmp[3], H = mul(h, YUV);
183
184	float3 A = tex2D(decal, t1.xw).xyz;
185	float3 C = tex2D(decal, t1.zw).xyz;
186	float3 G = tex2D(decal, t3.xw).xyz;
187	float3 I = tex2D(decal, t3.zw).xyz;
188
189	tmp = mul(float4x3(A,C,G,I), YUV);
190	A = tmp[0], C = tmp[1], G = tmp[2], I = tmp[3];
191
192	float3 J = tex2D(decal, t4.xy).xyz;
193	float3 K = tex2D(decal, t4.zw).xyz;
194	float3 L = tex2D(decal, t5.xy).xyz;
195	float3 M = tex2D(decal, t5.zw).xyz;
196
197	tmp = mul(float4x3(J,K,L,M), YUV);
198	J = tmp[0], K = tmp[1], L = tmp[2], M = tmp[3];
199
200	// parent condition
201	bool par0 = neq(B,F) == bool3(true) && neq(D,H) == bool3(true);
202	bool par1 = neq(B,D) == bool3(true) && neq(F,H) == bool3(true);
203
204	// equality checks
205	bool AE = eq(A,E) == bool3(true);
206	bool CE = eq(C,E) == bool3(true);
207	bool EG = eq(E,G) == bool3(true);
208	bool EI = eq(E,I) == bool3(true);
209
210	// artifact prevention
211	bool art0 = CE || EG;
212	bool art1 = AE || EI;
213
214	// rules
215	float3 E0 = eq(B,D) == bool3(true) && par0 == true && (AE == false || art0 == true || eq(A,J) == bool3(true) || eq(A,K) == bool3(true)) ? 0.5*(b+d) : e;
216	float3 E1 = eq(B,F) == bool3(true) && par1 == true && (CE == false || art1 == true || eq(C,J) == bool3(true) || eq(C,L) == bool3(true)) ? 0.5*(b+f) : e;
217	float3 E2 = eq(D,H) == bool3(true) && par1 == true && (EG == false || art1 == true || eq(G,K) == bool3(true) || eq(G,M) == bool3(true)) ? 0.5*(h+d) : e;
218	float3 E3 = eq(F,H) == bool3(true) && par0 == true && (EI == false || art0 == true || eq(I,L) == bool3(true) || eq(I,M) == bool3(true)) ? 0.5*(h+f) : e;
219
220	// subpixel output
221	FragColor = vec4(fp.y == 0. ? (fp.x == 0. ? E0 : E1) : (fp.x == 0. ? E2 : E3), 1.0);
222}
223#endif
224