1#define COLOR_LOW 0.7
2#define COLOR_HIGH 1.0
3#define VERTICAL_BORDER_DEPTH 0.6
4#define SCANLINE_DEPTH 0.3
5#define CURVENESS 0.3
6
7STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution)
8{
9    /* Curve and pixel ratio */
10    float y_curve = cos(position.x - 0.5) * CURVENESS + (1 - CURVENESS);
11    float y_multiplier = 8.0 / 7.0 / y_curve;
12    position.y *= y_multiplier;
13    position.y -= (y_multiplier - 1) / 2;
14    if (position.y < 0.0) return vec4(0,0,0,0);
15    if (position.y > 1.0) return vec4(0,0,0,0);
16
17    float x_curve = cos(position.y - 0.5) * CURVENESS + (1 - CURVENESS);
18    float x_multiplier = 1/x_curve;
19    position.x *= x_multiplier;
20    position.x -= (x_multiplier - 1) / 2;
21    if (position.x < 0.0) return vec4(0,0,0,0);
22    if (position.x > 1.0) return vec4(0,0,0,0);
23
24    /* Setting up common vars */
25    vec2 pos = fract(position * input_resolution);
26    vec2 sub_pos = fract(position * input_resolution * 6);
27
28    vec4 center = texture(image, position);
29    vec4 left = texture(image, position - vec2(1.0 / input_resolution.x, 0));
30    vec4 right = texture(image, position + vec2(1.0 / input_resolution.x, 0));
31
32    /* Vertical blurring */
33    if (pos.y < 1.0 / 6.0) {
34        center = mix(center, texture(image, position + vec2(0, -1.0 / input_resolution.y)), 0.5 - sub_pos.y / 2.0);
35        left =   mix(left,   texture(image, position + vec2(-1.0 / input_resolution.x, -1.0 / input_resolution.y)), 0.5 - sub_pos.y / 2.0);
36        right =  mix(right,  texture(image, position + vec2( 1.0 / input_resolution.x, -1.0 / input_resolution.y)), 0.5 - sub_pos.y / 2.0);
37    }
38    else if (pos.y > 5.0 / 6.0) {
39        center = mix(center, texture(image, position + vec2(0, 1.0 / input_resolution.y)), sub_pos.y / 2.0);
40        left =   mix(left,   texture(image, position + vec2(-1.0 / input_resolution.x, 1.0 / input_resolution.y)), sub_pos.y / 2.0);
41        right =  mix(right,  texture(image, position + vec2( 1.0 / input_resolution.x, 1.0 / input_resolution.y)), sub_pos.y / 2.0);
42    }
43
44    /* Scanlines */
45    float scanline_multiplier;
46    if (pos.y < 0.5) {
47        scanline_multiplier = (pos.y * 2) * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH);
48    }
49    else  {
50        scanline_multiplier = ((1 - pos.y) * 2) * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH);
51    }
52
53    center *= scanline_multiplier;
54    left *= scanline_multiplier;
55    right *= scanline_multiplier;
56
57    /* Vertical seperator for shadow masks */
58    bool odd = bool(int((position * input_resolution).x) & 1);
59    if (odd) {
60        pos.y += 0.5;
61        pos.y = fract(pos.y);
62    }
63
64    if (pos.y < 1.0 / 3.0) {
65        float gradient_position = pos.y * 3.0;
66        center *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
67        left *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
68        right *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
69    }
70    else if (pos.y > 2.0 / 3.0) {
71        float gradient_position = (1 - pos.y) * 3.0;
72        center *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
73        left *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
74        right *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
75    }
76
77    /* Blur the edges of the separators of adjacent columns */
78    if (pos.x < 1.0 / 6.0 || pos.x > 5.0 / 6.0) {
79        pos.y += 0.5;
80        pos.y = fract(pos.y);
81
82        if (pos.y < 1.0 / 3.0) {
83            float gradient_position = pos.y * 3.0;
84            if (pos.x < 0.5) {
85                gradient_position = 1 - (1 - gradient_position) * (1 - (pos.x) * 6.0);
86            }
87            else {
88                gradient_position = 1 - (1 - gradient_position) * (1 - (1 - pos.x) * 6.0);
89            }
90            center *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
91            left *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
92            right *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
93        }
94        else if (pos.y > 2.0 / 3.0) {
95            float gradient_position = (1 - pos.y) * 3.0;
96            if (pos.x < 0.5) {
97                gradient_position = 1 - (1 - gradient_position) * (1 - (pos.x) * 6.0);
98            }
99            else {
100                gradient_position = 1 - (1 - gradient_position) * (1 - (1 - pos.x) * 6.0);
101            }
102            center *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
103            left *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
104            right *= gradient_position * VERTICAL_BORDER_DEPTH + (1 - VERTICAL_BORDER_DEPTH);
105        }
106    }
107
108
109    /* Subpixel blurring, like LCD filter*/
110
111    vec4 midleft = mix(left, center, 0.5);
112    vec4 midright = mix(right, center, 0.5);
113
114    vec4 ret;
115    if (pos.x < 1.0 / 6.0) {
116        ret = mix(vec4(COLOR_HIGH * center.r, COLOR_LOW * center.g, COLOR_HIGH * left.b, 1),
117                  vec4(COLOR_HIGH * center.r, COLOR_LOW * center.g, COLOR_LOW  * left.b, 1),
118                  sub_pos.x);
119    }
120    else if (pos.x < 2.0 / 6.0) {
121        ret = mix(vec4(COLOR_HIGH * center.r, COLOR_LOW  * center.g, COLOR_LOW * left.b, 1),
122                  vec4(COLOR_HIGH * center.r, COLOR_HIGH * center.g, COLOR_LOW * midleft.b, 1),
123                  sub_pos.x);
124    }
125    else if (pos.x < 3.0 / 6.0) {
126        ret = mix(vec4(COLOR_HIGH * center.r  , COLOR_HIGH * center.g, COLOR_LOW * midleft.b, 1),
127                  vec4(COLOR_LOW  * midright.r, COLOR_HIGH * center.g, COLOR_LOW * center.b, 1),
128                  sub_pos.x);
129    }
130    else if (pos.x < 4.0 / 6.0) {
131        ret = mix(vec4(COLOR_LOW * midright.r, COLOR_HIGH * center.g , COLOR_LOW  * center.b, 1),
132                  vec4(COLOR_LOW * right.r   , COLOR_HIGH  * center.g, COLOR_HIGH * center.b, 1),
133                  sub_pos.x);
134    }
135    else if (pos.x < 5.0 / 6.0) {
136        ret = mix(vec4(COLOR_LOW * right.r, COLOR_HIGH * center.g  , COLOR_HIGH * center.b, 1),
137                  vec4(COLOR_LOW * right.r, COLOR_LOW  * midright.g, COLOR_HIGH * center.b, 1),
138                  sub_pos.x);
139    }
140    else {
141        ret = mix(vec4(COLOR_LOW  * right.r, COLOR_LOW * midright.g, COLOR_HIGH * center.b, 1),
142                  vec4(COLOR_HIGH * right.r, COLOR_LOW * right.g  ,  COLOR_HIGH * center.b, 1),
143                  sub_pos.x);
144    }
145
146    /* Anti alias the curve */
147    vec2 pixel_position = position * output_resolution;
148    if (pixel_position.x < 1) {
149        ret *= pixel_position.x;
150    }
151    else if (pixel_position.x > output_resolution.x - 1) {
152        ret *= output_resolution.x - pixel_position.x;
153    }
154    if (pixel_position.y < 1) {
155        ret *= pixel_position.y;
156    }
157    else if (pixel_position.y > output_resolution.y - 1) {
158        ret *= output_resolution.y - pixel_position.y;
159    }
160
161    return ret;
162}
163