1 module gbaid.render.shader;
2 
3 public enum string TEXTURE_POST_PROCESS_VERTEX_SHADER_SOURCE =
4 `
5 // $shader_type: vertex
6 
7 // $attrib_layout: position = 0
8 
9 #version 120
10 
11 attribute vec3 position;
12 
13 varying vec2 textureCoords;
14 
15 void main() {
16     textureCoords = (position.xy + 1) / 2;
17     gl_Position = vec4(position, 1);
18 }
19 `;
20 
21 public enum string WINDOW_OUTPUT_FRAGMENT_SHADER_SOURCE =
22 `
23 // $shader_type: fragment
24 
25 // $texture_layout: color = 0
26 
27 #version 120
28 
29 varying vec2 textureCoords;
30 
31 uniform sampler2D color;
32 uniform vec2 inputSize;
33 uniform vec2 outputSize;
34 
35 void main() {
36     float inputRatio = inputSize.x / inputSize.y;
37     float outputRatio = outputSize.x / outputSize.y;
38 
39     vec2 sampleCoords = textureCoords;
40     if (inputRatio < outputRatio) {
41         sampleCoords.x *= outputRatio / inputRatio;
42         sampleCoords.x += (inputRatio - outputRatio) / (2 * inputRatio);
43     } else {
44         sampleCoords.y *= inputRatio / outputRatio;
45         sampleCoords.y += (outputRatio - inputRatio) / (2 * outputRatio);
46     }
47 
48     sampleCoords.y = 1 - sampleCoords.y;
49 
50     gl_FragColor = vec4(texture2D(color, sampleCoords).rgb, 1);
51 }
52 `;
53 
54 public enum string EPX_UPSCALE_FRAGMENT_SHADER_SOURCE =
55 `
56 // $shader_type: fragment
57 
58 // $texture_layout: color = 0
59 
60 #version 120
61 
62 const float EPS = 1e-5;
63 
64 varying vec2 textureCoords;
65 
66 uniform sampler2D color;
67 uniform vec2 size;
68 
69 bool eq(vec3 a, vec3 b) {
70     vec3 d = a - b;
71     return dot(d, d) < EPS;
72 }
73 
74 bool neq(vec3 a, vec3 b) {
75     return !eq(a, b);
76 }
77 
78 void main() {
79     float sx = 1 / size.x;
80     float sy = 1 / size.y;
81 
82     vec2 dx = vec2(sx, 0);
83     vec2 dy = vec2(0, sy);
84 
85     vec2 fp = fract(textureCoords * size);
86 
87     vec3 p = texture2D(color, textureCoords).rgb;
88     vec3 a = texture2D(color, textureCoords + dy).rgb;
89     vec3 b = texture2D(color, textureCoords + dx).rgb;
90     vec3 c = texture2D(color, textureCoords - dx).rgb;
91     vec3 d = texture2D(color, textureCoords - dy).rgb;
92 
93     if (fp.x >= 0.5) {
94         if (fp.y >= 0.5) {
95             if (eq(a, b) && neq(a, c) && neq(b, d)) {
96                 gl_FragColor.rgb = b;
97             } else {
98                 gl_FragColor.rgb = p;
99             }
100         } else {
101             if (eq(b, d) && neq(b, a) && neq(d, c)) {
102                 gl_FragColor.rgb = d;
103             } else {
104                 gl_FragColor.rgb = p;
105             }
106         }
107     } else {
108         if (fp.y >= 0.5) {
109             if (eq(c, a) && neq(c, d) && neq(a, b)) {
110                 gl_FragColor.rgb = a;
111             } else {
112                 gl_FragColor.rgb = p;
113             }
114         } else {
115             if (eq(d, c) && neq(d, b) && neq(c, a)) {
116                 gl_FragColor.rgb = c;
117             } else {
118                 gl_FragColor.rgb = p;
119             }
120         }
121     }
122 }
123 `;
124 
125 public enum string XBR_UPSCALE_FRAGMENT_SHADER_SOURCE =
126 `
127 // Based on code from: http://filthypants.blogspot.ca/2012/03/xbr-vs-hqx-interpolation-filter.html
128 
129 // $shader_type: fragment
130 
131 // $texture_layout: color = 0
132 
133 #version 120
134 
135 const float coefficient = 2;
136 
137 const float threshold = 15;
138 
139 const vec3 colorWeights = 48 * vec3(0.299, 0.587, 0.114);
140 
141 const vec4 Ao = vec4(1.0, -1.0, -1.0,  1.0);
142 const vec4 Bo = vec4(1.0,  1.0, -1.0, -1.0);
143 const vec4 Co = vec4(1.5,  0.5, -0.5,  0.5);
144 const vec4 Ax = vec4(1.0, -1.0, -1.0,  1.0);
145 const vec4 Bx = vec4(0.5,  2.0, -0.5, -2.0);
146 const vec4 Cx = vec4(1.0,  1.0, -0.5,  0.0);
147 const vec4 Ay = vec4(1.0, -1.0, -1.0,  1.0);
148 const vec4 By = vec4(2.0,  0.5, -2.0, -0.5);
149 const vec4 Cy = vec4(2.0,  0.0, -1.0,  0.5);
150 
151 varying vec2 textureCoords;
152 
153 uniform sampler2D color;
154 uniform vec2 size;
155 
156 vec4 weightedBlend(vec3 v0, vec3 v1, vec3 v2, vec3 v3) {
157     return vec4(dot(colorWeights, v0), dot(colorWeights, v1), dot(colorWeights, v2), dot(colorWeights, v3));
158 }
159 
160 bvec4 andAll(bvec4 A, bvec4 B) {
161     return bvec4(A.x && B.x, A.y && B.y, A.z && B.z, A.w && B.w);
162 }
163 
164 bvec4 orAll(bvec4 A, bvec4 B) {
165     return bvec4(A.x || B.x, A.y || B.y, A.z || B.z, A.w || B.w);
166 }
167 
168 vec4 absDiff(vec4 A, vec4 B) {
169     return abs(A - B);
170 }
171 
172 bvec4 equalEps(vec4 A, vec4 B) {
173     return lessThan(absDiff(A, B), vec4(threshold));
174 }
175 
176 vec4 weightedDistance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h) {
177     return absDiff(a, b) + absDiff(a, c) + absDiff(d, e) + absDiff(d, f) + 4.0 * absDiff(g, h);
178 }
179 
180 void main() {
181     float sx = 1 / size.x;
182     float sy = 1 / size.y;
183 
184     vec2 dx = vec2(sx, 0);
185     vec2 dy = vec2(0, sy);
186 
187     vec2 fp = fract(textureCoords * size);
188 
189     vec3 A1 = texture2D(color, textureCoords - dx - 2 * dy).rgb;
190     vec3 B1 = texture2D(color, textureCoords - 2 * dy).rgb;
191     vec3 C1 = texture2D(color, textureCoords + dx - 2 * dy).rgb;
192 
193     vec3 A  = texture2D(color, textureCoords - dx - dy).rgb;
194     vec3 B  = texture2D(color, textureCoords - dy).rgb;
195     vec3 C  = texture2D(color, textureCoords + dx - dy).rgb;
196 
197     vec3 D  = texture2D(color, textureCoords - dx).rgb;
198     vec3 E  = texture2D(color, textureCoords).rgb;
199     vec3 F  = texture2D(color, textureCoords + dx).rgb;
200 
201     vec3 G  = texture2D(color, textureCoords - dx + dy).rgb;
202     vec3 H  = texture2D(color, textureCoords + dy).rgb;
203     vec3 I  = texture2D(color, textureCoords + dx + dy).rgb;
204 
205     vec3 G5 = texture2D(color, textureCoords - dx + 2 * dy).rgb;
206     vec3 H5 = texture2D(color, textureCoords + 2 * dy).rgb;
207     vec3 I5 = texture2D(color, textureCoords + dx + 2 * dy).rgb;
208 
209     vec3 A0 = texture2D(color, textureCoords - 2 * dx - dy).rgb;
210     vec3 D0 = texture2D(color, textureCoords - 2 * dx).rgb;
211     vec3 G0 = texture2D(color, textureCoords - 2 * dx + dy).rgb;
212 
213     vec3 C4 = texture2D(color, textureCoords + 2 * dx - dy).rgb;
214     vec3 F4 = texture2D(color, textureCoords + 2 * dx).rgb;
215     vec3 I4 = texture2D(color, textureCoords + 2 * dx + dy).rgb;
216 
217     vec4 b = weightedBlend(B, D, H, F);
218     vec4 c = weightedBlend(C, A, G, I);
219     vec4 e = weightedBlend(E, E, E, E);
220     vec4 d = b.yzwx;
221     vec4 f = b.wxyz;
222     vec4 g = c.zwxy;
223     vec4 h = b.zwxy;
224     vec4 i = c.wxyz;
225 
226     vec4 i4 = weightedBlend(I4, C1, A0, G5);
227     vec4 i5 = weightedBlend(I5, C4, A1, G0);
228     vec4 h5 = weightedBlend(H5, F4, B1, D0);
229     vec4 f4 = h5.yzwx;
230 
231     bvec4 fx = greaterThan(Ao * fp.y + Bo * fp.x, Co);
232     bvec4 fxLeft = greaterThan(Ax * fp.y + Bx * fp.x, Cx);
233     bvec4 fxUP = greaterThan(Ay * fp.y + By * fp.x, Cy);
234 
235     bvec4 t1 = andAll(notEqual(e, f), notEqual(e, h));
236     bvec4 t2 = andAll(not(equalEps(f, b)), not(equalEps(h, d)));
237     bvec4 t3 = andAll(andAll(equalEps(e, i), not(equalEps(f, i4))), not(equalEps(h, i5)));
238     bvec4 t4 = orAll(equalEps(e, g), equalEps(e, c));
239     bvec4 interpRestriction1 = andAll(t1, orAll(orAll(t2, t3), t4));
240 
241     bvec4 interpRestriction2Left = andAll(notEqual(e, g), notEqual(d, g));
242     bvec4 interpRestriction2Up = andAll(notEqual(e, c), notEqual(b, c));
243 
244     bvec4 edr = andAll(lessThan(weightedDistance(e, c, g, i, h5, f4, h, f), weightedDistance(h, d, i5, f, i4, b, e, i)), interpRestriction1);
245     bvec4 edrLeft = andAll(lessThanEqual(coefficient * absDiff(f, g), absDiff(h, c)), interpRestriction2Left);
246     bvec4 edrUp = andAll(greaterThanEqual(absDiff(f, g), coefficient * absDiff(h, c)), interpRestriction2Up);
247 
248     bvec4 nc = andAll(edr, orAll(orAll(fx, andAll(edrLeft, fxLeft)), andAll(edrUp, fxUP)));
249 
250     bvec4 px = lessThanEqual(absDiff(e, f), absDiff(e, h));
251 
252     gl_FragColor.rgb =
253         nc.x
254             ? px.x
255                 ? F
256                 : H
257             : nc.y
258                 ? px.y
259                     ? B
260                     : F
261                 : nc.z
262                     ? px.z
263                         ? D
264                         : B
265                     : nc.w
266                         ? px.w
267                             ? H
268                             : D
269                         : E;
270 }
271 `;
272 
273 public enum string BICUBIC_UPSCALE_FRAGMENT_SHADER_SOURCE =
274 `
275 // See: http://www.paulinternet.nl/?page=bicubic
276 
277 // $shader_type: fragment
278 
279 // $texture_layout: color = 0
280 
281 #version 120
282 
283 varying vec2 textureCoords;
284 
285 uniform sampler2D color;
286 uniform vec2 size;
287 
288 vec4 cubic(vec4 s0, vec4 s1, vec4 s2, vec4 s3, float p) {
289     return s1 + 0.5 * p * (s2 - s0 + p * (2 * s0 - 5 * s1 + 4 * s2 - s3 + p * (3 * (s1 - s2) + s3 - s0)));
290 }
291 
292 void main() {
293     float sx = 1 / size.x;
294     float sy = 1 / size.y;
295 
296     vec2 dx = vec2(sx, 0);
297     vec2 dy = vec2(0, sy);
298 
299     vec4 s00 = texture2D(color, textureCoords - dx - dy);
300     vec4 s01 = texture2D(color, textureCoords - dy);
301     vec4 s02 = texture2D(color, textureCoords + dx - dy);
302     vec4 s03 = texture2D(color, textureCoords + 2 * dx - dy);
303 
304     vec4 s10 = texture2D(color, textureCoords - dx);
305     vec4 s11 = texture2D(color, textureCoords);
306     vec4 s12 = texture2D(color, textureCoords + dx);
307     vec4 s13 = texture2D(color, textureCoords + 2 * dx);
308 
309     vec4 s20 = texture2D(color, textureCoords - dx + dy);
310     vec4 s21 = texture2D(color, textureCoords + dy);
311     vec4 s22 = texture2D(color, textureCoords + dx + dy);
312     vec4 s23 = texture2D(color, textureCoords + 2 * dx + dy);
313 
314     vec4 s30 = texture2D(color, textureCoords - dx + 2 * dy);
315     vec4 s31 = texture2D(color, textureCoords + 2 * dy);
316     vec4 s32 = texture2D(color, textureCoords + dx + 2 * dy);
317     vec4 s33 = texture2D(color, textureCoords + 2 * dx + 2 * dy);
318 
319     vec2 fp = fract(textureCoords * size);
320 
321     vec4 c0 = cubic(s00, s10, s20, s30, fp.y);
322     vec4 c1 = cubic(s01, s11, s21, s31, fp.y);
323     vec4 c2 = cubic(s02, s12, s22, s32, fp.y);
324     vec4 c3 = cubic(s03, s13, s23, s33, fp.y);
325 
326     gl_FragColor = cubic(c0, c1, c2, c3, fp.x);
327 }
328 `;