header_utils
Loading...
Searching...
No Matches
noise.h
1
4
5#pragma once
6
7#include "min-cpp-version/cpp17.h"
8#include <cstdint>
9
11
13{
14
18
19 template <typename F>
20 [[nodiscard]] constexpr F simplex_noise(F x) noexcept;
21
22 template <typename F>
23 [[nodiscard]] constexpr F simplex_noise(F x, F y) noexcept;
24
25 template <typename F>
26 [[nodiscard]] constexpr F fractal_simplex_noise(size_t octaves, F x, F frequency = F(1.0), F amplitude = F(1.0), F lacunarity = F(2.0), F persistence = F(0.5)) noexcept;
27
28 template <typename F>
29 [[nodiscard]] constexpr F fractal_simplex_noise_2d(size_t octaves, F x, F y, F frequency = F(1.0), F amplitude = F(1.0), F lacunarity = F(2.0), F persistence = F(0.5)) noexcept;
30
32}
33
35
36namespace ghassanpl::noise
37{
38
39 namespace detail
40 {
41 template <typename F>
42 constexpr int32_t fastfloor(F fp) noexcept
43 {
44 const auto i = static_cast<int32_t>(fp);
45 return (fp < i) ? (i - 1) : i;
46 }
47
48 constexpr inline uint8_t perm[256] = {
49 151, 160, 137, 91, 90, 15,
50 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,
51 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
52 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
53 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,
54 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
55 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
56 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,
57 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
58 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,
59 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,
60 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,
61 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180
62 };
63
64 constexpr uint8_t hash(int32_t i) noexcept
65 {
66 return perm[static_cast<uint8_t>(i)];
67 }
68
69 template <typename F>
70 constexpr F grad(int32_t hash, F x) noexcept
71 {
72 const int32_t h = hash & 0x0F; // Convert low 4 bits of hash code
73 F grad = F(1.0) + (h & 7); // Gradient value 1.0, 2.0, ..., 8.0
74 if ((h & 8) != 0) grad = -grad; // Set a random sign for the gradient
75 return (grad * x); // Multiply the gradient with the distance
76 }
77
78 template <typename F>
79 constexpr F grad(int32_t hash, F x, F y) noexcept
80 {
81 const int32_t h = hash & 0x3F; // Convert low 3 bits of hash code
82 const F u = h < 4 ? x : y; // into 8 simple gradient directions,
83 const F v = h < 4 ? y : x;
84 return ((h & 1) ? -u : u) + ((h & 2) ? F(-2.0) * v : F(2.0) * v); // and compute the dot product with (x,y).
85 }
86
87 template <typename F>
88 constexpr F grad(int32_t hash, F x, F y, F z) noexcept
89 {
90 const int h = hash & 15; // Convert low 4 bits of hash code into 12 simple
91 const F u = h < 8 ? x : y; // gradient directions, and compute dot product.
92 const F v = h < 4 ? y : h == 12 || h == 14 ? x : z; // Fix repeats at h = 12 to 15
93 return ((h & 1) ? -u : u) + ((h & 2) ? -v : v);
94 }
95 }
96
97 template <typename F>
98 [[nodiscard]] constexpr F simplex_noise(F x) noexcept
99 {
100 static_assert(std::is_floating_point_v<F>, "simplex_noise only works with floating point arguments");
101
102 int32_t i0 = detail::fastfloor(x);
103 int32_t i1 = i0 + 1;
104
105 F x0 = x - i0;
106 F x1 = x0 - F(1.0);
107
108 F t0 = F(1.0) - x0 * x0;
109
110 t0 *= t0;
111 F n0 = t0 * t0 * detail::grad(detail::hash(i0), x0);
112
113 F t1 = F(1.0) - x1 * x1;
114
115 t1 *= t1;
116 F n1 = t1 * t1 * detail::grad(detail::hash(i1), x1);
117
118 return F(0.395) * (n0 + n1);
119 }
120
121 template <typename F>
122 [[nodiscard]] constexpr F simplex_noise(F x, F y) noexcept
123 {
124 static_assert(std::is_floating_point_v<F>, "simplex_noise only works with floating point arguments");
125
126 constexpr F F2 = F(0.366025403); // F2 = (sqrt(3) - 1) / 2
127 constexpr F G2 = F(0.211324865); // G2 = (3 - sqrt(3)) / 6 = F2 / (1 + 2 * K)
128
129 const F s = (x + y) * F2;
130 const F xs = x + s;
131 const F ys = y + s;
132 const int32_t i = fastfloor(xs);
133 const int32_t j = fastfloor(ys);
134
135 const F t = static_cast<F>(i + j) * G2;
136 const F X0 = i - t;
137 const F Y0 = j - t;
138 const F x0 = x - X0;
139 const F y0 = y - Y0;
140
141 int32_t i1 = 0;
142 int32_t j1 =0;
143 if (x0 > y0) {
144 i1 = 1;
145 j1 = 0;
146 }
147 else {
148 i1 = 0;
149 j1 = 1;
150 }
151
152 const F x1 = x0 - i1 + G2;
153 const F y1 = y0 - j1 + G2;
154 const F x2 = x0 - F(1.0) + F(2.0) * G2;
155 const F y2 = y0 - F(1.0) + F(2.0) * G2;
156
157 const int gi0 = hash(i + hash(j));
158 const int gi1 = hash(i + i1 + hash(j + j1));
159 const int gi2 = hash(i + 1 + hash(j + 1));
160
161 F n0;
162 if (F t0 = F(0.5) - x0 * x0 - y0 * y0; t0 < F(0.0))
163 n0 = F(0.0);
164 else {
165 t0 *= t0;
166 n0 = t0 * t0 * grad(gi0, x0, y0);
167 }
168
169 F n1;
170 if (F t1 = F(0.5) - x1 * x1 - y1 * y1; t1 < F(0.0))
171 n1 = F(0.0);
172 else {
173 t1 *= t1;
174 n1 = t1 * t1 * grad(gi1, x1, y1);
175 }
176
177 F n2;
178 if (F t2 = F(0.5) - x2 * x2 - y2 * y2; t2 < F(0.0))
179 n2 = F(0.0);
180 else {
181 t2 *= t2;
182 n2 = t2 * t2 * grad(gi2, x2, y2);
183 }
184
185 return F(45.23065) * (n0 + n1 + n2);
186 }
187
188 template <typename F>
189 [[nodiscard]] constexpr F fractal_simplex_noise(size_t octaves, F x, F frequency, F amplitude, F lacunarity, F persistence) noexcept
190 {
191 static_assert(std::is_floating_point_v<F>, "fractal_simplex_noise only works with floating point arguments");
192
193 F output = 0;
194 F denom = 0;
195
196 for (size_t i = 0; i < octaves; i++)
197 {
198 output += (amplitude * simplex_noise(x * frequency));
199 denom += amplitude;
200
201 frequency *= lacunarity;
202 amplitude *= persistence;
203 }
204
205 return (output / denom);
206 }
207
208 template <typename F>
209 [[nodiscard]] constexpr F fractal_simplex_noise_2d(size_t octaves, F x, F y, F frequency, F amplitude, F lacunarity, F persistence) noexcept
210 {
211 static_assert(std::is_floating_point_v<F>, "fractal_simplex_noise only works with floating point arguments");
212
213 F output = 0;
214 F denom = 0;
215
216 for (size_t i = 0; i < octaves; i++)
217 {
218 output += (amplitude * simplex_noise(x * frequency, y * frequency));
219 denom += amplitude;
220
221 frequency *= lacunarity;
222 amplitude *= persistence;
223 }
224
225 return (output / denom);
226 }
227
228}
void output(OUTFUNC &&out, wilson const &value, output_parameters const &parameters={}, size_t indent=0)
Outputs value formatted as a string using the out function which should take a string_view to append ...
Definition wilson.h:391
The below code is based on Sun's libm library code, which is licensed under the following license:
Shamelessly stolen from https://github.com/SRombauts/SimplexNoise/.
Definition noise.h:13