all repos — mgba @ d242638e28fe899406068e11681b002256708d46

mGBA Game Boy Advance Emulator

res/shaders/xbr.shader/xbr.fs (view raw)

  1/*
  2   Hyllian's xBR-lv3 Shader
  3   
  4   Copyright (C) 2011-2015 Hyllian - sergiogdb@gmail.com
  5
  6   Permission is hereby granted, free of charge, to any person obtaining a copy
  7   of this software and associated documentation files (the "Software"), to deal
  8   in the Software without restriction, including without limitation the rights
  9   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10   copies of the Software, and to permit persons to whom the Software is
 11   furnished to do so, subject to the following conditions:
 12
 13   The above copyright notice and this permission notice shall be included in
 14   all copies or substantial portions of the Software.
 15
 16   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22   THE SOFTWARE.
 23
 24
 25   Incorporates some of the ideas from SABR shader. Thanks to Joshua Street.
 26*/
 27
 28uniform float XBR_Y_WEIGHT;
 29uniform float XBR_EQ_THRESHOLD;
 30uniform float XBR_EQ_THRESHOLD2;
 31uniform float XBR_LV2_COEFFICIENT;
 32
 33const mat3 yuv = mat3(0.299, 0.587, 0.114, -0.169, -0.331, 0.499, 0.499, -0.418, -0.0813);
 34const vec4 delta = vec4(0.4, 0.4, 0.4, 0.4);
 35
 36vec4 df(vec4 A, vec4 B)
 37{
 38	return vec4(abs(A-B));
 39}
 40
 41float c_df(vec3 c1, vec3 c2) {
 42	vec3 df = abs(c1 - c2);
 43	return df.r + df.g + df.b;
 44}
 45
 46bvec4 eq(vec4 A, vec4 B)
 47{
 48	return lessThan(df(A, B), vec4(XBR_EQ_THRESHOLD));
 49}
 50
 51bvec4 eq2(vec4 A, vec4 B)
 52{
 53	return lessThan(df(A, B), vec4(XBR_EQ_THRESHOLD2));
 54}
 55
 56bvec4 and(bvec4 A, bvec4 B)
 57{
 58	return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w);
 59}
 60
 61bvec4 or(bvec4 A, bvec4 B)
 62{
 63	return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w);
 64}
 65
 66vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h)
 67{
 68	return (df(a,b) + df(a,c) + df(d,e) + df(d,f) + 4.0*df(g,h));
 69}
 70
 71// GLSL shader autogenerated by cg2glsl.py.
 72#if __VERSION__ >= 130
 73#define varying in
 74#define COMPAT_TEXTURE texture
 75out vec4 FragColor;
 76#else
 77#define FragColor gl_FragColor
 78#define COMPAT_TEXTURE texture2D
 79#endif
 80
 81#ifdef GL_ES
 82#ifdef GL_FRAGMENT_PRECISION_HIGH
 83precision highp float;
 84#else
 85precision mediump float;
 86#endif
 87#define COMPAT_PRECISION mediump
 88#else
 89#define COMPAT_PRECISION
 90#endif
 91uniform sampler2D tex;
 92varying vec2 texCoord;
 93varying vec4 TEX1;
 94varying vec4 TEX2;
 95varying vec4 TEX3;
 96varying vec4 TEX4;
 97varying vec4 TEX5;
 98varying vec4 TEX6;
 99varying vec4 TEX7;
