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