1// OmniScale-Legacy 2// by Lior Halphon 3// ported to RetroArch's glsl format by hunterk 4 5/* 6MIT License 7 8Copyright (c) 2015-2016 Lior Halphon 9 10Permission is hereby granted, free of charge, to any person obtaining a copy 11of this software and associated documentation files (the "Software"), to deal 12in the Software without restriction, including without limitation the rights 13to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14copies of the Software, and to permit persons to whom the Software is 15furnished to do so, subject to the following conditions: 16 17The above copyright notice and this permission notice shall be included in all 18copies or substantial portions of the Software. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26SOFTWARE. 27*/ 28 29#if defined(VERTEX) 30 31#if __VERSION__ >= 130 32#define COMPAT_VARYING out 33#define COMPAT_ATTRIBUTE in 34#define COMPAT_TEXTURE texture 35#else 36#define COMPAT_VARYING varying 37#define COMPAT_ATTRIBUTE attribute 38#define COMPAT_TEXTURE texture2D 39#endif 40 41#ifdef GL_ES 42#define COMPAT_PRECISION mediump 43#else 44#define COMPAT_PRECISION 45#endif 46 47COMPAT_ATTRIBUTE vec4 VertexCoord; 48COMPAT_ATTRIBUTE vec4 COLOR; 49COMPAT_ATTRIBUTE vec4 TexCoord; 50COMPAT_VARYING vec4 COL0; 51COMPAT_VARYING vec4 TEX0; 52 53uniform mat4 MVPMatrix; 54uniform COMPAT_PRECISION int FrameDirection; 55uniform COMPAT_PRECISION int FrameCount; 56uniform COMPAT_PRECISION vec2 OutputSize; 57uniform COMPAT_PRECISION vec2 TextureSize; 58uniform COMPAT_PRECISION vec2 InputSize; 59 60// vertex compatibility #defines 61#define vTexCoord TEX0.xy 62#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize 63#define outsize vec4(OutputSize, 1.0 / OutputSize) 64 65void main() 66{ 67 gl_Position = MVPMatrix * VertexCoord; 68 COL0 = COLOR; 69 TEX0.xy = TexCoord.xy; 70} 71 72#elif defined(FRAGMENT) 73 74#if __VERSION__ >= 130 75#define COMPAT_VARYING in 76#define COMPAT_TEXTURE texture 77out vec4 FragColor; 78#else 79#define COMPAT_VARYING varying 80#define FragColor gl_FragColor 81#define COMPAT_TEXTURE texture2D 82#endif 83 84#ifdef GL_ES 85#ifdef GL_FRAGMENT_PRECISION_HIGH 86precision highp float; 87#else 88precision mediump float; 89precision mediump int; 90#endif 91#define COMPAT_PRECISION mediump 92#else 93#define COMPAT_PRECISION 94#endif 95 96uniform COMPAT_PRECISION int FrameDirection; 97uniform COMPAT_PRECISION int FrameCount; 98uniform COMPAT_PRECISION vec2 OutputSize; 99uniform COMPAT_PRECISION vec2 TextureSize; 100uniform COMPAT_PRECISION vec2 InputSize; 101uniform sampler2D Texture; 102COMPAT_VARYING vec4 TEX0; 103 104// fragment compatibility #defines 105#define Source Texture 106#define vTexCoord TEX0.xy 107 108#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize 109#define outsize vec4(OutputSize, 1.0 / OutputSize) 110 111float quickDistance(vec4 a, vec4 b) 112{ 113 return abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z); 114} 115 116#define uResolution outsize.xy 117#define textureDimensions SourceSize.xy 118 119vec4 omniScale(sampler2D image, vec2 texCoord) 120{ 121 vec2 pixel = texCoord * textureDimensions - vec2(0.5, 0.5); 122 123 vec4 q11 = COMPAT_TEXTURE(image, vec2(floor(pixel.x) / textureDimensions.x, floor(pixel.y) / textureDimensions.y+0.001)); 124 vec4 q12 = COMPAT_TEXTURE(image, vec2(floor(pixel.x) / textureDimensions.x, ceil(pixel.y) / textureDimensions.y+0.001)); 125 vec4 q21 = COMPAT_TEXTURE(image, vec2(ceil(pixel.x) / textureDimensions.x, floor(pixel.y) / textureDimensions.y+0.001)); 126 vec4 q22 = COMPAT_TEXTURE(image, vec2(ceil(pixel.x) / textureDimensions.x, ceil(pixel.y) / textureDimensions.y+0.001)); 127 128 vec2 pos = fract(pixel); 129 130 /* Special handling for diaonals */ 131 bool hasDownDiagonal = false; 132 bool hasUpDiagonal = false; 133 if (q12 == q21 && q11 != q22) hasUpDiagonal = true; 134 else if (q12 != q21 && q11 == q22) hasDownDiagonal = true; 135 else if (q12 == q21 && q11 == q22) { 136 if (q11 == q12) return q11; 137 int diagonalBias = 0; 138 #ifdef GL_ES // unroll the loops 139 vec4 color; 140 // y = -1.0 141 // x = -1.0 142 color = COMPAT_TEXTURE(image, (pixel + vec2(-1.0, -1.0)) / textureDimensions); 143 if (color == q11) diagonalBias = diagonalBias + 1; 144 if (color == q12) diagonalBias = diagonalBias - 1; 145 146 // y = 0.0 147 // x = -1.0 148 color = COMPAT_TEXTURE(image, (pixel + vec2(-1.0, 0.0)) / textureDimensions); 149 if (color == q11) diagonalBias = diagonalBias + 1; 150 if (color == q12) diagonalBias = diagonalBias - 1; 151 152 // y = 1.0 153 // x = -1.0 154 color = COMPAT_TEXTURE(image, (pixel + vec2(-1.0, 1.0)) / textureDimensions); 155 if (color == q11) diagonalBias = diagonalBias + 1; 156 if (color == q12) diagonalBias = diagonalBias - 1; 157 158 // y = 2.0 159 // x = -1.0 160 color = COMPAT_TEXTURE(image, (pixel + vec2(-1.0, 2.0)) / textureDimensions); 161 if (color == q11) diagonalBias = diagonalBias + 1; 162 if (color == q12) diagonalBias = diagonalBias - 1; 163 164 // y = -1.0 165 // x = 0.0 166 color = COMPAT_TEXTURE(image, (pixel + vec2(0.0, -1.0)) / textureDimensions); 167 if (color == q11) diagonalBias = diagonalBias + 1; 168 if (color == q12) diagonalBias = diagonalBias - 1; 169 170 // y = 0.0 171 // x = 0.0 172 color = COMPAT_TEXTURE(image, (pixel + vec2(0.0, 0.0)) / textureDimensions); 173 if (color == q11) diagonalBias = diagonalBias + 1; 174 if (color == q12) diagonalBias = diagonalBias - 1; 175 176 // y = 1.0 177 // x = 0.0 178 color = COMPAT_TEXTURE(image, (pixel + vec2(0.0, 1.0)) / textureDimensions); 179 if (color == q11) diagonalBias = diagonalBias + 1; 180 if (color == q12) diagonalBias = diagonalBias - 1; 181 182 // y = 2.0 183 // x = 0.0 184 color = COMPAT_TEXTURE(image, (pixel + vec2(0.0, 2.0)) / textureDimensions); 185 if (color == q11) diagonalBias = diagonalBias + 1; 186 if (color == q12) diagonalBias = diagonalBias - 1; 187 188 // y = -1.0 189 // x = 1.0 190 color = COMPAT_TEXTURE(image, (pixel + vec2(1.0, -1.0)) / textureDimensions); 191 if (color == q11) diagonalBias = diagonalBias + 1; 192 if (color == q12) diagonalBias = diagonalBias - 1; 193 194 // y = 0.0 195 // x = 1.0 196 color = COMPAT_TEXTURE(image, (pixel + vec2(1.0, 0.0)) / textureDimensions); 197 if (color == q11) diagonalBias = diagonalBias + 1; 198 if (color == q12) diagonalBias = diagonalBias - 1; 199 200 // y = 1.0 201 // x = 1.0 202 color = COMPAT_TEXTURE(image, (pixel + vec2(1.0, 1.0)) / textureDimensions); 203 if (color == q11) diagonalBias = diagonalBias + 1; 204 if (color == q12) diagonalBias = diagonalBias - 1; 205 206 // y = 2.0 207 // x = 1.0 208 color = COMPAT_TEXTURE(image, (pixel + vec2(1.0, 2.0)) / textureDimensions); 209 if (color == q11) diagonalBias = diagonalBias + 1; 210 if (color == q12) diagonalBias = diagonalBias - 1; 211 212 // y = -1.0 213 // x = 2.0 214 color = COMPAT_TEXTURE(image, (pixel + vec2(0.0, -1.0)) / textureDimensions); 215 if (color == q11) diagonalBias = diagonalBias + 1; 216 if (color == q12) diagonalBias = diagonalBias - 1; 217 218 // y = 0.0 219 // x = 2.0 220 color = COMPAT_TEXTURE(image, (pixel + vec2(0.0, 0.0)) / textureDimensions); 221 if (color == q11) diagonalBias = diagonalBias + 1; 222 if (color == q12) diagonalBias = diagonalBias - 1; 223 224 // y = 1.0 225 // x = 2.0 226 color = COMPAT_TEXTURE(image, (pixel + vec2(0.0, 1.0)) / textureDimensions); 227 if (color == q11) diagonalBias = diagonalBias + 1; 228 if (color == q12) diagonalBias = diagonalBias - 1; 229 230 // y = 2.0 231 // x = 2.0 232 color = COMPAT_TEXTURE(image, (pixel + vec2(0.0, 2.0)) / textureDimensions); 233 if (color == q11) diagonalBias = diagonalBias + 1; 234 if (color == q12) diagonalBias = diagonalBias - 1; 235 #else 236 for (float y = -1.0; y < 3.0; y++) { 237 for (float x = -1.0; x < 3.0; x++) { 238 vec4 color = COMPAT_TEXTURE(image, (pixel + vec2(x, y)) / textureDimensions); 239 if (color == q11) diagonalBias++; 240 if (color == q12) diagonalBias--; 241 } 242 } 243 #endif 244 if (diagonalBias <= 0) { 245 hasDownDiagonal = true; 246 } 247 if (diagonalBias >= 0) { 248 hasUpDiagonal = true; 249 } 250 } 251 252 if (hasUpDiagonal || hasDownDiagonal) { 253 vec4 downDiagonalResult, upDiagonalResult; 254 255 if (hasUpDiagonal) { 256 float diagonalPos = pos.x + pos.y; 257 258 if (diagonalPos < 0.5) { 259 upDiagonalResult = q11; 260 } 261 else if (diagonalPos > 1.5) { 262 upDiagonalResult = q22; 263 } 264 else { 265 upDiagonalResult = q12; 266 } 267 } 268 269 if (hasDownDiagonal) { 270 float diagonalPos = 1.0 - pos.x + pos.y; 271 272 if (diagonalPos < 0.5) { 273 downDiagonalResult = q21; 274 } 275 else if (diagonalPos > 1.5) { 276 downDiagonalResult = q12; 277 } 278 else { 279 downDiagonalResult = q11; 280 } 281 } 282 283 if (!hasUpDiagonal) return downDiagonalResult; 284 if (!hasDownDiagonal) return upDiagonalResult; 285 return mix(downDiagonalResult, upDiagonalResult, 0.5); 286 } 287 288 vec4 r1 = mix(q11, q21, fract(pos.x)); 289 vec4 r2 = mix(q12, q22, fract(pos.x)); 290 291 vec4 unquantized = mix(r1, r2, fract(pos.y)); 292 293 float q11d = quickDistance(unquantized, q11); 294 float q21d = quickDistance(unquantized, q21); 295 float q12d = quickDistance(unquantized, q12); 296 float q22d = quickDistance(unquantized, q22); 297 298 float best = min(q11d, 299 min(q21d, 300 min(q12d, 301 q22d))); 302 303 if (q11d == best) { 304 return q11; 305 } 306 307 if (q21d == best) { 308 return q21; 309 } 310 311 if (q12d == best) { 312 return q12; 313 } 314 315 return q22; 316} 317 318vec4 scale(sampler2D tex, vec2 coord){ 319 vec2 texCoord = coord; 320 vec2 pixel = vec2(1.0, 1.0) / uResolution; 321 // 4-pixel super sampling 322 323 vec4 q11 = omniScale(tex, texCoord + pixel * vec2(-0.25, -0.25)); 324 vec4 q21 = omniScale(tex, texCoord + pixel * vec2(+0.25, -0.25)); 325 vec4 q12 = omniScale(tex, texCoord + pixel * vec2(-0.25, +0.25)); 326 vec4 q22 = omniScale(tex, texCoord + pixel * vec2(+0.25, +0.25)); 327 328 return (q11 + q21 + q12 + q22) / 4.0; 329} 330 331void main() 332{ 333 FragColor = scale(Source, vTexCoord); 334} 335#endif 336