Skip to content
This repository was archived by the owner on Mar 15, 2025. It is now read-only.

Commit 87a4146

Browse files
committed
Added new noise header to generate from 2D up to 4D simplex noises.
1 parent e5fb554 commit 87a4146

File tree

1 file changed

+215
-0
lines changed

1 file changed

+215
-0
lines changed

dang-math/include/dang-math/noise.h

+215
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
#pragma once
2+
3+
#include "dang-math/vector.h"
4+
5+
#include "dang-utils/utils.h"
6+
7+
namespace dang::math::noise {
8+
9+
// Converted from https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
10+
11+
/// @brief A permutation seed, which is used by simplex noise generation.
12+
/// @remark Values wrap around in the range [0..289) and should be integers
13+
struct PermuteFactors {
14+
float f1 = 1.0f;
15+
float f2 = 34.0f;
16+
17+
/// @brief Selects one of the 82944 distinct factors from the given integral seed.
18+
template <typename T>
19+
static PermuteFactors fromSeed(T seed)
20+
{
21+
static_assert(std::is_integral_v<T>);
22+
auto seed_unsigned = static_cast<std::make_unsigned_t<T>>(seed);
23+
auto x = dutils::removeOddBits(seed_unsigned);
24+
auto y = dutils::removeOddBits(seed_unsigned >> 1);
25+
auto a = 1 + x % 288;
26+
auto b = 1 + y % 288;
27+
return {static_cast<float>(a), static_cast<float>(b)};
28+
}
29+
};
30+
31+
namespace detail {
32+
33+
template <std::size_t v_dim>
34+
[[nodiscard]] constexpr vec<v_dim> permute(vec<v_dim> x, const PermuteFactors& factors)
35+
{
36+
return ((x * factors.f2 + factors.f1) * x).mod(289.0f);
37+
}
38+
39+
[[nodiscard]] constexpr float permute(float x, const PermuteFactors& factors) { return permute(vec1(x), factors).x(); }
40+
41+
template <std::size_t v_dim>
42+
[[nodiscard]] constexpr vec<v_dim> taylorInvSqrt(vec<v_dim> r)
43+
{
44+
return 1.79284291400159f - 0.85373472095314f * r;
45+
}
46+
47+
[[nodiscard]] constexpr float taylorInvSqrt(float x) { return taylorInvSqrt(vec1(x)).x(); }
48+
49+
[[nodiscard]] constexpr vec4 grad4(float j, vec4 ip)
50+
{
51+
constexpr vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
52+
vec4 p, s;
53+
54+
p.set_xyz(((vec3(j) * ip.xyz()).fract() * 7.0).floor() * ip.z() - 1.0);
55+
p.w() = 1.5f - p.xyz().abs().dot(ones.xyz());
56+
s = vec4(p.lessThan(vec4(0.0)));
57+
p.set_xyz(p.xyz() + (s.xyz() * 2.0 - 1.0) * s.w());
58+
59+
return p;
60+
}
61+
62+
} // namespace detail
63+
64+
[[nodiscard]] constexpr float simplex(vec2 v, const PermuteFactors& factors = {})
65+
{
66+
auto permute = [&](auto x) { return detail::permute(x, factors); };
67+
68+
constexpr vec4 C = vec4(0.211324865405187f, 0.366025403784439f, -0.577350269189626f, 0.024390243902439f);
69+
vec2 i = (v + v.dot(C.y())).floor();
70+
vec2 x0 = v - i + i.dot(C.x());
71+
vec2 i1 = x0.x() > x0.y() ? vec2(1.0f, 0.0f) : vec2(0.0f, 1.0f);
72+
vec4 x12 = x0.swizzle<0, 1, 0, 1>() + C.swizzle<0, 0, 2, 2>();
73+
x12.set_xy(x12.xy() - i1);
74+
i = i.mod(289.0f);
75+
vec3 p = permute(permute(i.y() + vec3(0.0f, i1.y(), 1.0f)) + i.x() + vec3(0.0f, i1.x(), 1.0f));
76+
vec3 m = (0.5f - vec3(x0.sqrdot(), x12.xy().sqrdot(), x12.zw().sqrdot())).max(0.0f);
77+
m *= m * m * m;
78+
vec3 x = 2.0f * (p * C.w()).fract() - 1.0f;
79+
vec3 h = x.abs() - 0.5f;
80+
vec3 ox = (x + 0.5f).floor();
81+
vec3 a0 = x - ox;
82+
m *= detail::taylorInvSqrt(a0 * a0 + h * h);
83+
vec3 g;
84+
g.x() = a0.x() * x0.x() + h.x() * x0.y();
85+
g.set_yz(a0.yz() * x12.xz() + h.yz() * x12.yw());
86+
return 130.0f * m.dot(g);
87+
}
88+
89+
[[nodiscard]] constexpr float simplex(vec3 v, const PermuteFactors& factors = {})
90+
{
91+
auto permute = [&](auto x) { return detail::permute(x, factors); };
92+
93+
constexpr vec2 C = vec2(1.0f / 6.0f, 1.0f / 3.0f);
94+
constexpr vec4 D = vec4(0.0f, 0.5f, 1.0f, 2.0f);
95+
96+
vec3 i = (v + v.dot(C.y())).floor();
97+
vec3 x0 = v - i + i.dot(C.x());
98+
99+
// vec3 g = x0.yzx().step(x0);
100+
vec3 g = x0.swizzle<1, 2, 2>().step(x0.swizzle<0, 1, 0>());
101+
g.z() = 1.0f - g.z(); // Ugly fix
102+
103+
vec3 l = 1.0f - g;
104+
vec3 i1 = g.min(l.zxy());
105+
vec3 i2 = g.max(l.zxy());
106+
107+
vec3 x1 = x0 - i1 + 1.0f * C.x();
108+
vec3 x2 = x0 - i2 + 2.0f * C.x();
109+
vec3 x3 = x0 - 1.0f + 3.0f * C.x();
110+
111+
i = i.mod(289.0f);
112+
vec4 p =
113+
permute(permute(permute(i.z() + vec4(0.0f, i1.z(), i2.z(), 1.0f)) + i.y() + vec4(0.0f, i1.y(), i2.y(), 1.0f)) +
114+
i.x() + vec4(0.0f, i1.x(), i2.x(), 1.0f));
115+
116+
float n_ = 1.0f / 7.0f;
117+
vec3 ns = n_ * D.wyz() - D.swizzle<0, 2, 0>();
118+
119+
vec4 j = p - 49.0f * (p * ns.z() * ns.z()).floor();
120+
121+
vec4 x_ = (j * ns.z()).floor();
122+
vec4 y_ = (j - 7.0f * x_).floor();
123+
124+
vec4 x = x_ * ns.x() + ns.y();
125+
vec4 y = y_ * ns.x() + ns.y();
126+
vec4 h = 1.0f - x.abs() - y.abs();
127+
128+
vec4 b0 = vec4(x.x(), x.y(), y.x(), y.y());
129+
vec4 b1 = vec4(x.z(), x.w(), y.z(), y.w());
130+
131+
vec4 s0 = b0.floor() * 2.0f + 1.0f;
132+
vec4 s1 = b1.floor() * 2.0f + 1.0f;
133+
vec4 sh = -h.step(vec4(0.0f));
134+
135+
vec4 a0 = b0.xzyw() + s0.xzyw() * sh.swizzle<0, 0, 1, 1>();
136+
vec4 a1 = b1.xzyw() + s1.xzyw() * sh.swizzle<2, 2, 3, 3>();
137+
138+
vec3 p0 = vec3(a0.x(), a0.y(), h.x());
139+
vec3 p1 = vec3(a0.z(), a0.w(), h.y());
140+
vec3 p2 = vec3(a1.x(), a1.y(), h.z());
141+
vec3 p3 = vec3(a1.z(), a1.w(), h.w());
142+
143+
vec4 norm = detail::taylorInvSqrt(vec4(p0.sqrdot(), p1.sqrdot(), p2.sqrdot(), p3.sqrdot()));
144+
p0 *= norm.x();
145+
p1 *= norm.y();
146+
p2 *= norm.z();
147+
p3 *= norm.w();
148+
149+
vec4 m = (0.6f - vec4(x0.sqrdot(), x1.sqrdot(), x2.sqrdot(), x3.sqrdot())).max(0.0f);
150+
m *= m * m * m;
151+
return 42.0f * m.dot(vec4(p0.dot(x0), p1.dot(x1), p2.dot(x2), p3.dot(x3)));
152+
}
153+
154+
float simplex(vec4 v, const PermuteFactors& factors = {})
155+
{
156+
auto permute = [&](auto x) { return detail::permute(x, factors); };
157+
158+
constexpr vec2 C = vec2(0.138196601125010504f, 0.309016994374947451f);
159+
160+
vec4 i = (v + v.dot(C.y())).floor();
161+
vec4 x0 = v - i + i.dot(C.x());
162+
163+
vec4 i0;
164+
165+
vec3 isX = x0.yzw().step(x0.x());
166+
vec3 isYZ = x0.swizzle<2, 3, 3>().step(x0.swizzle<1, 1, 2>());
167+
168+
i0.x() = isX.x() + isX.y() + isX.z();
169+
i0.set_yzw(1.0f - isX);
170+
171+
i0.y() += isYZ.x() + isYZ.y();
172+
i0.set_zw(i0.zw() + 1.0f - isYZ.xy());
173+
174+
i0.z() += isYZ.z();
175+
i0.w() += 1.0f - isYZ.z();
176+
177+
vec4 i3 = i0.clamp(0.0f, 1.0f);
178+
vec4 i2 = (i0 - 1.0f).clamp(0.0f, 1.0f);
179+
vec4 i1 = (i0 - 2.0f).clamp(0.0f, 1.0f);
180+
181+
vec4 x1 = x0 - i1 + 1.0f * C.x();
182+
vec4 x2 = x0 - i2 + 2.0f * C.x();
183+
vec4 x3 = x0 - i3 + 3.0f * C.x();
184+
vec4 x4 = x0 - 1.0f + 4.0f * C.x();
185+
186+
i = i.mod(289.0f);
187+
float j0 = permute(permute(permute(permute(i.w()) + i.z()) + i.y()) + i.x());
188+
vec4 j1 = permute(permute(permute(permute(i.w() + vec4(i1.w(), i2.w(), i3.w(), 1.0f)) + i.z() +
189+
vec4(i1.z(), i2.z(), i3.z(), 1.0f)) +
190+
i.y() + vec4(i1.y(), i2.y(), i3.y(), 1.0f)) +
191+
i.x() + vec4(i1.x(), i2.x(), i3.x(), 1.0f));
192+
193+
vec4 ip = vec4(1.0f / 294.0f, 1.0f / 49.0f, 1.0f / 7.0f, 0.0f);
194+
195+
vec4 p0 = detail::grad4(j0, ip);
196+
vec4 p1 = detail::grad4(j1.x(), ip);
197+
vec4 p2 = detail::grad4(j1.y(), ip);
198+
vec4 p3 = detail::grad4(j1.z(), ip);
199+
vec4 p4 = detail::grad4(j1.w(), ip);
200+
201+
vec4 norm = detail::taylorInvSqrt(vec4(p0.sqrdot(), p1.sqrdot(), p2.sqrdot(), p3.sqrdot()));
202+
p0 *= norm.x();
203+
p1 *= norm.y();
204+
p2 *= norm.z();
205+
p3 *= norm.w();
206+
p4 *= detail::taylorInvSqrt(p4.sqrdot());
207+
208+
vec3 m0 = (0.6f - vec3(x0.sqrdot(), x1.sqrdot(), x2.sqrdot())).max(0.0f);
209+
vec2 m1 = (0.6f - vec2(x3.sqrdot(), x4.sqrdot())).max(0.0f);
210+
m0 *= m0 * m0 * m0;
211+
m1 *= m1 * m1 * m1;
212+
return 49.0f * (m0.dot(vec3(p0.dot(x0), p1.dot(x1), p2.dot(x2))) + m1.dot(vec2(p3.dot(x3), p4.dot(x4))));
213+
}
214+
215+
} // namespace dang::math::noise

0 commit comments

Comments
 (0)