shader_type canvas_item;
render_mode unshaded;
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
uniform float scanline_strength = 0.38;
uniform float mask_strength = 0.18;
uniform float curvature = 0.08;
uniform float glow = 0.22;
uniform bool preserve_luminance = true;
float luma(vec3 color) {
return dot(color, vec3(0.2126, 0.7152, 0.0722));
}
vec2 curve_uv(vec2 uv) {
vec2 centered = uv * 2.0 - 1.0;
centered += centered * abs(centered.yx) * abs(centered.yx) * curvature;
return centered * 0.5 + 0.5;
}
void fragment() {
vec2 uv = curve_uv(SCREEN_UV);
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
COLOR = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
vec3 original = texture(screen_texture, uv).rgb;
float line = sin(uv.y / SCREEN_PIXEL_SIZE.y * 3.14159265);
float scanline = mix(1.0, 0.62 + line * 0.18, scanline_strength);
vec3 mask = vec3(
0.72 + 0.28 * step(0.66, fract(uv.x / SCREEN_PIXEL_SIZE.x / 3.0)),
0.72 + 0.28 * step(0.33, fract(uv.x / SCREEN_PIXEL_SIZE.x / 3.0)),
0.72 + 0.28 * step(0.00, fract(uv.x / SCREEN_PIXEL_SIZE.x / 3.0))
);
vec3 crt = original * scanline * mix(vec3(1.0), mask, mask_strength);
crt += original * glow * 0.18;
if (preserve_luminance) {
float before = max(luma(original), 0.0001);
float after = max(luma(crt), 0.0001);
crt = mix(crt, crt * (before / after), 0.75);
}
COLOR = vec4(clamp(crt, 0.0, 1.0), 1.0);
}