How to get smooth circular ripples in fragment shader?

Godot Version

4.4.1

Question

`
ripple_01

I’m modifying a ripple shader that I found online to fit inside my game, and although I’ve gotten it to where I am pretty happy with how it looks, the ripple has an undesirable pinching or hourglass shape that is extremely noticeable towards the very center.
I think this is caused by the uv being a square shape and not circular to begin with. I want more circular ripples as I want to use this effect to disturb the surface of something, but I can’t figure it out.

void fragment() {
    // Set the pos of center and the distance to center
    vec2 center_position = -1.0 + 2.0 * UV / (1.0 / TEXTURE_PIXEL_SIZE);
    float center_distance = length(center_position);
    
    // Obtain uv behind the shape
    vec2 uv = FRAGCOORD.xy / (1.0 / SCREEN_PIXEL_SIZE).xy;
    
    // Create ripple that dissipates near edges
    float ripple = sin(center_distance * -frequency * PI + ripple_rate * TIME) * amplitude / (center_distance + 1.0);
    float alpha_scalar = (1.0 - min(center_distance, 1.0));
    ripple *= alpha_scalar;
    
    // Warp the uv
    uv = uv + (center_position/center_distance) * ripple * wave_amplitude;
    
    // Put the screen texture over the specified uv
    vec3 color = textureLod(SCREEN_TEXTURE, uv, 0.1).rgb;
    COLOR = vec4(color, 1.0);
}

`

Here’s a version of the gif with a frequency and amplitude of 1 so you can really see the pinching.

ripple_04

You’ve got center_distance telling you how far you are from the middle (and the point where it’s pinching). What I’d suggest is, check if the distance is less than (say) 0.1, and if so, don’t fully apply your ripple. Maybe smoothstep() between not applied at all at 0.0 and fully applied at 0.1. Adjust the deadzone to taste.

Thank you everyone in the discord was saying it was likely from the center_distance as well. Someone suggested trying to cancel out the exponential effect of center_distance with something like this

center_distance = 0.33 / pow(center_distance, 0.5);
// Warp the uv
uv = uv + (center_position / center_distance) * ripple * wave_amplitude;

I’ve tweaked the variables above a bit to get something i’m pretty happy with, added a slight wiggle to the position of the ripple and i have something like this

ripple_05

1 Like