NoiseUtils.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. #pragma once
  2. #include <algorithm>
  3. #include <cmath>
  4. #include <cstdint>
  5. #include <glm/glm.hpp>
  6. namespace WallpaperEngine::Render::Utils {
  7. static const unsigned char PERLIN_PERM[]
  8. = { 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37,
  9. 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177,
  10. 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146,
  11. 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25,
  12. 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100,
  13. 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206,
  14. 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153,
  15. 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246,
  16. 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192,
  17. 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114,
  18. 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180,
  19. // Duplicate for wrapping
  20. 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37,
  21. 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177,
  22. 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146,
  23. 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25,
  24. 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100,
  25. 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206,
  26. 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153,
  27. 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246,
  28. 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192,
  29. 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114,
  30. 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 };
  31. inline double perlinGrad (int hash, double x, double y, double z) {
  32. switch (hash & 0xF) {
  33. case 0x0:
  34. return x + y;
  35. case 0x1:
  36. return -x + y;
  37. case 0x2:
  38. return x - y;
  39. case 0x3:
  40. return -x - y;
  41. case 0x4:
  42. return x + z;
  43. case 0x5:
  44. return -x + z;
  45. case 0x6:
  46. return x - z;
  47. case 0x7:
  48. return -x - z;
  49. case 0x8:
  50. return y + z;
  51. case 0x9:
  52. return -y + z;
  53. case 0xA:
  54. return y - z;
  55. case 0xB:
  56. return -y - z;
  57. case 0xC:
  58. return y + x;
  59. case 0xD:
  60. return -y + z;
  61. case 0xE:
  62. return y - x;
  63. case 0xF:
  64. return -y - z;
  65. default:
  66. return 0;
  67. }
  68. }
  69. // Perlin noise ease curve (6t^5 - 15t^4 + 10t^3)
  70. inline double perlinEase (double t) { return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); }
  71. inline double lerpDouble (double t, double a, double b) { return a + t * (b - a); }
  72. inline double perlinNoise (double x, double y, double z) {
  73. int X = static_cast<int> (std::floor (x)) & 255;
  74. int Y = static_cast<int> (std::floor (y)) & 255;
  75. int Z = static_cast<int> (std::floor (z)) & 255;
  76. x -= std::floor (x);
  77. y -= std::floor (y);
  78. z -= std::floor (z);
  79. double u = perlinEase (x);
  80. double v = perlinEase (y);
  81. double w = perlinEase (z);
  82. int A = PERLIN_PERM[X] + Y;
  83. int AA = PERLIN_PERM[A] + Z;
  84. int AB = PERLIN_PERM[A + 1] + Z;
  85. int B = PERLIN_PERM[X + 1] + Y;
  86. int BA = PERLIN_PERM[B] + Z;
  87. int BB = PERLIN_PERM[B + 1] + Z;
  88. return lerpDouble (
  89. w,
  90. lerpDouble (
  91. v, lerpDouble (u, perlinGrad (PERLIN_PERM[AA], x, y, z), perlinGrad (PERLIN_PERM[BA], x - 1, y, z)),
  92. lerpDouble (u, perlinGrad (PERLIN_PERM[AB], x, y - 1, z), perlinGrad (PERLIN_PERM[BB], x - 1, y - 1, z))
  93. ),
  94. lerpDouble (
  95. v,
  96. lerpDouble (
  97. u, perlinGrad (PERLIN_PERM[AA + 1], x, y, z - 1), perlinGrad (PERLIN_PERM[BA + 1], x - 1, y, z - 1)
  98. ),
  99. lerpDouble (
  100. u, perlinGrad (PERLIN_PERM[AB + 1], x, y - 1, z - 1),
  101. perlinGrad (PERLIN_PERM[BB + 1], x - 1, y - 1, z - 1)
  102. )
  103. )
  104. );
  105. }
  106. // offset per axis so the 3 samples are decorrelated instead of identical
  107. inline glm::vec3 perlinNoiseVec3 (const glm::vec3& p) {
  108. return glm::vec3 (
  109. static_cast<float> (perlinNoise (p.x, p.y, p.z)),
  110. static_cast<float> (perlinNoise (p.x + 89.2, p.y + 33.1, p.z + 57.3)),
  111. static_cast<float> (perlinNoise (p.x + 100.3, p.y + 120.1, p.z + 142.2))
  112. );
  113. }
  114. // Curl noise - smooth, swirling patterns ideal for fluid-like particle motion
  115. inline glm::vec3 curlNoise (const glm::vec3& p) {
  116. const float e = 1e-4f;
  117. glm::vec3 dx (e, 0, 0);
  118. glm::vec3 dy (0, e, 0);
  119. glm::vec3 dz (0, 0, e);
  120. glm::vec3 x0 = perlinNoiseVec3 (p - dx);
  121. glm::vec3 x1 = perlinNoiseVec3 (p + dx);
  122. glm::vec3 y0 = perlinNoiseVec3 (p - dy);
  123. glm::vec3 y1 = perlinNoiseVec3 (p + dy);
  124. glm::vec3 z0 = perlinNoiseVec3 (p - dz);
  125. glm::vec3 z1 = perlinNoiseVec3 (p + dz);
  126. float x = (y1.z - y0.z) - (z1.y - z0.y);
  127. float y = (z1.x - z0.x) - (x1.z - x0.z);
  128. float z = (x1.y - x0.y) - (y1.x - y0.x);
  129. return glm::vec3 (x, y, z) / (2.0f * e);
  130. }
  131. // Stefan Gustavson's 1D simplex noise, the one wallpaper64.exe uses for turbulentvelocityrandom (roughly -1..1)
  132. inline float simplexNoise1D (float x) {
  133. const int i0 = static_cast<int> (std::floor (x));
  134. const float x0 = x - static_cast<float> (i0);
  135. const float x1 = x0 - 1.0f;
  136. const auto grad = [] (int hash, float value) {
  137. const float gradient = 1.0f + static_cast<float> (hash & 7);
  138. return ((hash & 8) ? -gradient : gradient) * value;
  139. };
  140. float t0 = 1.0f - x0 * x0;
  141. t0 *= t0;
  142. float t1 = 1.0f - x1 * x1;
  143. t1 *= t1;
  144. const float n0 = t0 * t0 * grad (PERLIN_PERM[i0 & 0xff], x0);
  145. const float n1 = t1 * t1 * grad (PERLIN_PERM[(i0 + 1) & 0xff], x1);
  146. return 0.395f * (n0 + n1);
  147. }
  148. // Stefan Gustavson's 3D simplex noise, used by wallpaper64.exe's turbulence operator (sub_1401EB070, roughly -1..1)
  149. inline float simplexNoise3D (float x, float y, float z) {
  150. static constexpr float gradients[12][3] = {
  151. { 1, 1, 0 }, { -1, 1, 0 }, { 1, -1, 0 }, { -1, -1, 0 }, { 1, 0, 1 }, { -1, 0, 1 },
  152. { 1, 0, -1 }, { -1, 0, -1 }, { 0, 1, 1 }, { 0, -1, 1 }, { 0, 1, -1 }, { 0, -1, -1 },
  153. };
  154. constexpr float F3 = 1.0f / 3.0f;
  155. constexpr float G3 = 1.0f / 6.0f;
  156. const float s = (x + y + z) * F3;
  157. const int i = static_cast<int> (std::floor (x + s));
  158. const int j = static_cast<int> (std::floor (y + s));
  159. const int k = static_cast<int> (std::floor (z + s));
  160. const float t = static_cast<float> (i + j + k) * G3;
  161. const float x0 = x - (static_cast<float> (i) - t);
  162. const float y0 = y - (static_cast<float> (j) - t);
  163. const float z0 = z - (static_cast<float> (k) - t);
  164. int i1, j1, k1, i2, j2, k2;
  165. if (x0 >= y0) {
  166. if (y0 >= z0) {
  167. i1 = 1, j1 = 0, k1 = 0, i2 = 1, j2 = 1, k2 = 0;
  168. } else if (x0 >= z0) {
  169. i1 = 1, j1 = 0, k1 = 0, i2 = 1, j2 = 0, k2 = 1;
  170. } else {
  171. i1 = 0, j1 = 0, k1 = 1, i2 = 1, j2 = 0, k2 = 1;
  172. }
  173. } else {
  174. if (y0 < z0) {
  175. i1 = 0, j1 = 0, k1 = 1, i2 = 0, j2 = 1, k2 = 1;
  176. } else if (x0 < z0) {
  177. i1 = 0, j1 = 1, k1 = 0, i2 = 0, j2 = 1, k2 = 1;
  178. } else {
  179. i1 = 0, j1 = 1, k1 = 0, i2 = 1, j2 = 1, k2 = 0;
  180. }
  181. }
  182. const float offsets[4][3] = {
  183. { x0, y0, z0 },
  184. { x0 - i1 + G3, y0 - j1 + G3, z0 - k1 + G3 },
  185. { x0 - i2 + 2.0f * G3, y0 - j2 + 2.0f * G3, z0 - k2 + 2.0f * G3 },
  186. { x0 - 1.0f + 3.0f * G3, y0 - 1.0f + 3.0f * G3, z0 - 1.0f + 3.0f * G3 },
  187. };
  188. const int corners[4][3] = { { 0, 0, 0 }, { i1, j1, k1 }, { i2, j2, k2 }, { 1, 1, 1 } };
  189. const auto perm = [] (int index) { return static_cast<int> (PERLIN_PERM[index & 0xff]); };
  190. float total = 0.0f;
  191. for (int c = 0; c < 4; c++) {
  192. const float* o = offsets[c];
  193. float falloff = 0.6f - o[0] * o[0] - o[1] * o[1] - o[2] * o[2];
  194. if (falloff < 0.0f) {
  195. continue;
  196. }
  197. const int gradient
  198. = perm (i + corners[c][0] + perm (j + corners[c][1] + perm (k + corners[c][2]))) % 12;
  199. falloff *= falloff;
  200. total += falloff * falloff
  201. * (gradients[gradient][0] * o[0] + gradients[gradient][1] * o[1] + gradients[gradient][2] * o[2]);
  202. }
  203. return 32.0f * total;
  204. }
  205. /**
  206. * wallpaper64.exe's 2D noise object (vtable off_140488440 slot 1, sub_1400FBE90, four lanes at once there): a hashed
  207. * simplex with the integer seed mixed into every corner hash, roughly -1..1. Same operations in the same order
  208. */
  209. inline float hashedNoise2D (int32_t seed, float x, float y) {
  210. constexpr float F2 = 0.36602540f;
  211. constexpr float G2 = 0.21132487f;
  212. constexpr uint32_t primeX = 501125321u;
  213. constexpr uint32_t primeY = 1136930381u;
  214. constexpr uint32_t hashMultiplier = 0x27D4EB2Du;
  215. constexpr float cornerOffset = -0.57735026f;
  216. constexpr float gradientRatio = 2.4142137f;
  217. const float skew = (x + y) * F2;
  218. const float i = std::floor (skew + x);
  219. const float j = std::floor (skew + y);
  220. const float unskew = G2 * (j + i);
  221. const float x0 = x - (i - unskew);
  222. const float y0 = y - (j - unskew);
  223. const uint32_t hashX = static_cast<uint32_t> (static_cast<int32_t> (i)) * primeX;
  224. const uint32_t hashY = static_cast<uint32_t> (static_cast<int32_t> (j)) * primeY;
  225. const bool xFirst = y0 < x0;
  226. const float x1 = (x0 - (xFirst ? 1.0f : 0.0f)) + G2;
  227. const float y1 = (y0 - (xFirst ? 0.0f : 1.0f)) + G2;
  228. const float x2 = x0 + cornerOffset;
  229. const float y2 = y0 + cornerOffset;
  230. float a0 = std::max (-(x0 * x0) + (-(y0 * y0) + 0.5f), 0.0f);
  231. float a1 = std::max (-(x1 * x1) + (-(y1 * y1) + 0.5f), 0.0f);
  232. float a2 = std::max (-(x2 * x2) + (-(y2 * y2) + 0.5f), 0.0f);
  233. a0 *= a0;
  234. a1 *= a1;
  235. a2 *= a2;
  236. const auto hash = [seed] (uint32_t hx, uint32_t hy) {
  237. int32_t h = static_cast<int32_t> (((hy ^ hx) ^ static_cast<uint32_t> (seed)) * hashMultiplier);
  238. return h ^ (h >> 15);
  239. };
  240. const auto flip = [] (float value, int32_t bit) { return bit != 0 ? -value : value; };
  241. // bit 0 and 1 flip the signs of x and y, bit 2 decides which one gets the bigger weight
  242. const auto gradient = [&flip, gradientRatio] (int32_t h, float gx, float gy) {
  243. const float a = flip (gx, h & 1);
  244. const float b = flip (gy, (h >> 1) & 1);
  245. return (h & 4) != 0 ? b * gradientRatio + a : a * gradientRatio + b;
  246. };
  247. const int32_t h0 = hash (hashX, hashY);
  248. const int32_t h1 = hash (hashX + (xFirst ? primeX : 0u), hashY + (xFirst ? 0u : primeY));
  249. const int32_t h2 = hash (hashX + primeX, hashY + primeY);
  250. return (gradient (h0, x0, y0) * (a0 * a0) + (gradient (h1, x1, y1) * (a1 * a1) + gradient (h2, x2, y2) * (a2 * a2)))
  251. * 38.283688f;
  252. }
  253. /** 1 / (1 + 0.5 + 0.25 ...) over the octaves, what wallpaper64.exe scales its fbm by (off_140488440 slot 3) */
  254. inline float hashedNoiseFbmNormalizer (int octaves) {
  255. float total = 1.0f;
  256. float amplitude = 0.5f;
  257. for (int octave = 1; octave < octaves; octave++) {
  258. total += amplitude;
  259. amplitude *= 0.5f;
  260. }
  261. return 1.0f / total;
  262. }
  263. /** off_140488440 slot 4 (sub_1400FBC70): octaves of hashedNoise2D, frequency x2, seed +1 and amplitude x0.5 each */
  264. inline float hashedNoiseFbm (int octaves, float amplitude, int32_t seed, float x, float y) {
  265. float sum = hashedNoise2D (seed, x, y) * amplitude;
  266. for (int octave = 1; octave < octaves; octave++) {
  267. x *= 2.0f;
  268. y *= 2.0f;
  269. seed++;
  270. amplitude *= 0.5f;
  271. sum += hashedNoise2D (seed, x, y) * amplitude;
  272. }
  273. return sum;
  274. }
  275. /** wallpaper64.exe sub_14027B170: 2D simplex over the permutation table, roughly -1..1 */
  276. inline float simplexNoise2D (float x, float y) {
  277. constexpr float F2 = 0.36602540f;
  278. constexpr float G2 = 0.21132487f;
  279. constexpr float G2x2 = 0.42264974f;
  280. const float skew = (x + y) * F2;
  281. const int i = static_cast<int> (std::floor (skew + x));
  282. const int j = static_cast<int> (std::floor (skew + y));
  283. const float unskew = static_cast<float> (j + i) * G2;
  284. const float x0 = x - (static_cast<float> (i) - unskew);
  285. const float y0 = y - (static_cast<float> (j) - unskew);
  286. const int i1 = x0 > y0 ? 1 : 0;
  287. const int j1 = 1 - i1;
  288. const float x1 = (x0 - static_cast<float> (i1)) + G2;
  289. const float y1 = (y0 - static_cast<float> (j1)) + G2;
  290. const float x2 = (x0 - 1.0f) + G2x2;
  291. const float y2 = (y0 - 1.0f) + G2x2;
  292. const auto perm = [] (int index) { return static_cast<int> (PERLIN_PERM[index & 0xff]); };
  293. // (h & 0x3c) swaps the axes, bit 0 negates the first one, bit 1 doubles the second one negative instead
  294. const auto corner = [] (int h, float cx, float cy, float falloff) {
  295. if (falloff < 0.0f) {
  296. return 0.0f;
  297. }
  298. float u = cx;
  299. float v = cy;
  300. if ((h & 0x3c) != 0) {
  301. std::swap (u, v);
  302. }
  303. if ((h & 1) != 0) {
  304. u = -u;
  305. }
  306. v = (h & 2) != 0 ? v * -2.0f : v + v;
  307. falloff *= falloff;
  308. return (v + u) * (falloff * falloff);
  309. };
  310. const float n0 = corner (perm (i + perm (j)), x0, y0, (0.5f - x0 * x0) - y0 * y0);
  311. const float n1 = corner (perm (i1 + perm (j + j1) + i), x1, y1, (0.5f - x1 * x1) - y1 * y1);
  312. const float n2 = corner (perm (i + 1 + perm (j + 1)), x2, y2, (0.5f - x2 * x2) - y2 * y2);
  313. return ((n1 + n0) + n2) * 45.230652f;
  314. }
  315. /** wallpaper64.exe sub_14027B4B0: octaves of simplexNoise1D, frequency x2 and amplitude x0.5 each, averaged */
  316. inline float simplexFbm1D (float x, float frequency, int octaves) {
  317. float sum = 0.0f;
  318. float total = 0.0f;
  319. float amplitude = 1.0f;
  320. for (int octave = 0; octave < octaves; octave++) {
  321. sum += simplexNoise1D (frequency * x) * amplitude;
  322. total += amplitude;
  323. frequency *= 2.0f;
  324. amplitude *= 0.5f;
  325. }
  326. return sum / total;
  327. }
  328. } // namespace WallpaperEngine::Render::Utils