1 <?xml version="1.0" encoding="UTF-8"?>
5 Copyright (C) 2012 Joshua Street
6 Copyright (C) 2011, 2012 Hyllian/Jararaca - sergiogdb@gmail.com
7 Copyright (C) 2012 crazy46guy (GLSL conversion)
9 Portions of this algorithm were taken from Hyllian's 5xBR v3.7c
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.
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.
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.
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 )
29 <shader language="GLSL">
31 uniform vec2 rubyTextureSize;
34 float x = 1.0 / rubyTextureSize.x;
35 float y = 1.0 / rubyTextureSize.y;
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);
44 <fragment filter="nearest"><![CDATA[
45 uniform sampler2D rubyTexture;
46 uniform vec2 rubyTextureSize;
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);
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);
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);
69 const float coef = 2.0;
70 // Threshold for if luminance values are "equal"
71 const float threshold = 15.0;
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;
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);
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);
86 vec4 lum_to(vec3 v0, vec3 v1, vec3 v2, vec3 v3) {
88 dot(lum_weighted, v0),
89 dot(lum_weighted, v1),
90 dot(lum_weighted, v2),
95 float lum_df(float A, float B) {
99 vec4 lum_df(vec4 A, vec4 B) {
103 bvec4 lum_eq(vec4 A, vec4 B) {
104 return lessThan(lum_df(A, B), vec4(threshold));
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);
112 vec2 fp = fract(gl_TexCoord[0].xy * rubyTextureSize);
114 vec2 dx = gl_TexCoord[1].xy;
115 vec2 dy = gl_TexCoord[1].zw;
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;
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);
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);
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);
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);
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);
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));
178 vec4 e15 = lum_df(p13, p16);
179 bvec4 r15 = _and_(notEqual(p12, p16), notEqual(p11, p16));
181 vec4 e60 = lum_df(p8, p17);
182 bvec4 r60 = _and_(notEqual(p12, p8), notEqual(p7, p8));
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);
189 bvec4 px = lessThanEqual(lum_df(p12, p13), lum_df(p12, p17));
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;
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;
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;
204 gl_FragColor.rgb = res;
205 gl_FragColor.a = 1.0;