1#[inline(always)]
2fn lerp(a: f32, b: f32, t: f32) -> f32 {
3 return (b - a) * t + a;
4}
5#[inline(always)]
6fn smoothstep(a: f32, b: f32, t: f32) -> f32 {
7 return (b - a) * (t * (t * 6.0 - 15.0) + 10.0) * t * t * t + a;
8}
9
10pub struct NoiseGenerator {
11 permutations: [i32; 256],
12}
13impl NoiseGenerator {
14 pub fn new(seed: u64) -> Self {
15 const A: u64 = 6364136223846793005;
16 const C: u64 = 1442695040888963407;
17 let mut seed = seed;
18 let mut rand = || {
19 seed = A.wrapping_mul(seed).wrapping_add(C);
20 seed
21 };
22
23 let mut permutations = [0i32; 256];
24 for i in 0..256 {
25 permutations[i] = rand() as i32;
26 }
27 Self { permutations }
28 }
29 fn randomize_2_f(&self, x: i32, y: i32) -> f32 {
30 let sum = y.wrapping_mul(506791837).wrapping_add(x);
31 (self.permutations[(sum & 0x000000ff) as usize]
37 .wrapping_add(self.permutations[(sum >> 8 & 0x000000ff) as usize])
38 .wrapping_add(self.permutations[(sum >> 16 & 0x000000ff) as usize])
39 .wrapping_add(self.permutations[(sum >> 24 & 0x000000ff) as usize])
40 % 123456) as f32
41 / 123456.0
42 }
43 fn random_gradient(&self, x: i32, y: i32) -> [f32; 2] {
44 let sum = y.wrapping_mul(506791837).wrapping_add(x);
45 let dir = (self.permutations[(sum & 0x000000ff) as usize]
46 .wrapping_add(self.permutations[(sum >> 8 & 0x000000ff) as usize])
47 .wrapping_add(self.permutations[(sum >> 16 & 0x000000ff) as usize])
48 .wrapping_add(self.permutations[(sum >> 24 & 0x000000ff) as usize])
49 % 123456) as f32
50 / 123456.0
51 * std::f32::consts::PI
52 * 8.0;
53 [dir.cos(), dir.sin()]
54 }
55 fn dot_gradient(&self, xi: i32, yi: i32, x: f32, y: f32) -> f32 {
56 let gradient = self.random_gradient(xi, yi);
57 let dx = xi as f32 - x;
58 let dy = yi as f32 - y;
59 dx * gradient[0] + dy * gradient[1]
60 }
61 pub fn perlin(&self, x: f32, y: f32) -> f32 {
62 let xff = x.floor();
63 let yff = y.floor();
64 let xf = xff as i32;
65 let yf = yff as i32;
66 let xc = xf + 1;
67 let yc = yf + 1;
68 let xo = x - xff;
69 let yo = y - yff;
70
71 smoothstep(
72 smoothstep(
73 self.dot_gradient(xf, yf, x, y),
74 self.dot_gradient(xc, yf, x, y),
75 xo,
76 ),
77 smoothstep(
78 self.dot_gradient(xf, yc, x, y),
79 self.dot_gradient(xc, yc, x, y),
80 xo,
81 ),
82 yo,
83 ) * std::f32::consts::SQRT_2
84 }
85 pub fn perlin_octaves(&self, x: f32, y: f32, octaves: usize, gain: f32) -> f32 {
86 let mut sum = 0.0;
87 let mut scale = 1.0;
88 for _ in 0..octaves {
89 sum = lerp(sum, self.perlin(x / scale, y / scale), scale);
90 scale *= gain;
91 }
92 sum
93 }
94 pub fn value(&self, x: f32, y: f32) -> f32 {
95 let xff = x.floor();
96 let yff = y.floor();
97 let xf = xff as i32;
98 let yf = yff as i32;
99 let xc = xf + 1;
100 let yc = yf + 1;
101 let xo = x - xff;
102 let yo = y - yff;
103
104 return lerp(
105 lerp(self.randomize_2_f(xf, yf), self.randomize_2_f(xc, yf), xo),
106 lerp(self.randomize_2_f(xf, yc), self.randomize_2_f(xc, yc), xo),
107 yo,
108 );
109 }
110 pub fn value_octaves(&self, x: f32, y: f32, octaves: usize, gain: f32) -> f32 {
111 let mut sum = 0.0;
112 let mut scale = 1.0;
113 for _ in 0..octaves {
114 sum = lerp(sum, self.value(x / scale, y / scale), scale);
115 scale *= gain;
116 }
117 sum
118 }
119}