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 `;