1use crate::{
2 base::impl_noise,
3 math::{floor, lerp},
4};
5
6#[cfg(feature = "nightly-simd")]
7use core::simd::{f32x2, f32x4};
8
9#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
11pub struct Perlin;
12
13impl_noise!(234 Perlin);
14
15impl Perlin {
16 #[inline]
17 fn gen2(self, [x, y]: [f32; 2], seed: i32) -> f32 {
18 use crate::from_fast_noise_lite::{floor_to_int, grad2, interp_quintic, PRIME_X, PRIME_Y};
20
21 let mut x0 = floor_to_int(x);
22 let mut y0 = floor_to_int(y);
23
24 let xd0 = x - x0 as f32;
25 let yd0 = y - y0 as f32;
26
27 let xd1 = xd0 - 1.0;
28 let yd1 = yd0 - 1.0;
29
30 let xs = interp_quintic(xd0);
31 let ys = interp_quintic(yd0);
32
33 x0 = x0.wrapping_mul(PRIME_X);
34 y0 = y0.wrapping_mul(PRIME_Y);
35
36 let x1 = x0.wrapping_add(PRIME_X);
37 let y1 = y0.wrapping_add(PRIME_Y);
38
39 let xf0 = lerp(grad2(seed, x0, y0, xd0, yd0), grad2(seed, x1, y0, xd1, yd0), xs);
40 let xf1 = lerp(grad2(seed, x0, y1, xd0, yd1), grad2(seed, x1, y1, xd1, yd1), xs);
41
42 lerp(xf0, xf1, ys) * 1.4247691104677813
43 }
44
45 #[inline]
46 fn gen3(self, [x, y, z]: [f32; 3], seed: i32) -> f32 {
47 use crate::from_fast_noise_lite::{floor_to_int, grad3, interp_quintic, PRIME_X, PRIME_Y, PRIME_Z};
49
50 let mut x0 = floor_to_int(x);
51 let mut y0 = floor_to_int(y);
52 let mut z0 = floor_to_int(z);
53
54 let xd0 = x - x0 as f32;
55 let yd0 = y - y0 as f32;
56 let zd0 = z - z0 as f32;
57
58 let xd1 = xd0 - 1.0;
59 let yd1 = yd0 - 1.0;
60 let zd1 = zd0 - 1.0;
61
62 let xs = interp_quintic(xd0);
63 let ys = interp_quintic(yd0);
64 let zs = interp_quintic(zd0);
65
66 x0 = x0.wrapping_mul(PRIME_X);
67 y0 = y0.wrapping_mul(PRIME_Y);
68 z0 = z0.wrapping_mul(PRIME_Z);
69
70 let x1 = x0.wrapping_add(PRIME_X);
71 let y1 = y0.wrapping_add(PRIME_Y);
72 let z1 = z0.wrapping_add(PRIME_Z);
73
74 let xf00 = lerp(grad3(seed, x0, y0, z0, xd0, yd0, zd0), grad3(seed, x1, y0, z0, xd1, yd0, zd0), xs);
75 let xf10 = lerp(grad3(seed, x0, y1, z0, xd0, yd1, zd0), grad3(seed, x1, y1, z0, xd1, yd1, zd0), xs);
76 let xf01 = lerp(grad3(seed, x0, y0, z1, xd0, yd0, zd1), grad3(seed, x1, y0, z1, xd1, yd0, zd1), xs);
77 let xf11 = lerp(grad3(seed, x0, y1, z1, xd0, yd1, zd1), grad3(seed, x1, y1, z1, xd1, yd1, zd1), xs);
78
79 let yf0 = lerp(xf00, xf10, ys);
80 let yf1 = lerp(xf01, xf11, ys);
81
82 lerp(yf0, yf1, zs) * 0.964921414852142333984375
83 }
84
85 #[inline]
86 fn gen4(self, [x, y, z, w]: [f32; 4], seed: i32) -> f32 {
87 use crate::from_fast_noise_2::{gradient_dot4, hash_primes4, interp_quintic, primes};
89
90 let xs = floor(x);
91 let ys = floor(y);
92 let zs = floor(z);
93 let ws = floor(w);
94
95 let x0 = (xs as i32).wrapping_mul(primes::X);
96 let y0 = (ys as i32).wrapping_mul(primes::Y);
97 let z0 = (zs as i32).wrapping_mul(primes::Z);
98 let w0 = (ws as i32).wrapping_mul(primes::W);
99 let x1 = x0.wrapping_add(primes::X);
100 let y1 = y0.wrapping_add(primes::Y);
101 let z1 = z0.wrapping_add(primes::Z);
102 let w1 = w0.wrapping_add(primes::W);
103
104 let xf0 = x - xs;
105 let yf0 = y - ys;
106 let zf0 = z - zs;
107 let wf0 = w - ws;
108 let xf1 = xf0 - 1.0;
109 let yf1 = yf0 - 1.0;
110 let zf1 = zf0 - 1.0;
111 let wf1 = wf0 - 1.0;
112
113 let xs = interp_quintic(xf0);
114 let ys = interp_quintic(yf0);
115 let zs = interp_quintic(zf0);
116 let ws = interp_quintic(wf0);
117
118 0.964921414852142333984375f32
119 * lerp(
120 lerp(
121 lerp(
122 lerp(
123 gradient_dot4(hash_primes4(seed, x0, y0, z0, w0), xf0, yf0, zf0, wf0),
124 gradient_dot4(hash_primes4(seed, x1, y0, z0, w0), xf1, yf0, zf0, wf0),
125 xs,
126 ),
127 lerp(
128 gradient_dot4(hash_primes4(seed, x0, y1, z0, w0), xf0, yf1, zf0, wf0),
129 gradient_dot4(hash_primes4(seed, x1, y1, z0, w0), xf1, yf1, zf0, wf0),
130 xs,
131 ),
132 ys,
133 ),
134 lerp(
135 lerp(
136 gradient_dot4(hash_primes4(seed, x0, y0, z1, w0), xf0, yf0, zf1, wf0),
137 gradient_dot4(hash_primes4(seed, x1, y0, z1, w0), xf1, yf0, zf1, wf0),
138 xs,
139 ),
140 lerp(
141 gradient_dot4(hash_primes4(seed, x0, y1, z1, w0), xf0, yf1, zf1, wf0),
142 gradient_dot4(hash_primes4(seed, x1, y1, z1, w0), xf1, yf1, zf1, wf0),
143 xs,
144 ),
145 ys,
146 ),
147 zs,
148 ),
149 lerp(
150 lerp(
151 lerp(
152 gradient_dot4(hash_primes4(seed, x0, y0, z0, w1), xf0, yf0, zf0, wf1),
153 gradient_dot4(hash_primes4(seed, x1, y0, z0, w1), xf1, yf0, zf0, wf1),
154 xs,
155 ),
156 lerp(
157 gradient_dot4(hash_primes4(seed, x0, y1, z0, w1), xf0, yf1, zf0, wf1),
158 gradient_dot4(hash_primes4(seed, x1, y1, z0, w1), xf1, yf1, zf0, wf1),
159 xs,
160 ),
161 ys,
162 ),
163 lerp(
164 lerp(
165 gradient_dot4(hash_primes4(seed, x0, y0, z1, w1), xf0, yf0, zf1, wf1),
166 gradient_dot4(hash_primes4(seed, x1, y0, z1, w1), xf1, yf0, zf1, wf1),
167 xs,
168 ),
169 lerp(
170 gradient_dot4(hash_primes4(seed, x0, y1, z1, w1), xf0, yf1, zf1, wf1),
171 gradient_dot4(hash_primes4(seed, x1, y1, z1, w1), xf1, yf1, zf1, wf1),
172 xs,
173 ),
174 ys,
175 ),
176 zs,
177 ),
178 ws,
179 )
180 }
181
182 #[inline]
183 #[cfg(feature = "nightly-simd")]
184 fn gen2a(self, point: f32x2, seed: i32) -> f32 {
185 use crate::from_fast_noise_lite::{floor_to_int, grad2, interp_quintic, splat, PRIME_XY};
187
188 use core::simd::num::SimdInt;
189
190 let v0 = floor_to_int(point);
191 let d0 = point - v0.cast::<f32>();
192 let d1 = d0 - splat(1.0);
193 let vs = interp_quintic(d0);
194 let v0 = v0 * PRIME_XY;
195 let v1 = v0 + PRIME_XY;
196
197 let xf0 = lerp(grad2(seed, v0[0], v0[1], d0[0], d0[1]), grad2(seed, v1[0], v0[1], d1[0], d0[1]), vs[0]);
198 let xf1 = lerp(grad2(seed, v0[0], v1[1], d0[0], d1[1]), grad2(seed, v1[0], v1[1], d1[0], d1[1]), vs[0]);
199
200 lerp(xf0, xf1, vs[1]) * 1.4247691104677813
201 }
202
203 #[inline]
204 #[cfg(feature = "nightly-simd")]
205 fn gen3a(self, point: f32x4, seed: i32) -> f32 {
206 use core::simd::{i32x4, num::SimdInt};
208
209 use crate::from_fast_noise_lite::{floor_to_int, grad3_with_hash, interp_quintic, Index4x4, PRIME_XYZ};
210
211 #[inline(always)]
212 fn create_hash(mut hash: i32x4) -> Index4x4<64> {
213 hash *= i32x4::splat(0x27d4eb2d);
214 hash ^= hash >> i32x4::splat(15);
215 Index4x4::new(hash)
216 }
217
218 let mut v0 = floor_to_int(point);
219 let d0 = point - v0.cast::<f32>();
220 let d1 = d0 - f32x4::splat(1.0);
221 let vs = interp_quintic(d0);
222 v0 *= PRIME_XYZ;
223 let v1 = v0 + PRIME_XYZ;
224
225 let hs = i32x4::from_array([v0[1] ^ v0[2], v1[1] ^ v0[2], v0[1] ^ v1[2], v1[1] ^ v1[2]]);
226
227 let h = create_hash(hs ^ i32x4::splat(v0[0] ^ seed));
228
229 let t0 = f32x4::from_array([
230 grad3_with_hash(h[0], d0[0], d0[1], d0[2]),
231 grad3_with_hash(h[1], d0[0], d1[1], d0[2]),
232 grad3_with_hash(h[2], d0[0], d0[1], d1[2]),
233 grad3_with_hash(h[3], d0[0], d1[1], d1[2]),
234 ]);
235
236 let h = create_hash(hs ^ i32x4::splat(v1[0] ^ seed));
237
238 let t1 = f32x4::from_array([
239 grad3_with_hash(h[0], d1[0], d0[1], d0[2]),
240 grad3_with_hash(h[1], d1[0], d1[1], d0[2]),
241 grad3_with_hash(h[2], d1[0], d0[1], d1[2]),
242 grad3_with_hash(h[3], d1[0], d1[1], d1[2]),
243 ]);
244
245 let vfx = lerp(t0, t1, f32x4::splat(vs[0]));
246
247 let yf0: f32 = lerp(vfx[0], vfx[1], vs[1]);
248 let yf1: f32 = lerp(vfx[2], vfx[3], vs[1]);
249
250 lerp(yf0, yf1, vs[2]) * 0.964921414852142333984375
251 }
252
253 #[inline]
254 #[cfg(feature = "nightly-simd")]
255 fn gen4a(self, point: f32x4, seed: i32) -> f32 {
256 self.gen4(point.into(), seed)
257 }
258}