1 <?xml version=
"1.0" encoding=
"UTF-8"?>
5 <shader language=
"GLSL">
9 uniform vec2 rubyTextureSize;
17 vec2 tex = gl_MultiTexCoord0.xy;
18 vec2 onetexelx = vec2(
1.0 / rubyTextureSize.x,
0.0);
19 vec2 onetexely = vec2(
0.0,
1.0 / rubyTextureSize.y);
22 c10 = tex - onetexelx;
23 c01 = tex - onetexely;
25 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
28 <fragment filter=
"linear"><![CDATA[
31 uniform float randomSeed;
33 uniform float CHROMA_TO_LUMA_STRENGTH;
34 uniform float LUMA_TO_CHROMA_STRENGTH;
35 uniform float SCANLINE_SHADE_LUMA;
36 uniform float PHOSPHOR_SHADE;
37 uniform float RANDOM_SCANLINE_DISPLACE;
38 uniform float RANDOM_Y;
39 uniform float RANDOM_UV;
40 uniform float LUMA_X_BLUR;
41 uniform float CHROMA_X_BLUR;
42 uniform float CHROMA_Y_BLUR;
43 uniform float RADIAL_DISTORTION;
45 uniform sampler2D rubyTexture;
46 uniform vec2 rubyTextureSize;
52 float rand(vec2 seed) {
53 return fract(sin(dot(vec2(seed.x + randomSeed, seed.y + randomSeed), vec2(
12.9898,
78.233))) *
43758.5453);
57 return vec2(fract(sin(dot(vec2(randomSeed, gl_FragCoord.y), vec2(
12.9898,
78.233))) *
43758.5453),
0.0);
60 vec2 radialDistortion(vec2 coord) {
61 vec2 cc = coord - vec2(
0.5);
62 float dist = dot(cc, cc) * RADIAL_DISTORTION *
0.5;
63 return (coord + cc * (
1.0 + dist) * dist);
66 vec4 texture_x_linear(vec2 pos) {
67 pos = radialDistortion(pos);
68 return texture2D(rubyTexture, vec2(pos.x, (floor(pos.y * rubyTextureSize.y) +
0.5) / rubyTextureSize.y));
71 vec4 texture(vec2 pos) {
72 pos = radialDistortion(pos);
73 return texture2D(rubyTexture, pos);
77 mat3 rgb2yuv = mat3(
0.299, -
0.14713,
0.615,
78 0.587, -
0.28886, -
0.51499,
79 0.114,
0.436 , -
0.10001);
80 mat3 yuv2rgb = mat3(
1.0,
1.0,
1.0,
81 0.0, -
0.39465,
2.03211,
82 1.13983, -
0.58060,
0.0);
84 bool even = mod(c00.y * rubyTextureSize.y,
2.0) <
1.0;
85 vec3 phosphor = vec3(
1.0, PHOSPHOR_SHADE, PHOSPHOR_SHADE);
88 vec2 dist = rand_x() / rubyTextureSize.x * RANDOM_SCANLINE_DISPLACE;
89 vec3 yuvm1 = rgb2yuv * texture_x_linear(c10 + dist).rgb;
90 vec3 yuv_0 = rgb2yuv * texture_x_linear(c00 + dist).rgb;
91 vec3 yuvym1 = rgb2yuv * texture(c01 + dist).rgb;
94 /* luma: set as blurred from original */
95 /* y */ mix(yuv_0.x, yuvm1.x, LUMA_X_BLUR *
0.5),
96 /* chroma: set as blurred from original */
97 /* u */ mix(yuv_0.y, yuvym1.y, CHROMA_Y_BLUR),
98 /* v */ mix(yuv_0.z, yuvym1.z, CHROMA_Y_BLUR)
101 /* edge detect for crosstalk. */
102 /* also chroma x blur from the edge detect vector - otherwise it's not really visible. */
103 vec3 d = yuvm1 - yuv_0;
105 /* chroma crosstalk to luma */
106 /* y */ CHROMA_TO_LUMA_STRENGTH * (even ? (d.y + d.z) : (d.z - d.y)),
107 /* luma crosstalk to chroma */
108 /* u */ -LUMA_TO_CHROMA_STRENGTH * d.x + CHROMA_X_BLUR * d.y,
109 /* v */ LUMA_TO_CHROMA_STRENGTH * d.x + CHROMA_X_BLUR * d.z
112 /* random noise. the positions are used to feed the random gen. */
114 (rand(c00) -
0.5) * RANDOM_Y,
115 (rand(c01) -
0.5) * RANDOM_UV,
116 (rand(c10) -
0.5) * RANDOM_UV
119 /* darken every second row */
120 if (mod(gl_FragCoord.y,
2.0) <
1.0)
121 yuv.x *= SCANLINE_SHADE_LUMA;
124 float pix = mod(gl_FragCoord.x,
3.0);
126 phosphor = phosphor.yzx;
128 phosphor = phosphor.zxy;
130 /* back to rgb and add phosphor. and here is the result */
131 gl_FragColor.rgb = yuv2rgb * yuv * phosphor;