Added SABR shader by Joshua Street.
[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    (The original Cg version of the xBR family of shaders is available on
27    Github: https://github.com/twinaphex/common-shaders/tree/master/xBR )
28 -->
29 <shader language="GLSL">
30   <vertex><![CDATA[
31     uniform vec2 rubyTextureSize;
32
33     void main() {
34       float x = 1.0 / rubyTextureSize.x;
35       float y = 1.0 / rubyTextureSize.y;
36
37       gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
38       gl_TexCoord[0] = gl_MultiTexCoord0;
39       gl_TexCoord[1].xy = vec2(x, 0.0);
40       gl_TexCoord[1].zw = vec2(0.0, y);
41     }
42   ]]></vertex>
43
44   <fragment filter="nearest"><![CDATA[
45     uniform sampler2D rubyTexture;
46     uniform vec2 rubyTextureSize;
47
48     // Inequations for interpolation
49     const vec4 A45 = vec4( 1.0, -1.0, -1.0,  1.0);
50     const vec4 B45 = vec4( 1.0,  1.0, -1.0, -1.0);
51     const vec4 C45 = vec4( 1.5,  0.5, -0.5,  0.5);
52     const vec4 A15 = vec4( 1.0, -1.0, -1.0,  1.0);
53     const vec4 B15 = vec4( 0.5,  2.0, -0.5, -2.0);
54     const vec4 C15 = vec4( 1.0,  1.0, -0.5,  0.0);
55     const vec4 A60 = vec4( 1.0, -1.0, -1.0,  1.0);
56     const vec4 B60 = vec4( 2.0,  0.5, -2.0, -0.5);
57     const vec4 C60 = vec4( 2.0,  0.0, -1.0,  0.5);
58
59     const vec4 S45 = vec4(0.2, 0.2, 0.2, 0.2);
60     const vec4 S15 = vec4(0.1, 0.2, 0.1, 0.2);
61     const vec4 S60 = vec4(0.2, 0.1, 0.2, 0.1);
62
63     const vec4 M45 = vec4(0.4, 0.4, 0.4, 0.4);
64     const vec4 M15 = vec4(0.2, 0.4, 0.2, 0.4);
65     const vec4 M60 = vec4(0.4, 0.2, 0.4, 0.2);
66     const vec4 shift = vec4(0.2);
67
68
69     const float coef = 2.0;
70     // Threshold for if luminance values are "equal"
71     const float threshold = 15.0;
72
73     const float lum_weight = 64.0;
74     // Conversion from RGB to Luminance
75     const vec3 lum = vec3(0.2126, 0.7152, 0.0722);
76     const vec3 lum_weighted = lum * lum_weight;
77
78     bvec4 _and_(bvec4 A, bvec4 B) {
79       return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w);
80     }
81
82     bvec4 _or_(bvec4 A, bvec4 B) {
83       return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w);
84     }
85
86     vec4 lum_to(vec3 v0, vec3 v1, vec3 v2, vec3 v3) {
87       return vec4(
88         dot(lum_weighted, v0),
89         dot(lum_weighted, v1),
90         dot(lum_weighted, v2),
91         dot(lum_weighted, v3)
92       );
93     }
94
95     float lum_df(float A, float B) {
96       return abs(A - B);
97     }
98
99     vec4 lum_df(vec4 A, vec4 B) {
100       return abs(A - B);
101     }
102
103     bvec4 lum_eq(vec4 A, vec4 B) {
104        return lessThan(lum_df(A, B), vec4(threshold));
105     }
106
107     vec4 lum_wd(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) {
108        return lum_df(a, b) + lum_df(a, c) + lum_df(d, e) + lum_df(d, f) + 4.0 * lum_df(g, h);
109     }
110
111     void main() {
112       vec2 fp = fract(gl_TexCoord[0].xy * rubyTextureSize);
113
114       vec2 dx = gl_TexCoord[1].xy;
115       vec2 dy = gl_TexCoord[1].zw;
116
117       vec3 P1  = texture2D(rubyTexture, gl_TexCoord[0].xy -       dx - 2.0 * dy).rgb;
118       vec3 P2  = texture2D(rubyTexture, gl_TexCoord[0].xy            - 2.0 * dy).rgb;
119       vec3 P3  = texture2D(rubyTexture, gl_TexCoord[0].xy +       dx - 2.0 * dy).rgb;
120       vec3 P5  = texture2D(rubyTexture, gl_TexCoord[0].xy - 2.0 * dx -       dy).rgb;
121       vec3 P6  = texture2D(rubyTexture, gl_TexCoord[0].xy -       dx -       dy).rgb;
122       vec3 P7  = texture2D(rubyTexture, gl_TexCoord[0].xy            -       dy).rgb;
123       vec3 P8  = texture2D(rubyTexture, gl_TexCoord[0].xy +       dx -       dy).rgb;
124       vec3 P9  = texture2D(rubyTexture, gl_TexCoord[0].xy + 2.0 * dx -       dy).rgb;
125       vec3 P10 = texture2D(rubyTexture, gl_TexCoord[0].xy - 2.0 * dx           ).rgb;
126       vec3 P11 = texture2D(rubyTexture, gl_TexCoord[0].xy -       dx           ).rgb;
127       vec3 P12 = texture2D(rubyTexture, gl_TexCoord[0].xy                      ).rgb;
128       vec3 P13 = texture2D(rubyTexture, gl_TexCoord[0].xy +       dx           ).rgb;
129       vec3 P14 = texture2D(rubyTexture, gl_TexCoord[0].xy + 2.0 * dx           ).rgb;
130       vec3 P15 = texture2D(rubyTexture, gl_TexCoord[0].xy - 2.0 * dx +       dy).rgb;
131       vec3 P16 = texture2D(rubyTexture, gl_TexCoord[0].xy -       dx +       dy).rgb;
132       vec3 P17 = texture2D(rubyTexture, gl_TexCoord[0].xy            +       dy).rgb;
133       vec3 P18 = texture2D(rubyTexture, gl_TexCoord[0].xy +       dx +       dy).rgb;
134       vec3 P19 = texture2D(rubyTexture, gl_TexCoord[0].xy + 2.0 * dx +       dy).rgb;
135       vec3 P21 = texture2D(rubyTexture, gl_TexCoord[0].xy -       dx + 2.0 * dy).rgb;
136       vec3 P22 = texture2D(rubyTexture, gl_TexCoord[0].xy            + 2.0 * dy).rgb;
137       vec3 P23 = texture2D(rubyTexture, gl_TexCoord[0].xy +       dx + 2.0 * dy).rgb;
138
139       vec4 p7  = lum_to(P7,  P11, P17, P13);
140       vec4 p8  = lum_to(P8,  P6,  P16, P18);
141       vec4 p11 = lum_to(P11, P17, P13, P7 );
142       vec4 p12 = lum_to(P12, P12, P12, P12);
143       vec4 p13 = lum_to(P13, P7,  P11, P17);
144       vec4 p14 = lum_to(P14, P2,  P10, P22);
145       vec4 p16 = lum_to(P16, P18, P8,  P6 );
146       vec4 p17 = lum_to(P17, P13, P7,  P11);
147       vec4 p18 = lum_to(P18, P8,  P6,  P16);
148       vec4 p19 = lum_to(P19, P3,  P5,  P21);
149       vec4 p22 = lum_to(P22, P14, P2,  P10);
150       vec4 p23 = lum_to(P23, P9,  P1,  P15);
151
152       vec4 t45   = vec4(A45 * fp.y + B45 * fp.x);
153       vec4 t15   = vec4(A15 * fp.y + B15 * fp.x);
154       vec4 t60   = vec4(A60 * fp.y + B60 * fp.x);
155
156       bvec4 fx45 = greaterThan(t45, C45 - S45);
157       bvec4 fx15 = greaterThan(t15, C15 - S15);
158       bvec4 fx60 = greaterThan(t60, C60 - S60);
159       bvec4 fxrn = greaterThan(t45, C45);
160
161       vec4 ma45 = smoothstep(C45 - M45, C45 + M45, t45);
162       vec4 ma15 = smoothstep(C15 - M15, C15 + M15, t15);
163       vec4 ma60 = smoothstep(C60 - M60, C60 + M60, t60);
164       vec4 marn = smoothstep(C45 - M45 + shift, C45 + M45 + shift, t45);
165
166       vec4 e45 = lum_wd(p12, p8, p16, p18, p22, p14, p17, p13);
167       vec4 econt = lum_wd(p17, p11, p23, p13, p7, p19, p12, p18);
168
169       bvec4 r45_1   = _and_(notEqual(p12, p13), notEqual(p12, p17));
170       bvec4 r45_2   = _and_(not(lum_eq(p13, p7)), not(lum_eq(p13, p8)));
171       bvec4 r45_3   = _and_(not(lum_eq(p17, p11)), not(lum_eq(p17, p16)));
172       bvec4 r45_4_1 = _and_(not(lum_eq(p13, p14)), not(lum_eq(p13, p19)));
173       bvec4 r45_4_2 = _and_(not(lum_eq(p17, p22)), not(lum_eq(p17, p23)));
174       bvec4 r45_4   = _and_(lum_eq(p12, p18), _or_(r45_4_1, r45_4_2));
175       bvec4 r45_5   = _or_(lum_eq(p12, p16), lum_eq(p12, p8));
176       bvec4 r45     = _and_(r45_1, _or_(_or_(_or_(r45_2, r45_3), r45_4), r45_5));
177
178       vec4 e15 = lum_df(p13, p16);
179       bvec4 r15 = _and_(notEqual(p12, p16), notEqual(p11, p16));
180
181       vec4 e60 = lum_df(p8, p17);
182       bvec4 r60 = _and_(notEqual(p12, p8), notEqual(p7, p8));
183
184       bvec4 edr45 = _and_(lessThan(e45, econt), r45);
185       bvec4 edr15 = _and_(edr45, _and_(lessThanEqual(coef * e15, e60), r15));
186       bvec4 edr60 = _and_(edr45, _and_(lessThanEqual(coef * e60, e15), r60));
187       bvec4 edrrn = lessThanEqual(e45, econt);
188
189       bvec4 px = lessThanEqual(lum_df(p12, p13), lum_df(p12, p17));
190
191       vec3 c;
192       vec3 res = P12;
193       if (any(edr45) || any(edrrn)) {
194         c = px.x ? P13 : P17;
195         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;
196         c = px.y ? P7 : P13;
197         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;
198         c = px.z ? P11 : P7;
199         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;
200         c = px.w ? P17 : P11;
201         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;
202       }
203
204       gl_FragColor.rgb = res;
205       gl_FragColor.a = 1.0;
206     }
207   ]]></fragment>
208 </shader>