Godot Version
v4.7.stable.official [5b4e0cb0f]
FIXED: I did need to adjust the scaled_uv by the resolution, but the resolution needed to passed in through a uniform set by a script. Got it functioning properly at all resolutions now.
Question
When running the shader below, I get peaceful raindrop splashes, which is what I was going for. However when I try to scale the scene to full screen (default 1920 x 1080, going to 3322 x 1869), the splashes start glitching out and their position jumps all over the screen.
The shader is being drawn on a ColorRect of size 1920x1080.
Currently have these settings:
shader_type canvas_item;
uniform float max_circle_size: hint_range(0.0, 1.0) = 0.5;
uniform int num_circles: hint_range(0, 20, 1) = 10;
uniform float threshold: hint_range(0.0, 1.0) = 0.5;
uniform float range: hint_range(0.0, 1.0) = 0.5;
uniform vec4 bg_color: source_color = vec4(0.0, 0.0, 0.8, 1.);
float hashy(float n) {
// get a random number between 0.25 and 1.0
// (offset that stil shows up on screen somewhere)
// need seperate x/y due to resolution sizing
return 0.25 + fract(sin(n) * 43758.5453) * 0.75;
}
float hashx(float n) {
return 0.25 + fract(sin(n) * 43758.5453) * 1.5;
}
vec2 hash2(float n) {
return vec2(hashx(n), hashy(n + 60.1));
}
float draw_circle(vec2 scaled_uv, float time_offset) {
// take the int value of full_time as the seed for position
// take the decimal value of full_time as the current size of the circle
// tried taking the mod of TIME to avoid huge TIME values causing floating pt issues.
float full_time = (mod(TIME, 1000.) + time_offset * hashx(time_offset)) / 7.;
// tried to increase the seed by 1 a little early to avoid jumping, no dice
vec2 rand_spawn = scaled_uv - hash2(floor(full_time) + step(0.95, fract(full_time)));
float curr_size = fract(full_time) * max_circle_size;
//curr_size = pow(curr_size, 1./2.);
//float circle = distance(rand_spawn, vec2(curr_size, curr_size));
float circle = length(rand_spawn) - curr_size;
// make it so its a ring not a full circle
circle = 1. - smoothstep(0., 0.05, abs(circle));
// add some fuzziness to the edges
float lb = threshold - range;
float ub = threshold + range;
circle = smoothstep(lb, ub, circle);
// ease the start/ends
circle *= smoothstep(0., 0.1, curr_size);
circle *= 1. - smoothstep(0.7, 1., fract(full_time));
//circle -= smoothstep(0.7, 1., curr_size + 0.3);
return circle;
//return step(circle, fract(full_time) * max_circle_size);
}
void fragment() {
// need to scale uv so that circles are actually circular, not ovals
vec2 scaled_uv = UV;
// I've tried adjusting this using SCREEN_PIXEL_SIZE with no differences
// The shader is being drawn on a ColorRect of size 1920x1080
scaled_uv.x *= 1920. / 1080.;
COLOR = bg_color;
for (int i = 0; i < num_circles; i++) {
COLOR.b += draw_circle(scaled_uv + vec2(0.2), float(i) * float(num_circles));
}
}
