/*! par-term shader metadata
name: rain
author: null
description: null
version: 1.0.0
defaults:
animation_speed: 0.5
channel0: textures/wallpaper/MagicMushrooms.png
channel1: null
channel2: null
channel3: null
cubemap: ''
cubemap_enabled: false
use_background_as_channel0: null
uniforms:
iDropScale: 1.0
iFogAmount: 0.0
iFogClearAmount: 0.79999995
iFogColor: '#b3bfcc'
iPostAmount: 1.0
iRainAmount: 0.7
iRainPulse: 0.29999998
iRainSpeed: 1.0
iRefractionStrength: 1.0
iVignetteAmount: 1.0
*/
// Rain on Glass - based on Heartfelt by Martijn Steinrucken aka BigWings - 2017
// Modified to remove heart, lightning, and mouse effects
// Original: https://www.shadertoy.com/view/ltffzl
// control slider min=0 max=1 step=0.01 label="Rain Amount"
uniform float iRainAmount;
// control slider min=0 max=1 step=0.01 label="Rain Pulse"
uniform float iRainPulse;
// control slider min=0 max=3 step=0.01 label="Rain Speed"
uniform float iRainSpeed;
// control slider min=0.5 max=2 step=0.01 label="Drop Scale"
uniform float iDropScale;
// control slider min=0 max=2 step=0.01 label="Refraction"
uniform float iRefractionStrength;
// control slider min=0 max=1 step=0.01 label="Fog Amount"
uniform float iFogAmount;
// control slider min=0 max=1 step=0.01 label="Fog Clearing"
uniform float iFogClearAmount;
// control color label="Fog Color"
uniform vec3 iFogColor;
// control slider min=0 max=1 step=0.01 label="Color Shift"
uniform float iPostAmount;
// control slider min=0 max=1 step=0.01 label="Vignette"
uniform float iVignetteAmount;
#define S(a, b, t) smoothstep(a, b, t)
//#define CHEAP_NORMALS
#define USE_POST_PROCESSING
vec3 N13(float p) {
// from DAVE HOSKINS
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));
}
vec4 N14(float t) {
return fract(sin(t*vec4(123., 1024., 1456., 264.))*vec4(6547., 345., 8799., 1564.));
}
float N(float t) {
return fract(sin(t*12345.564)*7658.76);
}
float Saw(float b, float t) {
return S(0., b, t)*S(1., b, t);
}
vec2 DropLayer2(vec2 uv, float t) {
vec2 UV = uv;
uv.y -= t*0.75;
vec2 a = vec2(6., 1.);
vec2 grid = a*2.;
vec2 id = floor(uv*grid);
float colShift = N(id.x);
uv.y += colShift;
id = floor(uv*grid);
vec3 n = N13(id.x*35.2+id.y*2376.1);
vec2 st = fract(uv*grid)-vec2(.5, 0);
float x = n.x-.5;
float y = UV.y*20.;
float wiggle = sin(y+sin(y));
x += wiggle*(.5-abs(x))*(n.z-.5);
x *= .7;
float ti = fract(t+n.z);
y = 1.0 - ((Saw(.85, ti)-.5)*.9+.5);
vec2 p = vec2(x, y);
float d = length((st-p)*a.yx);
float mainDrop = S(.4, .0, d);
float r = sqrt(S(0., y, st.y));
float cd = abs(st.x-x);
float trail = S(.23*r, .15*r*r, cd);
float trailFront = S(-.02, .02, y-st.y);
trail *= trailFront*r*r;
y = UV.y;
float trail2 = S(.2*r, .0, cd);
float droplets = max(0., (sin(y*(1.-y)*120.)-st.y))*trail2*trailFront*n.z;
y = fract(y*10.)+(st.y-.5);
float dd = length(st-vec2(x, y));
droplets = S(.3, 0., dd);
float m = mainDrop+droplets*r*trailFront;
return vec2(m, trail);
}
float StaticDrops(vec2 uv, float t) {
uv *= 40.;
vec2 id = floor(uv);
uv = fract(uv)-.5;
vec3 n = N13(id.x*107.45+id.y*3543.654);
vec2 p = (n.xy-.5)*.7;
float d = length(uv-p);
float fade = Saw(.025, fract(t+n.z));
float c = S(.3, 0., d)*fract(n.z*10.)*fade;
return c;
}
vec2 Drops(vec2 uv, float t, float l0, float l1, float l2) {
float s = StaticDrops(uv, t)*l0;
vec2 m1 = DropLayer2(uv, t)*l1;
vec2 m2 = DropLayer2(uv*1.85, t)*l2;
float c = s+m1.x+m2.x;
c = S(.3, 1., c);
return vec2(c, max(m1.y*l0, m2.y*l1));
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = (fragCoord.xy-.5*iResolution.xy) / iResolution.y;
vec2 UV = fragCoord.xy/iResolution.xy;
float T = iTime * max(iRainSpeed, 0.0);
float t = T*.2;
float rainBase = clamp(iRainAmount, 0.0, 1.0);
float rainPulse = clamp(iRainPulse, 0.0, 1.0);
float rainAmount = clamp(sin(T*.05) * rainPulse + rainBase, 0.0, 1.0);
uv *= .7 * clamp(iDropScale, 0.5, 2.0);
UV = (UV-.5)*.9+.5;
float staticDrops = S(-.5, 1., rainAmount)*2.;
float layer1 = S(.25, .75, rainAmount);
float layer2 = S(.0, .5, rainAmount);
vec2 c = Drops(uv, t, staticDrops, layer1, layer2);
#ifdef CHEAP_NORMALS
vec2 n = vec2(dFdx(c.x), dFdy(c.x));// cheap normals (3x cheaper, but 2 times shittier ;))
#else
vec2 e = vec2(.001, 0.);
float cx = Drops(uv+e, t, staticDrops, layer1, layer2).x;
float cy = Drops(uv+e.yx, t, staticDrops, layer1, layer2).x;
vec2 n = vec2(cx-c.x, cy-c.x); // expensive normals
#endif
// Sample background
vec2 refractedUV = clamp(UV + n * clamp(iRefractionStrength, 0.0, 2.0), vec2(0.0), vec2(1.0));
vec3 col = texture(iChannel0, refractedUV).rgb;
// Apply fog effect - drops and trails clear the fog
float fogClearAmount = clamp(iFogClearAmount, 0.0, 1.0);
float fogClear = c.y * fogClearAmount;
fogClear = max(fogClear, S(.1, .3, c.x) * fogClearAmount);
float fogLevel = clamp(iFogAmount, 0.0, 1.0) * (1.0 - fogClear);
col = mix(col, iFogColor, fogLevel);
#ifdef USE_POST_PROCESSING
float postAmount = clamp(iPostAmount, 0.0, 1.0);
float colFade = (sin(t*.2)*.5+.5) * postAmount;
col *= mix(vec3(1.), vec3(.8, .9, 1.3), colFade); // subtle color shift
vec2 vignetteUV = UV - .5;
col *= mix(1.0, 1.0 - dot(vignetteUV, vignetteUV), clamp(iVignetteAmount, 0.0, 1.0));
#endif
fragColor = vec4(col, 1.);
}