1#version 130 2 3#define NTSC_CRT_GAMMA 2.5 4#define NTSC_MONITOR_GAMMA 2.0 5 6#define fetch_offset(offset, one_x) \ 7 COMPAT_TEXTURE(Source, vTexCoord + vec2((offset) * (one_x), 0.0)).xyz 8 9#if defined(VERTEX) 10 11#if __VERSION__ >= 130 12#define COMPAT_VARYING out 13#define COMPAT_ATTRIBUTE in 14#define COMPAT_TEXTURE texture 15#else 16#define COMPAT_VARYING varying 17#define COMPAT_ATTRIBUTE attribute 18#define COMPAT_TEXTURE texture2D 19#endif 20 21#ifdef GL_ES 22#define COMPAT_PRECISION mediump 23#else 24#define COMPAT_PRECISION 25#endif 26 27COMPAT_ATTRIBUTE vec4 VertexCoord; 28COMPAT_ATTRIBUTE vec4 COLOR; 29COMPAT_ATTRIBUTE vec4 TexCoord; 30COMPAT_VARYING vec4 COL0; 31COMPAT_VARYING vec4 TEX0; 32 33uniform mat4 MVPMatrix; 34uniform COMPAT_PRECISION int FrameDirection; 35uniform COMPAT_PRECISION int FrameCount; 36uniform COMPAT_PRECISION vec2 OutputSize; 37uniform COMPAT_PRECISION vec2 TextureSize; 38uniform COMPAT_PRECISION vec2 InputSize; 39 40// vertex compatibility #defines 41#define vTexCoord TEX0.xy 42#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize 43#define outsize vec4(OutputSize, 1.0 / OutputSize) 44 45void main() 46{ 47 gl_Position = MVPMatrix * VertexCoord; 48 COL0 = COLOR; 49 TEX0.xy = TexCoord.xy - vec2(0.5 / SourceSize.x, 0.0); // Compensate for decimate-by-2. 50} 51 52#elif defined(FRAGMENT) 53 54#ifdef GL_ES 55#ifdef GL_FRAGMENT_PRECISION_HIGH 56precision highp float; 57#else 58precision mediump float; 59#endif 60#define COMPAT_PRECISION mediump 61#else 62#define COMPAT_PRECISION 63#endif 64 65#if __VERSION__ >= 130 66#define COMPAT_VARYING in 67#define COMPAT_TEXTURE texture 68out COMPAT_PRECISION vec4 FragColor; 69#else 70#define COMPAT_VARYING varying 71#define FragColor gl_FragColor 72#define COMPAT_TEXTURE texture2D 73#endif 74 75uniform COMPAT_PRECISION int FrameDirection; 76uniform COMPAT_PRECISION int FrameCount; 77uniform COMPAT_PRECISION vec2 OutputSize; 78uniform COMPAT_PRECISION vec2 TextureSize; 79uniform COMPAT_PRECISION vec2 InputSize; 80uniform sampler2D Texture; 81COMPAT_VARYING vec4 TEX0; 82 83// fragment compatibility #defines 84#define Source Texture 85#define vTexCoord TEX0.xy 86 87#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize 88#define outsize vec4(OutputSize, 1.0 / OutputSize) 89 90// begin ntsc-rgbyuv 91const mat3 yiq2rgb_mat = mat3( 92 1.0, 0.956, 0.6210, 93 1.0, -0.2720, -0.6474, 94 1.0, -1.1060, 1.7046); 95 96vec3 yiq2rgb(vec3 yiq) 97{ 98 return yiq * yiq2rgb_mat; 99} 100 101const mat3 yiq_mat = mat3( 102 0.2989, 0.5870, 0.1140, 103 0.5959, -0.2744, -0.3216, 104 0.2115, -0.5229, 0.3114 105); 106 107vec3 rgb2yiq(vec3 col) 108{ 109 return col * yiq_mat; 110} 111// end ntsc-rgbyuv 112 113// begin ntsc-decode-filter-3phase 114#if __VERSION__ <= 150 115float luma_filter1 = -0.000012020; 116float luma_filter2 = -0.000022146; 117float luma_filter3 = -0.000013155; 118float luma_filter4 = -0.000012020; 119float luma_filter5 = -0.000049979; 120float luma_filter6 = -0.000113940; 121float luma_filter7 = -0.000122150; 122float luma_filter8 = -0.000005612; 123float luma_filter9 = 0.000170516; 124float luma_filter10 = 0.000237199; 125float luma_filter11 = 0.000169640; 126float luma_filter12 = 0.000285688; 127float luma_filter13 = 0.000984574; 128float luma_filter14 = 0.002018683; 129float luma_filter15 = 0.002002275; 130float luma_filter16 = -0.000909882; 131float luma_filter17 = -0.007049081; 132float luma_filter18 = -0.013222860; 133float luma_filter19 = -0.012606931; 134float luma_filter20 = 0.002460860; 135float luma_filter21 = 0.035868225; 136float luma_filter22 = 0.084016453; 137float luma_filter23 = 0.135563500; 138float luma_filter24 = 0.175261268; 139float luma_filter25 = 0.190176552; 140 141float chroma_filter1 = -0.000118847; 142float chroma_filter2 = -0.000271306; 143float chroma_filter3 = -0.000502642; 144float chroma_filter4 = -0.000930833; 145float chroma_filter5 = -0.001451013; 146float chroma_filter6 = -0.002064744; 147float chroma_filter7 = -0.002700432; 148float chroma_filter8 = -0.003241276; 149float chroma_filter9 = -0.003524948; 150float chroma_filter10 = -0.003350284; 151float chroma_filter11 = -0.002491729; 152float chroma_filter12 = -0.000721149; 153float chroma_filter13 = 0.002164659; 154float chroma_filter14 = 0.006313635; 155float chroma_filter15 = 0.011789103; 156float chroma_filter16 = 0.018545660; 157float chroma_filter17 = 0.026414396; 158float chroma_filter18 = 0.035100710; 159float chroma_filter19 = 0.044196567; 160float chroma_filter20 = 0.053207202; 161float chroma_filter21 = 0.061590275; 162float chroma_filter22 = 0.068803602; 163float chroma_filter23 = 0.074356193; 164float chroma_filter24 = 0.077856564; 165float chroma_filter25 = 0.079052396; 166#else 167#define TAPS 24 168const float luma_filter[TAPS + 1] = float[TAPS + 1]( 169 -0.000012020, 170 -0.000022146, 171 -0.000013155, 172 -0.000012020, 173 -0.000049979, 174 -0.000113940, 175 -0.000122150, 176 -0.000005612, 177 0.000170516, 178 0.000237199, 179 0.000169640, 180 0.000285688, 181 0.000984574, 182 0.002018683, 183 0.002002275, 184 -0.000909882, 185 -0.007049081, 186 -0.013222860, 187 -0.012606931, 188 0.002460860, 189 0.035868225, 190 0.084016453, 191 0.135563500, 192 0.175261268, 193 0.190176552); 194 195const float chroma_filter[TAPS + 1] = float[TAPS + 1]( 196 -0.000118847, 197 -0.000271306, 198 -0.000502642, 199 -0.000930833, 200 -0.001451013, 201 -0.002064744, 202 -0.002700432, 203 -0.003241276, 204 -0.003524948, 205 -0.003350284, 206 -0.002491729, 207 -0.000721149, 208 0.002164659, 209 0.006313635, 210 0.011789103, 211 0.018545660, 212 0.026414396, 213 0.035100710, 214 0.044196567, 215 0.053207202, 216 0.061590275, 217 0.068803602, 218 0.074356193, 219 0.077856564, 220 0.079052396); 221#endif 222// end ntsc-decode-filter-3phase 223 224void main() 225{ 226// begin ntsc-pass2-decode 227 float one_x = 1.0 / SourceSize.x; 228 vec3 signal = vec3(0.0); 229#if __VERSION__ <= 130 230 float offset; 231 vec3 sums; 232 233 #define macro_loopz(c) offset = float(c) - 1.0; \ 234 sums = fetch_offset(offset - 24., one_x) + fetch_offset(24. - offset, one_x); \ 235 signal += sums * vec3(luma_filter##c, chroma_filter##c, chroma_filter##c); 236 237 // unrolling the loopz 238 macro_loopz(1) 239 macro_loopz(2) 240 macro_loopz(3) 241 macro_loopz(4) 242 macro_loopz(5) 243 macro_loopz(6) 244 macro_loopz(7) 245 macro_loopz(8) 246 macro_loopz(9) 247 macro_loopz(10) 248 macro_loopz(11) 249 macro_loopz(12) 250 macro_loopz(13) 251 macro_loopz(14) 252 macro_loopz(15) 253 macro_loopz(16) 254 macro_loopz(17) 255 macro_loopz(18) 256 macro_loopz(19) 257 macro_loopz(20) 258 macro_loopz(21) 259 macro_loopz(22) 260 macro_loopz(23) 261 macro_loopz(24) 262 263 signal += COMPAT_TEXTURE(Texture, TEX0.xy).xyz * 264 vec3(luma_filter25, chroma_filter25, chroma_filter25); 265#else 266 for (int i = 0; i < TAPS; i++) 267 { 268 float offset = float(i); 269 270 vec3 sums = fetch_offset(offset - float(TAPS), one_x) + 271 fetch_offset(float(TAPS) - offset, one_x); 272 273 signal += sums * vec3(luma_filter[i], chroma_filter[i], chroma_filter[i]); 274 } 275 signal += COMPAT_TEXTURE(Source, vTexCoord).xyz * 276 vec3(luma_filter[TAPS], chroma_filter[TAPS], chroma_filter[TAPS]); 277#endif 278// end ntsc-pass2-decode 279 vec3 rgb = yiq2rgb(signal); 280 FragColor = vec4(pow(rgb, vec3(NTSC_CRT_GAMMA / NTSC_MONITOR_GAMMA)), 1.0); 281} 282#endif 283