diff --git a/ps1_filter.gdshader b/ps1_filter.gdshader new file mode 100644 index 0000000..4783328 --- /dev/null +++ b/ps1_filter.gdshader @@ -0,0 +1,32 @@ +shader_type canvas_item; + +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_nearest; +uniform float pixel_scale : hint_range(1.0, 8.0, 1.0) = 4.0; +uniform float color_depth : hint_range(2.0, 8.0, 1.0) = 5.0; +uniform float dither_strength : hint_range(0.0, 2.0, 0.05) = 0.8; + +float bayer4(ivec2 p) { + int x = p.x & 3; + int y = p.y & 3; + float m[16] = float[16]( + 0.0, 8.0, 2.0, 10.0, + 12.0, 4.0, 14.0, 6.0, + 3.0, 11.0, 1.0, 9.0, + 15.0, 7.0, 13.0, 5.0 + ); + return m[y * 4 + x] / 16.0 - 0.5; +} + +void fragment() { + vec2 pixel_size = SCREEN_PIXEL_SIZE * pixel_scale; + vec2 snapped = (floor(SCREEN_UV / pixel_size) + 0.5) * pixel_size; + vec3 col = texture(SCREEN_TEXTURE, snapped).rgb; + + ivec2 dpos = ivec2(FRAGCOORD.xy / pixel_scale); + float t = bayer4(dpos) * dither_strength; + + float levels = exp2(color_depth) - 1.0; + col = clamp(floor(col * levels + t + 0.5) / levels, 0.0, 1.0); + + COLOR = vec4(col, 1.0); +}