Files
Five-Nights-At-Akers/Scripts/Logic/video_distortion.gdshader
2026-03-24 12:56:35 -07:00

86 lines
2.6 KiB
Plaintext

shader_type canvas_item;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
uniform float amount : hint_range(0.0, 1.0) = 0.5;
uniform float seed = 0.0;
uniform float line_density : hint_range(0.0, 1.0) = 0.4;
uniform float offset_mul : hint_range(0.0, 2.0) = 1.0;
uniform vec2 screen_offset = vec2(0.0);
uniform vec2 screen_bend_amount = vec2(0.02, 0.02);
float hash1d(float p) {
return fract(sin(127.1 * p) * 43758.5453123);
}
void fragment() {
/* ===============================
Coordinate setup
================================ */
vec2 uv = SCREEN_UV;
uv += screen_offset;
// Screen bend (CRT-like)
vec2 normal_uv = uv * 2.0 - 1.0;
vec2 bend_add;
bend_add.x = cos(1.5707963 * normal_uv.y) * normal_uv.x - normal_uv.x * 1.5;
bend_add.y = cos(1.5707963 * normal_uv.x) * normal_uv.y - normal_uv.y * 1.5;
uv += bend_add * screen_bend_amount;
vec4 base_color = texture(SCREEN_TEXTURE, uv);
vec2 virtual_coords = uv * 100.0;
/* ===============================
Row-based randomization
================================ */
float row_rand = hash1d(seed + floor(virtual_coords.y * 0.1));
float y_mul = mix(0.05, 0.8, row_rand * row_rand);
float rand_strength = hash1d(floor(virtual_coords.y * y_mul) + 100.0 + row_rand);
float final_amount = 0.0;
float coord_add = 0.0;
if (rand_strength > (1.0 - line_density)) {
float distort_amount = 0.15;
final_amount = amount * (
0.5 +
(hash1d(floor(virtual_coords.y * y_mul) + 1273.0 + floor(amount * 4.0)) * 2.0 - 1.0) * 0.5
);
float ra = hash1d(floor(virtual_coords.y)) * 2.0 - 1.0;
coord_add = ra * distort_amount * final_amount;
coord_add += (hash1d(floor(virtual_coords.x * 0.25)) * 2.0 - 1.0) * distort_amount * 0.4;
coord_add *= offset_mul;
}
/* ===============================
Intensity weighting
================================ */
float intensity = dot(base_color.rgb, vec3(0.3, 0.58, 0.12));
intensity = clamp(intensity, 0.0, 1.0);
float dual_intensity = abs(intensity * 2.0 - 1.0);
dual_intensity *= dual_intensity;
/* ===============================
Distortion sampling
================================ */
vec4 samp1 = texture(SCREEN_TEXTURE, uv + vec2(coord_add * -0.65 * dual_intensity, 0.0));
vec4 samp2 = texture(SCREEN_TEXTURE, uv + vec2(coord_add * 1.0 * dual_intensity, 0.0));
vec4 distort_color = mix(samp1, samp2, 0.5);
/* ===============================
Final output
================================ */
float mix_amount = dual_intensity * final_amount;
COLOR = mix(base_color, distort_color, mix_amount)
+ vec4(vec3(intensity * final_amount * 0.05), 1.0);
}