diff --git a/SDL/gui.c b/SDL/gui.c index 6ab6f003..46397902 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -2339,11 +2339,6 @@ void convert_mouse_coordinates(signed *x, signed *y) *x = (signed)(*x - rect.x / factor) * width / (signed)(rect.w / factor) - x_offset; *y = (signed)(*y - rect.y / factor) * height / (signed)(rect.h / factor) - y_offset; - - if (strcmp("CRT", configuration.filter) == 0) { - *y = *y * 8 / 7; - *y -= 144 / 16; - } } void update_swap_interval(void) diff --git a/Shaders/CRT.fsh b/Shaders/CRT.fsh index 154f0a2f..a2200821 100644 --- a/Shaders/CRT.fsh +++ b/Shaders/CRT.fsh @@ -6,21 +6,39 @@ STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 output_resolution) { - /* Curve and pixel ratio */ + /* Curve */ float y_curve = cos(position.x - 0.5) * CURVENESS + (1.0 - CURVENESS); - float y_multiplier = 8.0 / 7.0 / y_curve; + float y_multiplier = 1 / y_curve; position.y *= y_multiplier; position.y -= (y_multiplier - 1.0) / 2.0; - if (position.y < 0.0) return vec4(0,0,0,0); - if (position.y > 1.0) return vec4(0,0,0,0); - + float x_curve = cos(position.y - 0.5) * CURVENESS + (1.0 - CURVENESS); float x_multiplier = 1.0/x_curve; position.x *= x_multiplier; position.x -= (x_multiplier - 1.0) / 2.0; - if (position.x < 0.0) return vec4(0,0,0,0); - if (position.x > 1.0) return vec4(0,0,0,0); - + + float aa_x = max(fwidth(position.x), 1e-5); + float aa_y = max(fwidth(position.y), 1e-5); + + float edge_mask = smoothstep(-aa_x, aa_x, position.x) + * smoothstep(-aa_x, aa_x, 1.0 - position.x) + * smoothstep(-aa_y, aa_y, position.y) + * smoothstep(-aa_y, aa_y, 1.0 - position.y); + + float superellipse = pow(abs(position.x * 2.0 - 1.0), 16.0) + pow(abs(position.y * 2.0 - 1.0), 16.0); + float edge_aa = max(fwidth(superellipse), 1e-5); + float corner_mask = 1.0 - smoothstep(1.0 - edge_aa, 1.0 + edge_aa, superellipse); + + float total_mask = edge_mask * corner_mask; + + /* Safe to branch now: this is AFTER all fwidth() calls, so it no longer + corrupts derivative computation for neighboring pixels. */ + if (total_mask <= 0.0) return vec4(0,0,0,1); + + /* Clamp position for the rest of the effect, now that out-of-range + pixels are handled purely through total_mask */ + position = clamp(position, 0.0, 1.0); + /* Setting up common vars */ vec2 pos = fract(position * input_resolution); vec2 sub_pos = pos * 6.0; @@ -158,5 +176,7 @@ STATIC vec4 scale(sampler2D image, vec2 position, vec2 input_resolution, vec2 ou ret *= output_resolution.y - pixel_position.y; } + ret = mix(vec4(0,0,0,1), ret, corner_mask); + return ret; }