86 lines
2.6 KiB
Plaintext
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);
|
|
}
|