1#version 150
2
3uniform UBO
4{
5   mat4 MVP;
6   vec2 OutputSize;
7   float time;
8} global;
9
10layout(location = 0) out vec4 FragColor;
11
12const float baseScale = 3.5;  //  [1.0  .. 10.0]
13const float density   = 0.7;  //  [0.01 ..  1.0]
14const float speed     = 0.25; //  [0.1  ..  1.0]
15
16float rand(vec2 co)
17{
18   return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
19}
20
21float dist_func(vec2 distv)
22{
23   float dist = sqrt((distv.x * distv.x) + (distv.y * distv.y)) * (40.0 / baseScale);
24   dist = clamp(dist, 0.0, 1.0);
25   return cos(dist * (3.14159265358 * 0.5)) * 0.5;
26}
27
28float random_dots(vec2 co)
29{
30   float part = 1.0 / 20.0;
31   vec2 cd = floor(co / part);
32   float p = rand(cd);
33
34   if (p > 0.005 * (density * 40.0))
35      return 0.0;
36
37   vec2 dpos = (vec2(fract(p * 2.0) , p) + vec2(2.0, 2.0)) * 0.25;
38
39   vec2 cellpos = fract(co / part);
40   vec2 distv = (cellpos - dpos);
41
42   return dist_func(distv);
43}
44
45float snow(vec2 pos, float time, float scale)
46{
47   // add wobble
48   pos.x += cos(pos.y * 1.2 + time * 3.14159 * 2.0 + 1.0 / scale) / (8.0 / scale) * 4.0;
49   // add gravity
50   pos += time * scale * vec2(-0.5, 1.0) * 4.0;
51   return random_dots(pos / scale) * (scale * 0.5 + 0.5);
52}
53
54void main(void)
55{
56   float tim = global.time * 0.4 * speed;
57   vec2 pos = gl_FragCoord.xy / global.OutputSize.xx;
58   pos.y = 1.0 - pos.y; // Flip Y
59   float a = 0.0;
60   // Each of these is a layer of snow
61   // Remove some for better performance
62   // Changing the scale (3rd value) will mess with the looping
63   a += snow(pos, tim, 1.0);
64   a += snow(pos, tim, 0.7);
65   a += snow(pos, tim, 0.6);
66   a += snow(pos, tim, 0.5);
67   a += snow(pos, tim, 0.4);
68   a += snow(pos, tim, 0.3);
69   a += snow(pos, tim, 0.25);
70   a += snow(pos, tim, 0.125);
71   a = a * min(pos.y * 4.0, 1.0);
72   FragColor = vec4(1.0, 1.0, 1.0, a);
73}
74