-
Notifications
You must be signed in to change notification settings - Fork 15
/
Rain.sksl
223 lines (173 loc) · 6.69 KB
/
Rain.sksl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
uniform float3 iResolution; // Viewport resolution (pixels)
uniform float iTime; // Shader playback time (s)
uniform float4 iMouse; // Mouse drag pos=.xy Click pos=.zw (pixels)
uniform float3 iImage1Resolution; // iImage1 resolution (pixels)
uniform shader iImage1; // An input image.
// Heartfelt - by Martijn Steinrucken aka BigWings - 2017
// Email:[email protected] Twitter:@The_ArtOfCode
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// Original: https://www.shadertoy.com/view/ltffzl
// I revisited the rain effect I did for another shader. This one is better in multiple ways:
// 1. The glass gets foggy.
// 2. Drops cut trails in the fog on the glass.
// 3. The amount of rain is adjustable (with Mouse.y)
// To have full control over the rain, uncomment the HAS_HEART define
// A video of the effect can be found here:
// https://www.youtube.com/watch?v=uiF5Tlw22PI&feature=youtu.be
// Music - Alone In The Dark - Vadim Kiselev
// https://soundcloud.com/ahmed-gado-1/sad-piano-alone-in-the-dark
// Rain sounds:
// https://soundcloud.com/elirtmusic/sleeping-sound-rain-and-thunder-1-hours
const bool HAS_HEART = false;
const bool USE_POST_PROCESSING = true;
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 smoothstep(0., b, t)*smoothstep(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 = (Saw(.85, ti)-.5)*.9+.5;
vec2 p = vec2(x, y);
float d = length((st-p)*a.yx);
float mainDrop = smoothstep(.4, .0, d);
float r = sqrt(smoothstep(1., y, st.y));
float cd = abs(st.x-x);
float trail = smoothstep(.23*r, .15*r*r, cd);
float trailFront = smoothstep(-.02, .02, st.y-y);
trail *= trailFront*r*r;
y = UV.y;
float trail2 = smoothstep(.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 = smoothstep(.3, 0., dd);
float m = mainDrop+droplets*r*trailFront;
//m += st.x>a.y*.45 || st.y>a.x*.165 ? 1.2 : 0.;
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 = smoothstep(.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 = smoothstep(.3, 1., c);
return vec2(c, max(m1.y*l0, m2.y*l1));
}
vec4 main( in vec2 fragCoord )
{
// Vertical flip for GlSL to SkSL
fragCoord.y = iResolution.y - fragCoord.y;
vec2 uv = (fragCoord.xy-.5*iResolution.xy) / iResolution.y;
vec2 UV = fragCoord.xy/iResolution.xy;
vec3 M = iMouse.xyz/iResolution.xyz;
float T = iTime+M.x*2.;
if(HAS_HEART)
{
T = mod(iTime, 102.);
T = mix(T, M.x*102., M.z>0.?1.:0.);
}
float t = T*.2;
float rainAmount = iMouse.z>0. ? M.y : sin(T*.05)*.3+.7;
float maxBlur = mix(3., 6., rainAmount);
float minBlur = 2.;
float story = 0.;
float heart = 0.;
float zoom = 0.;
if(HAS_HEART)
{
story = smoothstep(0., 70., T);
t = min(1., T/70.); // remap drop time so it goes slower when it freezes
t = 1.-t;
t = (1.-t*t)*70.;
zoom= mix(.3, 1.2, story); // slowly zoom out
uv *=zoom;
minBlur = 4.+smoothstep(.5, 1., story)*3.; // more opaque glass towards the end
maxBlur = 6.+smoothstep(.5, 1., story)*1.5;
vec2 hv = uv-vec2(.0, -.1); // build heart
hv.x *= .5;
float s = smoothstep(110., 70., T); // heart gets smaller and fades towards the end
hv.y-=sqrt(abs(hv.x))*.5*s;
heart = length(hv);
heart = smoothstep(.4*s, .2*s, heart)*s;
rainAmount = heart; // the rain is where the heart is
maxBlur-=heart; // inside the heart slighly less foggy
uv *= 1.5; // zoom out a bit more
t *= .25;
}
else
{
zoom = -cos(T*.2);
uv *= .7+zoom*.3;
}
UV = (UV-.5)*(.9+zoom*.1)+.5;
float staticDrops = smoothstep(-.5, 1., rainAmount)*2.;
float layer1 = smoothstep(.25, .75, rainAmount);
float layer2 = smoothstep(.0, .5, rainAmount);
vec2 c = Drops(uv, t, staticDrops, layer1, layer2);
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
if(HAS_HEART) {
n *= 1.-smoothstep(60., 85., T);
c.y *= 1.-smoothstep(80., 100., T)*.8;
}
float focus = mix(maxBlur-c.y, minBlur, smoothstep(.1, .2, c.x));
vec3 col = iImage1.eval(UV+n).rgb * iImage1.eval(vec2(focus)).rgb;
// The above is a mistranslation of
// vec3 col = textureLod(iChannel0, UV+n, focus).rgb;
if (USE_POST_PROCESSING) {
t = (T+3.)*.5; // make time sync with first lightnoing
float colFade = sin(t*.2)*.5+.5+story;
col *= mix(vec3(1.), vec3(.8, .9, 1.3), colFade); // subtle color shift
float fade = smoothstep(0., 10., T); // fade in at the start
float lightning = sin(t*sin(t*10.)); // lighting flicker
lightning *= pow(max(0., sin(t+sin(t))), 10.); // lightning flash
col *= 1.+lightning*fade*mix(1., .1, story*story); // composite lightning
col *= 1.-dot(UV-=.5, UV); // vignette
if(HAS_HEART) {
col = mix(pow(col, vec3(1.2)), col, heart);
fade *= smoothstep(102., 97., T);
}
col *= fade; // composite start and end fade
}
//col = vec3(heart);
return( vec4(col, 1.));
}