Update the SABR shader.
[bsnes:xml-shaders.git] / shaders / OpenGL / v1.0 / SABR.shader
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!--
3    SABR v1.0 Shader
4
5    Copyright (C) 2012 Joshua Street
6    Copyright (C) 2011, 2012 Hyllian/Jararaca - sergiogdb@gmail.com
7    Copyright (C) 2012 crazy46guy (GLSL conversion)
8
9    Portions of this algorithm were taken from Hyllian's 5xBR v3.7c
10    shader.
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    as published by the Free Software Foundation; either version 2
15    of the License, or (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26 -->
27 <shader language="GLSL">
28   <vertex><![CDATA[
29     uniform vec2 rubyTextureSize;
30
31     void main() {
32       float x = 1.0 / rubyTextureSize.x;
33       float y = 1.0 / rubyTextureSize.y;
34
35       gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
36       gl_TexCoord[0] = gl_MultiTexCoord0;
37       gl_TexCoord[1].xy = vec2(x, 0.0);
38       gl_TexCoord[1].zw = vec2(0.0, y);
39     }
40   ]]></vertex>
41
42   <fragment filter="nearest"><![CDATA[
43     uniform sampler2D rubyTexture;
44     uniform vec2 rubyTextureSize;
45
46     // Inequations for interpolation
47     const vec4 A45 = vec4( 1.0, -1.0, -1.0,  1.0);
48     const vec4 B45 = vec4( 1.0,  1.0, -1.0, -1.0);
49     const vec4 C45 = vec4( 1.5,  0.5, -0.5,  0.5);
50     const vec4 A15 = vec4( 1.0, -1.0, -1.0,  1.0);
51     const vec4 B15 = vec4( 0.5,  2.0, -0.5, -2.0);
52     const vec4 C15 = vec4( 1.0,  1.0, -0.5,  0.0);
53     const vec4 A60 = vec4( 1.0, -1.0, -1.0,  1.0);
54     const vec4 B60 = vec4( 2.0,  0.5, -2.0, -0.5);
55     const vec4 C60 = vec4( 2.0,  0.0, -1.0,  0.5);
56
57     const vec4 S45 = vec4(0.2, 0.2, 0.2, 0.2);
58     const vec4 S15 = vec4(0.1, 0.2, 0.1, 0.2);
59     const vec4 S60 = vec4(0.2, 0.1, 0.2, 0.1);
60
61     const vec4 M45 = vec4(0.4, 0.4, 0.4, 0.4);
62     const vec4 M15 = vec4(0.2, 0.4, 0.2, 0.4);
63     const vec4 M60 = vec4(0.4, 0.2, 0.4, 0.2);
64     const vec4 shift = vec4(0.2);
65
66
67     const float coef = 2.0;
68     // Threshold for if luminance values are "equal"
69     const float threshold = 20.0;
70
71     const float lum_weight = 48.0;
72     // Conversion from RGB to Luminance
73     const vec3 lum = vec3(0.2126, 0.7152, 0.0722);
74     const vec3 lum_weighted = lum * lum_weight;
75
76     bvec4 _and_(bvec4 A, bvec4 B) {
77       return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w);
78     }
79
80     bvec4 _or_(bvec4 A, bvec4 B) {
81       return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w);
82     }
83
84     vec4 lum_to(vec3 v0, vec3 v1, vec3 v2, vec3 v3) {
85       return vec4(
86         dot(lum_weighted, v0),
87         dot(lum_weighted, v1),
88         dot(lum_weighted, v2),
89         dot(lum_weighted, v3)
90       );
91     }
92
93     float lum_df(float A, float B) {
94       return abs(A - B);
95     }
96
97     vec4 lum_df(vec4 A, vec4 B) {
98       return abs(A - B);
99     }
100
101     bvec4 lum_eq(vec4 A, vec4 B) {
102       return lessThan(lum_df(A, B), vec4(threshold));
103     }
104
105     vec4 lum_wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) {
106       return lum_df(a, b) + lum_df(a, c) + lum_df(d, e) + lum_df(d, f) + 4.0 * lum_df(g, h);
107     }
108
109     void main() {
110       vec2 fp = fract(gl_TexCoord[0].xy * rubyTextureSize);
111
112       vec2 dx = gl_TexCoord[1].xy;
113       vec2 dy = gl_TexCoord[1].zw;
114
115       vec3 P1  = texture2D(rubyTexture, gl_TexCoord[0].xy -       dx - 2.0 * dy).rgb;
116       vec3 P2  = texture2D(rubyTexture, gl_TexCoord[0].xy            - 2.0 * dy).rgb;
117       vec3 P3  = texture2D(rubyTexture, gl_TexCoord[0].xy +       dx - 2.0 * dy).rgb;
118       vec3 P5  = texture2D(rubyTexture, gl_TexCoord[0].xy - 2.0 * dx -       dy).rgb;
119       vec3 P6  = texture2D(rubyTexture, gl_TexCoord[0].xy -       dx -       dy).rgb;
120       vec3 P7  = texture2D(rubyTexture, gl_TexCoord[0].xy            -       dy).rgb;
121       vec3 P8  = texture2D(rubyTexture, gl_TexCoord[0].xy +       dx -       dy).rgb;
122       vec3 P9  = texture2D(rubyTexture, gl_TexCoord[0].xy + 2.0 * dx -       dy).rgb;
123       vec3 P10 = texture2D(rubyTexture, gl_TexCoord[0].xy - 2.0 * dx           ).rgb;
124       vec3 P11 = texture2D(rubyTexture, gl_TexCoord[0].xy -       dx           ).rgb;
125       vec3 P12 = texture2D(rubyTexture, gl_TexCoord[0].xy                      ).rgb;
126       vec3 P13 = texture2D(rubyTexture, gl_TexCoord[0].xy +       dx           ).rgb;
127       vec3 P14 = texture2D(rubyTexture, gl_TexCoord[0].xy + 2.0 * dx           ).rgb;
128       vec3 P15 = texture2D(rubyTexture, gl_TexCoord[0].xy - 2.0 * dx +       dy).rgb;
129       vec3 P16 = texture2D(rubyTexture, gl_TexCoord[0].xy -       dx +       dy).rgb;
130       vec3 P17 = texture2D(rubyTexture, gl_TexCoord[0].xy            +       dy).rgb;
131       vec3 P18 = texture2D(rubyTexture, gl_TexCoord[0].xy +       dx +       dy).rgb;
132       vec3 P19 = texture2D(rubyTexture, gl_TexCoord[0].xy + 2.0 * dx +       dy).rgb;
133       vec3 P21 = texture2D(rubyTexture, gl_TexCoord[0].xy -       dx + 2.0 * dy).rgb;
134       vec3 P22 = texture2D(rubyTexture, gl_TexCoord[0].xy            + 2.0 * dy).rgb;
135       vec3 P23 = texture2D(rubyTexture, gl_TexCoord[0].xy +       dx + 2.0 * dy).rgb;
136
137       vec4 p7  = lum_to(P7,  P11, P17, P13);
138       vec4 p8  = lum_to(P8,  P6,  P16, P18);
139       vec4 p11 = lum_to(P11, P17, P13, P7 );
140       vec4 p12 = lum_to(P12, P12, P12, P12);
141       vec4 p13 = lum_to(P13, P7,  P11, P17);
142       vec4 p14 = lum_to(P14, P2,  P10, P22);
143       vec4 p16 = lum_to(P16, P18, P8,  P6 );
144       vec4 p17 = lum_to(P17, P13, P7,  P11);
145       vec4 p18 = lum_to(P18, P8,  P6,  P16);
146       vec4 p19 = lum_to(P19, P3,  P5,  P21);
147       vec4 p22 = lum_to(P22, P14, P2,  P10);
148       vec4 p23 = lum_to(P23, P9,  P1,  P15);
149
150       vec4 t45   = vec4(A45 * fp.y + B45 * fp.x);
151       vec4 t15   = vec4(A15 * fp.y + B15 * fp.x);
152       vec4 t60   = vec4(A60 * fp.y + B60 * fp.x);
153
154       bvec4 fx45 = greaterThan(t45, C45 - S45);
155       bvec4 fx15 = greaterThan(t15, C15 - S15);
156       bvec4 fx60 = greaterThan(t60, C60 - S60);
157       bvec4 fxrn = greaterThan(t45, C45);
158
159       vec4 ma45 = smoothstep(C45 - M45, C45 + M45, t45);
160       vec4 ma15 = smoothstep(C15 - M15, C15 + M15, t15);
161       vec4 ma60 = smoothstep(C60 - M60, C60 + M60, t60);
162       vec4 marn = smoothstep(C45 - M45 + shift, C45 + M45 + shift, t45);
163
164       vec4 e45 = lum_wd(p12, p8, p16, p18, p22, p14, p17, p13);
165       vec4 econt = lum_wd(p17, p11, p23, p13, p7, p19, p12, p18);
166
167       bvec4 r45_1   = _and_(notEqual(p12, p13), notEqual(p12, p17));
168       bvec4 r45_2   = _and_(not(lum_eq(p13, p7)), not(lum_eq(p13, p8)));
169       bvec4 r45_3   = _and_(not(lum_eq(p17, p11)), not(lum_eq(p17, p16)));
170       bvec4 r45_4_1 = _and_(not(lum_eq(p13, p14)), not(lum_eq(p13, p19)));
171       bvec4 r45_4_2 = _and_(not(lum_eq(p17, p22)), not(lum_eq(p17, p23)));
172       bvec4 r45_4   = _and_(lum_eq(p12, p18), _or_(r45_4_1, r45_4_2));
173       bvec4 r45_5   = _or_(lum_eq(p12, p16), lum_eq(p12, p8));
174       bvec4 r45     = _and_(r45_1, _or_(_or_(_or_(r45_2, r45_3), r45_4), r45_5));
175
176       vec4 e15 = lum_df(p13, p16);
177       bvec4 r15 = _and_(notEqual(p12, p16), notEqual(p11, p16));
178
179       vec4 e60 = lum_df(p8, p17);
180       bvec4 r60 = _and_(notEqual(p12, p8), notEqual(p7, p8));
181
182       bvec4 edr45 = _and_(lessThan(e45, econt), r45);
183       bvec4 edr15 = _and_(edr45, _and_(lessThanEqual(coef * e15, e60), r15));
184       bvec4 edr60 = _and_(edr45, _and_(lessThanEqual(coef * e60, e15), r60));
185       bvec4 edrrn = lessThanEqual(e45, econt);
186
187       bvec4 px = lessThanEqual(lum_df(p12, p13), lum_df(p12, p17));
188
189       vec3 c;
190       vec3 res = P12;
191       if (any(edr45) || any(edrrn)) {
192         c = px.x ? P13 : P17;
193         res = edr15.x && fx15.x ? mix(res, c, ma15.x) : edr60.x && fx60.x ? mix(res, c, ma60.x) : edr45.x && fx45.x ? mix(res, c, ma45.x) : edrrn.x && fxrn.x ? mix(res, c, marn.x) : res;
194         c = px.y ? P7 : P13;
195         res = edr15.y && fx15.y ? mix(res, c, ma15.y) : edr60.y && fx60.y ? mix(res, c, ma60.y) : edr45.y && fx45.y ? mix(res, c, ma45.y) : edrrn.y && fxrn.y ? mix(res, c, marn.y) : res;
196         c = px.z ? P11 : P7;
197         res = edr15.z && fx15.z ? mix(res, c, ma15.z) : edr60.z && fx60.z ? mix(res, c, ma60.z) : edr45.z && fx45.z ? mix(res, c, ma45.z) : edrrn.z && fxrn.z ? mix(res, c, marn.z) : res;
198         c = px.w ? P17 : P11;
199         res = edr15.w && fx15.w ? mix(res, c, ma15.w) : edr60.w && fx60.w ? mix(res, c, ma60.w) : edr45.w && fx45.w ? mix(res, c, ma45.w) : edrrn.w && fxrn.w ? mix(res, c, marn.w) : res;
200       }
201
202       gl_FragColor.rgb = res;
203       gl_FragColor.a = 1.0;
204     }
205   ]]></fragment>
206 </shader>