1// Credit: Patricio Gonzalez 2015 https://thebookofshaders.com/13/
2
3let
4    random xy = frac(sin(dot[xy, [12.9898,78.233]])*43758.5453123);
5
6    // Based on Morgan McGuire @morgan3d
7    // https://www.shadertoy.com/view/4dS3Wd
8    noise xy =
9        let i = floor xy;
10            f = xy - i;
11
12            // Four corners in 2D of a tile
13            a = random(i);
14            b = random(i + [1, 0]);
15            c = random(i + [0, 1]);
16            d = random(i + [1, 1]);
17
18            u = f * f * (3 - 2 * f);
19
20        in lerp[a, b, u.[X]] +
21            (c - a) * u.[Y] * (1 - u.[X]) +
22            (d - b) * u.[X] * u.[Y];
23
24    fbm xy =
25        let shift = [100,100];
26            rot = cis(0.5);   // Rotate to reduce axial bias
27            st = xy;
28            v = 0;
29            a = 0.5;
30        in do
31            for (i in 1..5) (
32                v := v + a * noise st;
33                st := cmul[rot, st] * 2 + shift;
34                a := a * 0.5;
35            );
36        in v;
37
38    smoke [x,y,z,t] =
39        let st = [x,y];
40            q = [ fbm(st), fbm(st + 1) ];
41            r = [ fbm(st + q + [1.7,9.2] + 0.150*t),
42                  fbm(st + q + [8.3,2.8] + 0.126*t) ];
43            f = fbm(st + r);
44            c = lerp[[0.101961,0.619608,0.666667],
45                     [0.666667,0.666667,0.498039],
46                     clamp[f*f*4, 0, 1]];
47        in do
48            c := lerp[c,
49                     [0,0,0.164706],
50                     clamp[mag q, 0, 1]];
51            c := lerp[c,
52                     [0.666667,1,1],
53                     clamp[r.[X], 0, 1]];
54        in (f*f*f+.6*f*f+.5*f)*c;
55
56in
57circle 2 >> colour smoke
58