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