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}