100
101uniform vec2 texSize;
102
103void main()
104{
105	bvec4 edr, edr_left, edr_up, edr3_left, edr3_up, px; // px = pixel, edr = edge detection rule
106	bvec4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up;
107	bvec4 interp_restriction_lv3_left, interp_restriction_lv3_up;
108	bvec4 nc, nc30, nc60, nc45, nc15, nc75; // new_color
109	vec4 fx, fx_left, fx_up, finalfx, fx3_left, fx3_up; // inequations of straight lines.
110	vec3 res1, res2, pix1, pix2;
111	float blend1, blend2;
112
113    vec2 fp = fract(texCoord * texSize);
114
115    vec3 A1 = COMPAT_TEXTURE(tex, TEX1.xw).rgb;
116    vec3 B1 = COMPAT_TEXTURE(tex, TEX1.yw).rgb;
117    vec3 C1 = COMPAT_TEXTURE(tex, TEX1.zw).rgb;
118
119    vec3 A = COMPAT_TEXTURE(tex, TEX2.xw).rgb;
120    vec3 B = COMPAT_TEXTURE(tex, TEX2.yw).rgb;
121    vec3 C = COMPAT_TEXTURE(tex, TEX2.zw).rgb;
122
123    vec3 D = COMPAT_TEXTURE(tex, TEX3.xw).rgb;
124    vec3 E = COMPAT_TEXTURE(tex, TEX3.yw).rgb;
125    vec3 F = COMPAT_TEXTURE(tex, TEX3.zw).rgb;
126
127    vec3 G = COMPAT_TEXTURE(tex, TEX4.xw).rgb;
128    vec3 H = COMPAT_TEXTURE(tex, TEX4.yw).rgb;
129    vec3 I = COMPAT_TEXTURE(tex, TEX4.zw).rgb;
130
131    vec3 G5 = COMPAT_TEXTURE(tex, TEX5.xw).rgb;
132    vec3 H5 = COMPAT_TEXTURE(tex, TEX5.yw).rgb;
133    vec3 I5 = COMPAT_TEXTURE(tex, TEX5.zw).rgb;
134
135    vec3 A0 = COMPAT_TEXTURE(tex, TEX6.xy).rgb;
136    vec3 D0 = COMPAT_TEXTURE(tex, TEX6.xz).rgb;
137    vec3 G0 = COMPAT_TEXTURE(tex, TEX6.xw).rgb;
138
139    vec3 C4 = COMPAT_TEXTURE(tex, TEX7.xy).rgb;
140    vec3 F4 = COMPAT_TEXTURE(tex, TEX7.xz).rgb;
141    vec3 I4 = COMPAT_TEXTURE(tex, TEX7.xw).rgb;
142
143	vec4 b = transpose(mat4x3(B, D, H, F)) * (XBR_Y_WEIGHT * yuv[0]);
144	vec4 c = transpose(mat4x3(C, A, G, I)) * (XBR_Y_WEIGHT * yuv[0]);
145	vec4 e = transpose(mat4x3(E, E, E, E)) * (XBR_Y_WEIGHT * yuv[0]);
146	vec4 d = b.yzwx;
147	vec4 f = b.wxyz;
148	vec4 g = c.zwxy;
149	vec4 h = b.zwxy;
150	vec4 i = c.wxyz;
151
152	vec4 i4 = transpose(mat4x3(I4, C1, A0, G5)) * (XBR_Y_WEIGHT*yuv[0]);
153	vec4 i5 = transpose(mat4x3(I5, C4, A1, G0)) * (XBR_Y_WEIGHT*yuv[0]);
154	vec4 h5 = transpose(mat4x3(H5, F4, B1, D0)) * (XBR_Y_WEIGHT*yuv[0]);
155	vec4 f4 = h5.yzwx;
156
157	vec4 c1 = i4.yzwx;
158	vec4 g0 = i5.wxyz;
159	vec4 b1 = h5.zwxy;
160	vec4 d0 = h5.wxyz;
161
162	vec4 Ao = vec4( 1.0, -1.0, -1.0, 1.0 );
163	vec4 Bo = vec4( 1.0,  1.0, -1.0,-1.0 );
164	vec4 Co = vec4( 1.5,  0.5, -0.5, 0.5 );
165	vec4 Ax = vec4( 1.0, -1.0, -1.0, 1.0 );
166	vec4 Bx = vec4( 0.5,  2.0, -0.5,-2.0 );
167	vec4 Cx = vec4( 1.0,  1.0, -0.5, 0.0 );
168	vec4 Ay = vec4( 1.0, -1.0, -1.0, 1.0 );
169	vec4 By = vec4( 2.0,  0.5, -2.0,-0.5 );
170	vec4 Cy = vec4( 2.0,  0.0, -1.0, 0.5 );
171
172	vec4 Az = vec4( 6.0, -2.0, -6.0, 2.0 );
173	vec4 Bz = vec4( 2.0, 6.0, -2.0, -6.0 );
174	vec4 Cz = vec4( 5.0, 3.0, -3.0, -1.0 );
175	vec4 Aw = vec4( 2.0, -6.0, -2.0, 6.0 );
176	vec4 Bw = vec4( 6.0, 2.0, -6.0,-2.0 );
177	vec4 Cw = vec4( 5.0, -1.0, -3.0, 3.0 );
178
179	fx      = (Ao*fp.y+Bo*fp.x); 
180	fx_left = (Ax*fp.y+Bx*fp.x);
181	fx_up   = (Ay*fp.y+By*fp.x);
182	fx3_left= (Az*fp.y+Bz*fp.x);
183	fx3_up  = (Aw*fp.y+Bw*fp.x);
184
185	// It uses CORNER_C if none of the others are defined.
186#ifdef CORNER_A
187	interp_restriction_lv1 = and(notEqual(e, f), notEqual(e, h));
188#elif defined(CORNER_B)
189	interp_restriction_lv1      = ((e!=f) && (e!=h)  &&  ( !eq(f,b) && !eq(h,d) || eq(e,i) && !eq(f,i4) && !eq(h,i5) || eq(e,g) || eq(e,c) ) );
190#elif defined(CORNER_D)
191	interp_restriction_lv1      = ((e!=f) && (e!=h)  &&  ( !eq(f,b) && !eq(h,d) || eq(e,i) && !eq(f,i4) && !eq(h,i5) || eq(e,g) || eq(e,c) ) && (f!=f4 && f!=i || h!=h5 && h!=i || h!=g || f!=c || eq(b,c1) && eq(d,g0)));
192#else
193	interp_restriction_lv1 = and(and(notEqual(e, f), notEqual(e, h)),
194	                             or(or(and(not(eq(f,b)), not(eq(f,c))),
195	                                   and(not(eq(h,d)), not(eq(h,g)))),
196	                                or(and(eq(e,i), or(and(not(eq(f,f4)), not(eq(f,i4))),
197	                                                   and(not(eq(h,h5)), not(eq(h,i5))))),
198	                                   or(eq(e,g), eq(e,c)))));
199#endif
200
201    interp_restriction_lv2_left = and(notEqual(e, g), notEqual(d, g));
202	interp_restriction_lv2_up   = and(notEqual(e, c), notEqual(b, c));
203	interp_restriction_lv3_left = and(eq2(g,g0), not(eq2(d0,g0)));
204	interp_restriction_lv3_up   = and(eq2(c,c1), not(eq2(b1,c1)));
205
206	vec4 fx45 = smoothstep(Co - delta, Co + delta, fx);
207	vec4 fx30 = smoothstep(Cx - delta, Cx + delta, fx_left);
208	vec4 fx60 = smoothstep(Cy - delta, Cy + delta, fx_up);
209	vec4 fx15 = smoothstep(Cz - delta, Cz + delta, fx3_left);
210	vec4 fx75 = smoothstep(Cw - delta, Cw + delta, fx3_up);
211
212	edr = and(lessThan(weighted_distance( e, c, g, i, h5, f4, h, f), weighted_distance( h, d, i5, f, i4, b, e, i)), interp_restriction_lv1);
213	edr_left = and(lessThanEqual((XBR_LV2_COEFFICIENT*df(f,g)), df(h,c)), interp_restriction_lv2_left);
214	edr_up   = and(greaterThanEqual(df(f,g), (XBR_LV2_COEFFICIENT*df(h,c))), interp_restriction_lv2_up);
215	edr3_left = interp_restriction_lv3_left;
216	edr3_up = interp_restriction_lv3_up;
217
218	nc45 = and(edr, bvec4(fx45));
219	nc30 = and(edr, and(edr_left, bvec4(fx30)));
220	nc60 = and(edr, and(edr_up, bvec4(fx60)));
221	nc15 = and(and(edr, edr_left), and(edr3_left, bvec4(fx15)));
222	nc75 = and(and(edr, edr_up), and(edr3_up, bvec4(fx75)));
223
224    px = lessThanEqual(df(e, f), df(e, h));
225
226    nc = bvec4(nc75.x || nc15.x || nc30.x || nc60.x || nc45.x, nc75.y || nc15.y || nc30.y || nc60.y || nc45.y, nc75.z || nc15.z || nc30.z || nc60.z || nc45.z, nc75.w || nc15.w || nc30.w || nc60.w || nc45.w);
227
228	vec4 final45 = vec4(nc45) * fx45;
229	vec4 final30 = vec4(nc30) * fx30;
230	vec4 final60 = vec4(nc60) * fx60;
231	vec4 final15 = vec4(nc15) * fx15;
232	vec4 final75 = vec4(nc75) * fx75;
233
234	vec4 maximo = max(max(max(final15, final75),max(final30, final60)), final45);
235
236	     if (nc.x) {pix1 = px.x ? F : H; blend1 = maximo.x;}
237	else if (nc.y) {pix1 = px.y ? B : F; blend1 = maximo.y;}
238	else if (nc.z) {pix1 = px.z ? D : B; blend1 = maximo.z;}
239	else if (nc.w) {pix1 = px.w ? H : D; blend1 = maximo.w;}
240
241	     if (nc.w) {pix2 = px.w ? H : D; blend2 = maximo.w;}
242	else if (nc.z) {pix2 = px.z ? D : B; blend2 = maximo.z;}
243	else if (nc.y) {pix2 = px.y ? B : F; blend2 = maximo.y;}
244	else if (nc.x) {pix2 = px.x ? F : H; blend2 = maximo.x;}
245
246    res1 = mix(E, pix1, blend1);
247    res2 = mix(E, pix2, blend2);
248    vec3 res = mix(res1, res2, step(c_df(E, res1), c_df(E, res2)));
249
250    FragColor = vec4(res, 1.0);
251}