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;
}
Live Preview
Tags
animated, rain, skin, sweat
This shader is a port from an existing Shadertoy project. Shadertoy shaders are by default protected under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) license unless anything else has been stated by the author. For more info, see our License terms.

More from paper

Related shaders

guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Fame
Fame
8 months ago

Thank you!!