Simple rain/snow shader

Simple rain/snow shader learning project for godot 4.x

 

Attach to e.g. a ColorRect and adjust to desired size

Shader code
// simple rain/snow shader
// useful learning resources:
// https://www.ronja-tutorials.com/post/034-2d-sdf-basics/#circle
// https://iquilezles.org/articles/distfunctions2d/

shader_type canvas_item;

// can make snow by adjusting values
uniform int count: hint_range(0, 2000) = 150;
uniform float slant: hint_range(-0.1, 0.1) = -0.01;
uniform float speed: hint_range(25.0, 100.0) = 50.0;
uniform float blur: hint_range(0.0005, 0.1) = 0.002;
uniform vec4 colour: source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform vec2 size = vec2(0.005, 0.2);

float line_sdf(vec2 p, vec2 s) {
    vec2 d = abs(p) - s;
    return min(max(d.x, d.y), 0.0) + length(max(d, 0.0));
}

float Hash(float x) {
    return fract(sin(x * 18.34) * 51.78);
}

float Hash2(float x) {
    return fract(sin(x * 25.42) * 21.24);
}

void fragment() {
	// inspector issue with tiny vec 2
    vec2 s = size * 0.1;
	// to work at the start
    float time = TIME + 1000.0;
    vec2 uv = UV;
	// slant each line left or right
    uv.x += uv.y * slant;
    float output = 0.0;
    
    for (int i = 1; i <= count; i++) {
        float h1 = Hash(float(i));
        float h2 = Hash2(float(i));
		// make it so the lines move in the direction of the slant as well
		// otherwise they would go directly down no matter what slant is
        float sl = h1 * uv.y * -slant;
		// compute random x position of line, multiply by 1.2 to cover the far edges more predictably
        float pos_mod_x = h1 * 1.2;
		// there is probably better way to do this, to prevent line from moving too slow compared to other lines
        float pos_mod_y = max(h2 * speed, pos_mod_x * speed);
		// wrap y values around to loop the anim
        vec2 position = vec2(pos_mod_x + sl, -mod(-pos_mod_y * time * 0.1, -1.));
        float sdf = line_sdf(uv - position, s);
        output += clamp(- sdf / blur, 0.0, 1.0);
    }

    COLOR = vec4(colour.rgb, output);
}
Tags
2d, rain, Snow
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Rain and Snow with Parallax Effect

Procedural Window Rain Drop Shader

Rain drops on screen – notexture

Subscribe
Notify of
guest

4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
alefranart
alefranart
1 year ago

I absolutely loved it! Thank you so much.

mohamed
mohamed
8 months ago

but But it is very slow and when I adjust the speed it does not increase

bestkindbean
bestkindbean
5 months ago

This is great! Adjusted the speed parameters to slow the snow down in order to make it look less heavy and more flowy. Thank you!

seqxxxx
2 months ago

Great shader!!
// there is probably better way to do this, to prevent line from moving too slow compared to other lines
float pos_mod_y = max(h2 * speed, pos_mod_x * speed);
This line can be replaced with the following snippet to improve the problem.
float pos_mod_y = (0.5 + h2) * speed; 
For some reason using this on a MeshInstance2D child of a Parallax2D I was having the issue of the rain going in the wrong direction.
uniform float speed: hint_range(0.0, 100.0) = 50.0;
If anybody else is having that issue simply replace the speed range to accept negative values.
uniform float speed: hint_range(-100.0, 100.0) = 50.0;

Last edited 2 months ago by seqxxxx