vivisu/psx_camera/psx_camera_shader.gdshader
2025-08-04 00:39:07 -04:00

80 lines
2.6 KiB
Text

shader_type spatial;
render_mode cull_disabled, unshaded;
uniform sampler2D depth_texture : source_color, hint_depth_texture;
uniform sampler2D screen_texture : source_color, hint_screen_texture, repeat_disable, filter_nearest;
uniform bool enable_fog = true;
uniform vec3 fog_color : source_color;
uniform vec3 noise_color : source_color;
uniform float fog_distance : hint_range(1, 6000) = 100;
uniform float fog_fade_range : hint_range(1, 6000) = 50;
uniform bool enable_noise = true;
uniform float noise_time_fac : hint_range(0.1, 10) = 4;
uniform bool enable_color_limitation = true;
uniform int color_levels : hint_range(2, 256) = 32;
uniform bool enable_dithering = true;
uniform float dither_strength : hint_range(0.0, 1.0) = 0.3;
float hashOld12(vec2 p){
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453 + (TIME / noise_time_fac)) ;
}
vec3 color_mix(vec3 a, vec3 b, float f ){
f = clamp(abs(f), 0,1);
float invf = 1.0 - f;
return (a*f) + (b*invf);
}
vec3 quantize_color(vec3 color, int levels) {
float quantizer = float(levels - 1);
return floor(color * quantizer + 0.5) / quantizer;
}
float dither(vec2 position, float brightness) {
int x = int(mod(position.x, 4.0));
int y = int(mod(position.y, 4.0));
int index = x + y * 4;
float dithering[16] = float[](
0.0, 0.5, 0.125, 0.625,
0.75, 0.25, 0.875, 0.375,
0.1875, 0.6875, 0.0625, 0.5625,
0.9375, 0.4375, 1.0, 0.8125
);
float threshold = dithering[index];
return brightness < threshold ? 0.0 : 1.0;
}
void vertex() {
POSITION = vec4(VERTEX.xy, 1.0, 1.0);
}
void fragment(){
vec3 screen_color = texture(screen_texture, SCREEN_UV).rgb;
vec2 screen_coords = SCREEN_UV * 2.0 - 1.0;
float depth = texture(depth_texture, SCREEN_UV).x;
vec3 ndc = vec3(screen_coords, depth);
vec4 view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
view.xyz /= view.w;
float linear_depth = -view.z;
float depth_mask_inv = clamp((linear_depth - (fog_distance - fog_fade_range)) / fog_fade_range, 0.0, 1.0);
vec3 final_color = screen_color;
if (enable_noise){
vec3 twocolornoise = color_mix(fog_color, noise_color, hashOld12(screen_coords));
final_color = color_mix(twocolornoise, final_color, depth_mask_inv);
}
if (enable_fog){
final_color = color_mix(fog_color, final_color, depth_mask_inv);
}
if (enable_color_limitation){
final_color = quantize_color(final_color, color_levels);
}
if (enable_dithering){
float brightness = dot(final_color, vec3(0.3, 0.59, 0.11));
brightness += dither_strength * (dither(FRAGCOORD.xy, brightness) - 0.5);
final_color *= (1.0 + dither_strength * (dither(FRAGCOORD.xy, brightness) - 0.5));
}
ALBEDO = final_color;
}