Procedural Drops Animated – Rain / Sweat / etc
Based on https://www.shadertoy.com/view/tdG3Rw by piyushslayer
This is a .gdshaderinc file
Use it to add animated drops to another shader
Example images are when used with my stylized skin shader :
https://godotshaders.com/shader/stylized-skin/
Model:
“miku brazilian (fbx) + rig” (https://skfb.ly/pwtDx) by Prismxd oficial yt is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
Usage example:
#include "your/path/drops.gdshaderinc"
varying vec2 drops;
void fragment() {
drops = dropsUV(UV, TIME); // if upside down use -TIME
// ...
NORMAL_MAP -= vec3(drops, 0.) * 6.0; // multiply to increase intensity
ALBEDO = texture(SomeTexture, UV + drops).rgb; // adds distortion inside the drops
// ...
}
void light() {
SPECULAR_LIGHT += length(drops); // makes drops shinier around their edges | NOTE If you use this you will need to define the rest of the light function
}
Shader code
// Ported to Godot by paperbag
// Based on https://www.shadertoy.com/view/tdG3Rw by piyushslayer
// This code is for a .gdshaderinc file
// Use the dropsUV(UV, TIME) function in your own shader
// And don't forget to assign a noise texture (recommend enabling seamless on it)
uniform sampler2D DropsNoise;
#define PI 3.141592653589793
float hash21(vec2 p)
{
uvec2 q = uvec2(ivec2(p)) * uvec2(1597334673U, 3812015801U);
uint n = (q.x ^ q.y) * 1597334673U;
return float(n) / float(0xffffffffU);
}
vec3 hash13(float p) {
vec3 p3 = fract(vec3(p) * vec3(.1031,.11369,.13787));
p3 += dot(p3, p3.yzx + 19.19);
return fract(vec3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));
}
float rainDrops(vec2 st, float time, float size, vec2 scale)
{
vec2 uv = st * size;
uv.x *= scale.x / scale.y;
vec2 gridUv = fract(uv) - .5; // grid
vec2 id = floor(uv);
vec3 h = (hash13(id.x * 467.983 + id.y * 1294.387) - .5) * .8;
vec2 dropUv = gridUv - h.xy;
vec4 noise = texture(DropsNoise, id * .05, 0.);
float drop = smoothstep(.25, 0., length(dropUv)) *
max(0., 1. - fract(time * (noise.b + .1) * .2 + noise.g) * 2.);
return drop;
}
vec2 wigglyDrops(vec2 st, float time, float size, vec2 scale)
{
vec2 wigglyDropAspect = vec2(2., 1.);
vec2 uv = st * size * wigglyDropAspect;
uv.x *= scale.x / scale.y;
uv.y += time * .23;
vec2 gridUv = fract(uv) - .5; // rectangular grid
vec2 id = floor(uv);
float h = hash21(id);
time += h * 2. * PI;
float w = st.y * 10.;
float dx = (h - .5) * .8;
dx += (.3 - abs(dx)) * pow(sin(w), 2.) * sin(2. * w) *
pow(cos(w), 3.) * 1.05; // wiggle
float dy = -sin(time + sin(time + sin(time) * .5)) * .45; // slow down drop before continuing falling
dy -= (gridUv.x - dx) * (gridUv.x - dx);
vec2 dropUv = (gridUv - vec2(dx, dy)) / wigglyDropAspect;
float drop = smoothstep(.06, .0, length(dropUv));
vec2 trailUv = (gridUv - vec2(dx, time * .23)) / wigglyDropAspect;
trailUv.y = (fract((trailUv.y) * 8.) - .5) / 8.;
float trailDrop = smoothstep(.03, .0, length(trailUv));
trailDrop *= smoothstep(-.05, .05, dropUv.y) * smoothstep(.4, dy, gridUv.y) *
(1.-step(.4, gridUv.y));
float fogTrail = smoothstep(-.05, .05, dropUv.y) * smoothstep(.4, dy, gridUv.y) *
smoothstep(.05, .01, abs(dropUv.x)) * (1.-step(.4, gridUv.y));
return vec2(drop + trailDrop, fogTrail);
}
vec2 getDrops(vec2 st, float time, vec2 scale)
{
vec2 largeDrops = wigglyDrops(st, time * 2., 1.6, scale);
vec2 mediumDrops = wigglyDrops(st + 2.65, (time + 1296.675) * 1.4, 2.5, scale);
vec2 smallDrops = wigglyDrops(st - 1.67, time - 896.431, 3.6, scale);
vec2 drops;
drops.y = max(largeDrops.y, max(mediumDrops.y, smallDrops.y));
drops.x = smoothstep(.4, 2., largeDrops.x + mediumDrops.x + smallDrops.x);
return drops;
}
vec2 dropsUV(vec2 uv, float _time) {
vec2 st = uv;
vec2 scale = vec2(1);
float time = mod(100000. - _time, 7200.);
vec2 drops = getDrops(st, time, scale);
vec2 offset = drops.xy;
vec2 dropsX = getDrops(st + vec2(.001, 0.), time, scale);
vec2 dropsY = getDrops(st + vec2(0., .001), time, scale);
vec3 normal = vec3(dropsX.x - drops.x, dropsY.x - drops.x, 0.);
normal.z = sqrt(1. - normal.x * normal.x - normal.y * normal.y);
normal = normalize(normal);
//vec2 uv_offset = st+normal.xy * 3.;
return normal.xy;
}


Thank you!!