File size: 7,237 Bytes
18a519f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
// Cellular noise ("Worley noise") in 3D in GLSL.
// Copyright (c) Stefan Gustavson 2011-04-19. All rights reserved.
// This code is released under the conditions of the MIT license.
// See LICENSE file for details.
// https://github.com/stegu/webgl-noise

using static Unity.Mathematics.math;

namespace Unity.Mathematics
{
    public static partial class noise
    {
        /// <summary>
        /// 3D Cellular noise ("Worley noise") with 3x3x3 search region for good F2 everywhere, but a lot slower than the 2x2x2 version.
        /// </summary>
        /// <param name="P">A point in 2D space.</param>
        /// <returns>Feature points. F1 is in the x component, F2 in the y component.</returns>
        // The code below is a bit scary even to its author,
        // but it has at least half decent performance on a
        // math.modern GPU. In any case, it beats any software
        // implementation of Worley noise hands down.

        public static float2 cellular(float3 P)
        {
            const float K = 0.142857142857f; // 1/7
            const float Ko = 0.428571428571f; // 1/2-K/2
            const float K2 = 0.020408163265306f; // 1/(7*7)
            const float Kz = 0.166666666667f; // 1/6
            const float Kzo = 0.416666666667f; // 1/2-1/6*2
            const float jitter = 1.0f; // smaller jitter gives more regular pattern

            float3 Pi = mod289(floor(P));
            float3 Pf = frac(P) - 0.5f;

            float3 Pfx = Pf.x + float3(1.0f, 0.0f, -1.0f);
            float3 Pfy = Pf.y + float3(1.0f, 0.0f, -1.0f);
            float3 Pfz = Pf.z + float3(1.0f, 0.0f, -1.0f);

            float3 p = permute(Pi.x + float3(-1.0f, 0.0f, 1.0f));
            float3 p1 = permute(p + Pi.y - 1.0f);
            float3 p2 = permute(p + Pi.y);
            float3 p3 = permute(p + Pi.y + 1.0f);

            float3 p11 = permute(p1 + Pi.z - 1.0f);
            float3 p12 = permute(p1 + Pi.z);
            float3 p13 = permute(p1 + Pi.z + 1.0f);

            float3 p21 = permute(p2 + Pi.z - 1.0f);
            float3 p22 = permute(p2 + Pi.z);
            float3 p23 = permute(p2 + Pi.z + 1.0f);

            float3 p31 = permute(p3 + Pi.z - 1.0f);
            float3 p32 = permute(p3 + Pi.z);
            float3 p33 = permute(p3 + Pi.z + 1.0f);

            float3 ox11 = frac(p11 * K) - Ko;
            float3 oy11 = mod7(floor(p11 * K)) * K - Ko;
            float3 oz11 = floor(p11 * K2) * Kz - Kzo; // p11 < 289 guaranteed

            float3 ox12 = frac(p12 * K) - Ko;
            float3 oy12 = mod7(floor(p12 * K)) * K - Ko;
            float3 oz12 = floor(p12 * K2) * Kz - Kzo;

            float3 ox13 = frac(p13 * K) - Ko;
            float3 oy13 = mod7(floor(p13 * K)) * K - Ko;
            float3 oz13 = floor(p13 * K2) * Kz - Kzo;

            float3 ox21 = frac(p21 * K) - Ko;
            float3 oy21 = mod7(floor(p21 * K)) * K - Ko;
            float3 oz21 = floor(p21 * K2) * Kz - Kzo;

            float3 ox22 = frac(p22 * K) - Ko;
            float3 oy22 = mod7(floor(p22 * K)) * K - Ko;
            float3 oz22 = floor(p22 * K2) * Kz - Kzo;

            float3 ox23 = frac(p23 * K) - Ko;
            float3 oy23 = mod7(floor(p23 * K)) * K - Ko;
            float3 oz23 = floor(p23 * K2) * Kz - Kzo;

            float3 ox31 = frac(p31 * K) - Ko;
            float3 oy31 = mod7(floor(p31 * K)) * K - Ko;
            float3 oz31 = floor(p31 * K2) * Kz - Kzo;

            float3 ox32 = frac(p32 * K) - Ko;
            float3 oy32 = mod7(floor(p32 * K)) * K - Ko;
            float3 oz32 = floor(p32 * K2) * Kz - Kzo;

            float3 ox33 = frac(p33 * K) - Ko;
            float3 oy33 = mod7(floor(p33 * K)) * K - Ko;
            float3 oz33 = floor(p33 * K2) * Kz - Kzo;

            float3 dx11 = Pfx + jitter * ox11;
            float3 dy11 = Pfy.x + jitter * oy11;
            float3 dz11 = Pfz.x + jitter * oz11;

            float3 dx12 = Pfx + jitter * ox12;
            float3 dy12 = Pfy.x + jitter * oy12;
            float3 dz12 = Pfz.y + jitter * oz12;

            float3 dx13 = Pfx + jitter * ox13;
            float3 dy13 = Pfy.x + jitter * oy13;
            float3 dz13 = Pfz.z + jitter * oz13;

            float3 dx21 = Pfx + jitter * ox21;
            float3 dy21 = Pfy.y + jitter * oy21;
            float3 dz21 = Pfz.x + jitter * oz21;

            float3 dx22 = Pfx + jitter * ox22;
            float3 dy22 = Pfy.y + jitter * oy22;
            float3 dz22 = Pfz.y + jitter * oz22;

            float3 dx23 = Pfx + jitter * ox23;
            float3 dy23 = Pfy.y + jitter * oy23;
            float3 dz23 = Pfz.z + jitter * oz23;

            float3 dx31 = Pfx + jitter * ox31;
            float3 dy31 = Pfy.z + jitter * oy31;
            float3 dz31 = Pfz.x + jitter * oz31;

            float3 dx32 = Pfx + jitter * ox32;
            float3 dy32 = Pfy.z + jitter * oy32;
            float3 dz32 = Pfz.y + jitter * oz32;

            float3 dx33 = Pfx + jitter * ox33;
            float3 dy33 = Pfy.z + jitter * oy33;
            float3 dz33 = Pfz.z + jitter * oz33;

            float3 d11 = dx11 * dx11 + dy11 * dy11 + dz11 * dz11;
            float3 d12 = dx12 * dx12 + dy12 * dy12 + dz12 * dz12;
            float3 d13 = dx13 * dx13 + dy13 * dy13 + dz13 * dz13;
            float3 d21 = dx21 * dx21 + dy21 * dy21 + dz21 * dz21;
            float3 d22 = dx22 * dx22 + dy22 * dy22 + dz22 * dz22;
            float3 d23 = dx23 * dx23 + dy23 * dy23 + dz23 * dz23;
            float3 d31 = dx31 * dx31 + dy31 * dy31 + dz31 * dz31;
            float3 d32 = dx32 * dx32 + dy32 * dy32 + dz32 * dz32;
            float3 d33 = dx33 * dx33 + dy33 * dy33 + dz33 * dz33;

            // Sort out the two smallest distances (F1, F2)
            // Do it right and sort out both F1 and F2
            float3 d1a = min(d11, d12);
            d12 = max(d11, d12);
            d11 = min(d1a, d13); // Smallest now not in d12 or d13
            d13 = max(d1a, d13);
            d12 = min(d12, d13); // 2nd smallest now not in d13
            float3 d2a = min(d21, d22);
            d22 = max(d21, d22);
            d21 = min(d2a, d23); // Smallest now not in d22 or d23
            d23 = max(d2a, d23);
            d22 = min(d22, d23); // 2nd smallest now not in d23
            float3 d3a = min(d31, d32);
            d32 = max(d31, d32);
            d31 = min(d3a, d33); // Smallest now not in d32 or d33
            d33 = max(d3a, d33);
            d32 = min(d32, d33); // 2nd smallest now not in d33
            float3 da = min(d11, d21);
            d21 = max(d11, d21);
            d11 = min(da, d31); // Smallest now in d11
            d31 = max(da, d31); // 2nd smallest now not in d31
            d11.xy = (d11.x < d11.y) ? d11.xy : d11.yx;
            d11.xz = (d11.x < d11.z) ? d11.xz : d11.zx; // d11.x now smallest
            d12 = min(d12, d21); // 2nd smallest now not in d21
            d12 = min(d12, d22); // nor in d22
            d12 = min(d12, d31); // nor in d31
            d12 = min(d12, d32); // nor in d32
            d11.yz = min(d11.yz, d12.xy); // nor in d12.yz
            d11.y = min(d11.y, d12.z); // Only two more to go
            d11.y = min(d11.y, d11.z); // Done! (Phew!)
            return sqrt(d11.xy); // F1, F2
        }
    }
}