1 module open_simplex_2.open_simplex_2_f; 2 3 import open_simplex_2.open_simplex_2; 4 import std.math : abs; 5 6 7 /** 8 * K.jpg's OpenSimplex 2, faster variant 9 * 10 * - 2D is standard simplex implemented using a lookup table. 11 * - 3D is "Re-oriented 4-point BCC noise" which constructs a 12 * congruent BCC lattice in a much different way than usual. 13 * - 4D constructs the lattice as a union of five copies of its 14 * reciprocal. It successively finds the closest point on each. 15 * 16 * Multiple versions of each function are provided. See the 17 * documentation above each, for more info. 18 */ 19 public final class OpenSimplex2F : OpenSimplex2 { 20 21 private enum int PSIZE = 2048; 22 private enum int PMASK = 2047; 23 24 private short[] perm; 25 private Grad2[] permGrad2; 26 private Grad3[] permGrad3; 27 private Grad4[] permGrad4; 28 29 public this(long seed) 30 { 31 perm = new short[PSIZE]; 32 permGrad2 = new Grad2[PSIZE]; 33 permGrad3 = new Grad3[PSIZE]; 34 permGrad4 = new Grad4[PSIZE]; 35 short[] source = new short[PSIZE]; 36 for (short i = 0; i < PSIZE; i++) 37 source[i] = i; 38 for (int i = PSIZE - 1; i >= 0; i--) { 39 seed = seed * 6_364_136_223_846_793_005L + 1_442_695_040_888_963_407L; 40 int r = cast(int)((seed + 31) % (i + 1)); 41 if (r < 0) 42 r += (i + 1); 43 perm[i] = source[r]; 44 permGrad2[i] = GRADIENTS_2D[perm[i]]; 45 permGrad3[i] = GRADIENTS_3D[perm[i]]; 46 permGrad4[i] = GRADIENTS_4D[perm[i]]; 47 source[r] = source[i]; 48 } 49 } 50 51 /* 52 * Noise Evaluators 53 */ 54 55 /** 56 * 2D Simplex noise, standard lattice orientation. 57 */ 58 public double noise2(double x, double y) { 59 60 // Get points for A2* lattice 61 double s = 0.366025403784439 * (x + y); 62 double xs = x + s, ys = y + s; 63 64 return noise2_Base(xs, ys); 65 } 66 67 /** 68 * 2D Simplex noise, with Y pointing down the main diagonal. 69 * Might be better for a 2D sandbox style game, where Y is vertical. 70 * Probably slightly less optimal for heightmaps or continent maps. 71 */ 72 public double noise2_XBeforeY(double x, double y) { 73 74 // Skew transform and rotation baked into one. 75 double xx = x * 0.7071067811865476; 76 double yy = y * 1.224744871380249; 77 78 return noise2_Base(yy + xx, yy - xx); 79 } 80 81 /** 82 * 2D Simplex noise base. 83 * Lookup table implementation inspired by DigitalShadow. 84 */ 85 private double noise2_Base(double xs, double ys) { 86 double value = 0; 87 88 // Get base points and offsets 89 int xsb = fastFloor(xs), ysb = fastFloor(ys); 90 double xsi = xs - xsb, ysi = ys - ysb; 91 92 // Index to point list 93 int index = cast(int)((ysi - xsi) / 2 + 1); 94 95 double ssi = (xsi + ysi) * -0.211324865405187; 96 double xi = xsi + ssi, yi = ysi + ssi; 97 98 // Point contributions 99 for (int i = 0; i < 3; i++) { 100 LatticePoint2D c = LOOKUP_2D[index + i]; 101 102 double dx = xi + c.dx, dy = yi + c.dy; 103 double attn = 0.5 - dx * dx - dy * dy; 104 if (attn <= 0) continue; 105 106 int pxm = (xsb + c.xsv) & PMASK, pym = (ysb + c.ysv) & PMASK; 107 Grad2 grad = permGrad2[perm[pxm] ^ pym]; 108 double extrapolation = grad.dx * dx + grad.dy * dy; 109 110 attn *= attn; 111 value += attn * attn * extrapolation; 112 } 113 114 return value; 115 } 116 117 /** 118 * 3D Re-oriented 4-point BCC noise, classic orientation. 119 * Proper substitute for 3D Simplex in light of Forbidden Formulae. 120 * Use noise3_XYBeforeZ or noise3_XZBeforeY instead, wherever appropriate. 121 */ 122 public double noise3_Classic(double x, double y, double z) { 123 124 // Re-orient the cubic lattices via rotation, to produce the expected look on cardinal planar slices. 125 // If texturing objects that don't tend to have cardinal plane faces, you could even remove this. 126 // Orthonormal rotation. Not a skew transform. 127 double r = (2.0 / 3.0) * (x + y + z); 128 double xr = r - x, yr = r - y, zr = r - z; 129 130 // Evaluate both lattices to form a BCC lattice. 131 return noise3_BCC(xr, yr, zr); 132 } 133 134 /** 135 * 3D Re-oriented 4-point BCC noise, with better visual isotropy in (X, Y). 136 * Recommended for 3D terrain and time-varied animations. 137 * The Z coordinate should always be the "different" coordinate in your use case. 138 * If Y is vertical in world coordinates, call noise3_XYBeforeZ(x, z, Y) or use noise3_XZBeforeY. 139 * If Z is vertical in world coordinates, call noise3_XYBeforeZ(x, y, Z). 140 * For a time varied animation, call noise3_XYBeforeZ(x, y, T). 141 */ 142 public double noise3_XYBeforeZ(double x, double y, double z) { 143 144 // Re-orient the cubic lattices without skewing, to make X and Y triangular like 2D. 145 // Orthonormal rotation. Not a skew transform. 146 double xy = x + y; 147 double s2 = xy * -0.211324865405187; 148 double zz = z * 0.577350269189626; 149 double xr = x + s2 - zz, yr = y + s2 - zz; 150 double zr = xy * 0.577350269189626 + zz; 151 152 // Evaluate both lattices to form a BCC lattice. 153 return noise3_BCC(xr, yr, zr); 154 } 155 156 /** 157 * 3D Re-oriented 4-point BCC noise, with better visual isotropy in (X, Z). 158 * Recommended for 3D terrain and time-varied animations. 159 * The Y coordinate should always be the "different" coordinate in your use case. 160 * If Y is vertical in world coordinates, call noise3_XZBeforeY(x, Y, z). 161 * If Z is vertical in world coordinates, call noise3_XZBeforeY(x, Z, y) or use noise3_XYBeforeZ. 162 * For a time varied animation, call noise3_XZBeforeY(x, T, y) or use noise3_XYBeforeZ. 163 */ 164 public double noise3_XZBeforeY(double x, double y, double z) { 165 166 // Re-orient the cubic lattices without skewing, to make X and Z triangular like 2D. 167 // Orthonormal rotation. Not a skew transform. 168 double xz = x + z; 169 double s2 = xz * -0.211324865405187; 170 double yy = y * 0.577350269189626; 171 double xr = x + s2 - yy; double zr = z + s2 - yy; 172 double yr = xz * 0.577350269189626 + yy; 173 174 // Evaluate both lattices to form a BCC lattice. 175 return noise3_BCC(xr, yr, zr); 176 } 177 178 /** 179 * Generate overlapping cubic lattices for 3D Re-oriented BCC noise. 180 * Lookup table implementation inspired by DigitalShadow. 181 * It was actually faster to narrow down the points in the loop itself, 182 * than to build up the index with enough info to isolate 4 points. 183 */ 184 private double noise3_BCC(double xr, double yr, double zr) { 185 186 // Get base and offsets inside cube of first lattice. 187 int xrb = fastFloor(xr), yrb = fastFloor(yr), zrb = fastFloor(zr); 188 double xri = xr - xrb, yri = yr - yrb, zri = zr - zrb; 189 190 // Identify which octant of the cube we're in. This determines which cell 191 // in the other cubic lattice we're in, and also narrows down one point on each. 192 int xht = cast(int)(xri + 0.5), yht = cast(int)(yri + 0.5), zht = cast(int)(zri + 0.5); 193 int index = (xht << 0) | (yht << 1) | (zht << 2); 194 195 // Point contributions 196 double value = 0; 197 LatticePoint3D c = LOOKUP_3D[index]; 198 while (c !is null) { 199 double dxr = xri + c.dxr, dyr = yri + c.dyr, dzr = zri + c.dzr; 200 double attn = 0.5 - dxr * dxr - dyr * dyr - dzr * dzr; 201 if (attn < 0) { 202 c = c.nextOnFailure; 203 } else { 204 int pxm = (xrb + c.xrv) & PMASK, pym = (yrb + c.yrv) & PMASK, pzm = (zrb + c.zrv) & PMASK; 205 Grad3 grad = permGrad3[perm[perm[pxm] ^ pym] ^ pzm]; 206 double extrapolation = grad.dx * dxr + grad.dy * dyr + grad.dz * dzr; 207 208 attn *= attn; 209 value += attn * attn * extrapolation; 210 c = c.nextOnSuccess; 211 } 212 } 213 return value; 214 } 215 216 /** 217 * 4D OpenSimplex2F noise, classic lattice orientation. 218 */ 219 public double noise4_Classic(double x, double y, double z, double w) { 220 221 // Get points for A4 lattice 222 double s = -0.138196601125011 * (x + y + z + w); 223 double xs = x + s, ys = y + s, zs = z + s, ws = w + s; 224 225 return noise4_Base(xs, ys, zs, ws); 226 } 227 228 /** 229 * 4D OpenSimplex2F noise, with XY and ZW forming orthogonal triangular-based planes. 230 * Recommended for 3D terrain, where X and Y (or Z and W) are horizontal. 231 * Recommended for noise(x, y, sin(time), cos(time)) trick. 232 */ 233 public double noise4_XYBeforeZW(double x, double y, double z, double w) { 234 235 double s2 = (x + y) * -0.178275657951399372 + (z + w) * 0.215623393288842828; 236 double t2 = (z + w) * -0.403949762580207112 + (x + y) * -0.375199083010075342; 237 double xs = x + s2, ys = y + s2, zs = z + t2, ws = w + t2; 238 239 return noise4_Base(xs, ys, zs, ws); 240 } 241 242 /** 243 * 4D OpenSimplex2F noise, with XZ and YW forming orthogonal triangular-based planes. 244 * Recommended for 3D terrain, where X and Z (or Y and W) are horizontal. 245 */ 246 public double noise4_XZBeforeYW(double x, double y, double z, double w) { 247 248 double s2 = (x + z) * -0.178275657951399372 + (y + w) * 0.215623393288842828; 249 double t2 = (y + w) * -0.403949762580207112 + (x + z) * -0.375199083010075342; 250 double xs = x + s2, ys = y + t2, zs = z + s2, ws = w + t2; 251 252 return noise4_Base(xs, ys, zs, ws); 253 } 254 255 /** 256 * 4D OpenSimplex2F noise, with XYZ oriented like noise3_Classic, 257 * and W for an extra degree of freedom. W repeats eventually. 258 * Recommended for time-varied animations which texture a 3D object (W=time) 259 */ 260 public double noise4_XYZBeforeW(double x, double y, double z, double w) { 261 262 double xyz = x + y + z; 263 double ww = w * 0.2236067977499788; 264 double s2 = xyz * -0.16666666666666666 + ww; 265 double xs = x + s2, ys = y + s2, zs = z + s2, ws = -0.5 * xyz + ww; 266 267 return noise4_Base(xs, ys, zs, ws); 268 } 269 270 /** 271 * 4D OpenSimplex2F noise base. 272 * Current implementation not fully optimized by lookup tables. 273 * But still comes out slightly ahead of Gustavson's Simplex in tests. 274 */ 275 private double noise4_Base(double xs, double ys, double zs, double ws) { 276 double value = 0; 277 278 // Get base points and offsets 279 int xsb = fastFloor(xs), ysb = fastFloor(ys), zsb = fastFloor(zs), wsb = fastFloor(ws); 280 double xsi = xs - xsb, ysi = ys - ysb, zsi = zs - zsb, wsi = ws - wsb; 281 282 // If we're in the lower half, flip so we can repeat the code for the upper half. We'll flip back later. 283 double siSum = xsi + ysi + zsi + wsi; 284 double ssi = siSum * 0.309016994374947; // Prep for vertex contributions. 285 bool inLowerHalf = (siSum < 2); 286 if (inLowerHalf) { 287 xsi = 1 - xsi; ysi = 1 - ysi; zsi = 1 - zsi; wsi = 1 - wsi; 288 siSum = 4 - siSum; 289 } 290 291 // Consider opposing vertex pairs of the octahedron formed by the central cross-section of the stretched tesseract 292 double aabb = xsi + ysi - zsi - wsi, abab = xsi - ysi + zsi - wsi, abba = xsi - ysi - zsi + wsi; 293 double aabbScore = abs(aabb), ababScore = abs(abab), abbaScore = abs(abba); 294 295 // Find the closest point on the stretched tesseract as if it were the upper half 296 int vertexIndex, via, vib; 297 double asi, bsi; 298 if (aabbScore > ababScore && aabbScore > abbaScore) { 299 if (aabb > 0) { 300 asi = zsi; bsi = wsi; vertexIndex = 0b0011; via = 0b0111; vib = 0b1011; 301 } else { 302 asi = xsi; bsi = ysi; vertexIndex = 0b1100; via = 0b1101; vib = 0b1110; 303 } 304 } else if (ababScore > abbaScore) { 305 if (abab > 0) { 306 asi = ysi; bsi = wsi; vertexIndex = 0b0101; via = 0b0111; vib = 0b1101; 307 } else { 308 asi = xsi; bsi = zsi; vertexIndex = 0b1010; via = 0b1011; vib = 0b1110; 309 } 310 } else { 311 if (abba > 0) { 312 asi = ysi; bsi = zsi; vertexIndex = 0b1001; via = 0b1011; vib = 0b1101; 313 } else { 314 asi = xsi; bsi = wsi; vertexIndex = 0b0110; via = 0b0111; vib = 0b1110; 315 } 316 } 317 if (bsi > asi) { 318 via = vib; 319 double temp = bsi; 320 bsi = asi; 321 asi = temp; 322 } 323 if (siSum + asi > 3) { 324 vertexIndex = via; 325 if (siSum + bsi > 4) { 326 vertexIndex = 0b1111; 327 } 328 } 329 330 // Now flip back if we're actually in the lower half. 331 if (inLowerHalf) { 332 xsi = 1 - xsi; ysi = 1 - ysi; zsi = 1 - zsi; wsi = 1 - wsi; 333 vertexIndex ^= 0b1111; 334 } 335 336 // Five points to add, total, from five copies of the A4 lattice. 337 for (int i = 0; i < 5; i++) { 338 339 // Update xsb/etc. and add the lattice point's contribution. 340 LatticePoint4D c = VERTICES_4D[vertexIndex]; 341 xsb += c.xsv; ysb += c.ysv; zsb += c.zsv; wsb += c.wsv; 342 double xi = xsi + ssi, yi = ysi + ssi, zi = zsi + ssi, wi = wsi + ssi; 343 double dx = xi + c.dx, dy = yi + c.dy, dz = zi + c.dz, dw = wi + c.dw; 344 double attn = 0.5 - dx * dx - dy * dy - dz * dz - dw * dw; 345 if (attn > 0) { 346 int pxm = xsb & PMASK, pym = ysb & PMASK, pzm = zsb & PMASK, pwm = wsb & PMASK; 347 Grad4 grad = permGrad4[perm[perm[perm[pxm] ^ pym] ^ pzm] ^ pwm]; 348 double ramped = grad.dx * dx + grad.dy * dy + grad.dz * dz + grad.dw * dw; 349 350 attn *= attn; 351 value += attn * attn * ramped; 352 } 353 354 // Maybe this helps the compiler/JVM/LLVM/etc. know we can end the loop here. Maybe not. 355 if (i == 4) break; 356 357 // Update the relative skewed coordinates to reference the vertex we just added. 358 // Rather, reference its counterpart on the lattice copy that is shifted down by 359 // the vector <-0.2, -0.2, -0.2, -0.2> 360 xsi += c.xsi; ysi += c.ysi; zsi += c.zsi; wsi += c.wsi; 361 ssi += c.ssiDelta; 362 363 // Next point is the closest vertex on the 4-simplex whose base vertex is the aforementioned vertex. 364 double score0 = 1.0 + ssi * (-1.0 / 0.309016994374947); // Seems slightly faster than 1.0-xsi-ysi-zsi-wsi 365 vertexIndex = 0b0000; 366 if (xsi >= ysi && xsi >= zsi && xsi >= wsi && xsi >= score0) { 367 vertexIndex = 0b0001; 368 } 369 else if (ysi > xsi && ysi >= zsi && ysi >= wsi && ysi >= score0) { 370 vertexIndex = 0b0010; 371 } 372 else if (zsi > xsi && zsi > ysi && zsi >= wsi && zsi >= score0) { 373 vertexIndex = 0b0100; 374 } 375 else if (wsi > xsi && wsi > ysi && wsi > zsi && wsi >= score0) { 376 vertexIndex = 0b1000; 377 } 378 } 379 380 return value; 381 } 382 383 /* 384 * Utility 385 */ 386 387 private static int fastFloor(double x) { 388 int xi = cast(int)x; 389 return x < xi ? xi - 1 : xi; 390 } 391 392 /* 393 * Definitions 394 */ 395 396 private static LatticePoint2D[] LOOKUP_2D; 397 private static LatticePoint3D[] LOOKUP_3D; 398 private static LatticePoint4D[] VERTICES_4D; 399 400 static this() 401 { 402 LOOKUP_2D = new LatticePoint2D[4]; 403 LOOKUP_3D = new LatticePoint3D[8]; 404 VERTICES_4D = new LatticePoint4D[16]; 405 406 LOOKUP_2D[0] = new LatticePoint2D(1, 0); 407 LOOKUP_2D[1] = new LatticePoint2D(0, 0); 408 LOOKUP_2D[2] = new LatticePoint2D(1, 1); 409 LOOKUP_2D[3] = new LatticePoint2D(0, 1); 410 411 for (int i = 0; i < 8; i++) { 412 int i1, j1, k1, i2, j2, k2; 413 i1 = (i >> 0) & 1; j1 = (i >> 1) & 1; k1 = (i >> 2) & 1; 414 i2 = i1 ^ 1; j2 = j1 ^ 1; k2 = k1 ^ 1; 415 416 // The two points within this octant, one from each of the two cubic half-lattices. 417 LatticePoint3D c0 = new LatticePoint3D(i1, j1, k1, 0); 418 LatticePoint3D c1 = new LatticePoint3D(i1 + i2, j1 + j2, k1 + k2, 1); 419 420 // Each single step away on the first half-lattice. 421 LatticePoint3D c2 = new LatticePoint3D(i1 ^ 1, j1, k1, 0); 422 LatticePoint3D c3 = new LatticePoint3D(i1, j1 ^ 1, k1, 0); 423 LatticePoint3D c4 = new LatticePoint3D(i1, j1, k1 ^ 1, 0); 424 425 // Each single step away on the second half-lattice. 426 LatticePoint3D c5 = new LatticePoint3D(i1 + (i2 ^ 1), j1 + j2, k1 + k2, 1); 427 LatticePoint3D c6 = new LatticePoint3D(i1 + i2, j1 + (j2 ^ 1), k1 + k2, 1); 428 LatticePoint3D c7 = new LatticePoint3D(i1 + i2, j1 + j2, k1 + (k2 ^ 1), 1); 429 430 // First two are guaranteed. 431 c0.nextOnFailure = c0.nextOnSuccess = c1; 432 c1.nextOnFailure = c1.nextOnSuccess = c2; 433 434 // Once we find one on the first half-lattice, the rest are out. 435 // In addition, knowing c2 rules out c5. 436 c2.nextOnFailure = c3; c2.nextOnSuccess = c6; 437 c3.nextOnFailure = c4; c3.nextOnSuccess = c5; 438 c4.nextOnFailure = c4.nextOnSuccess = c5; 439 440 // Once we find one on the second half-lattice, the rest are out. 441 c5.nextOnFailure = c6; c5.nextOnSuccess = null; 442 c6.nextOnFailure = c7; c6.nextOnSuccess = null; 443 c7.nextOnFailure = c7.nextOnSuccess = null; 444 445 LOOKUP_3D[i] = c0; 446 } 447 448 for (int i = 0; i < 16; i++) { 449 VERTICES_4D[i] = new LatticePoint4D((i >> 0) & 1, (i >> 1) & 1, (i >> 2) & 1, (i >> 3) & 1); 450 } 451 } 452 453 private static class LatticePoint2D { 454 int xsv, ysv; 455 double dx, dy; 456 public this(int xsv, int ysv) { 457 this.xsv = xsv; this.ysv = ysv; 458 double ssv = (xsv + ysv) * -0.211324865405187; 459 this.dx = -xsv - ssv; 460 this.dy = -ysv - ssv; 461 } 462 } 463 464 private static class LatticePoint3D { 465 public double dxr, dyr, dzr; 466 public int xrv, yrv, zrv; 467 LatticePoint3D nextOnFailure, nextOnSuccess; 468 public this(int xrv, int yrv, int zrv, int lattice) { 469 this.dxr = -xrv + lattice * 0.5; this.dyr = -yrv + lattice * 0.5; this.dzr = -zrv + lattice * 0.5; 470 this.xrv = xrv + lattice * 1024; this.yrv = yrv + lattice * 1024; this.zrv = zrv + lattice * 1024; 471 } 472 } 473 474 private static class LatticePoint4D { 475 int xsv, ysv, zsv, wsv; 476 double dx, dy, dz, dw; 477 double xsi, ysi, zsi, wsi; 478 double ssiDelta; 479 public this(int xsv, int ysv, int zsv, int wsv) { 480 this.xsv = xsv + 409; this.ysv = ysv + 409; this.zsv = zsv + 409; this.wsv = wsv + 409; 481 double ssv = (xsv + ysv + zsv + wsv) * 0.309016994374947; 482 this.dx = -xsv - ssv; 483 this.dy = -ysv - ssv; 484 this.dz = -zsv - ssv; 485 this.dw = -wsv - ssv; 486 this.xsi = xsi = 0.2 - xsv; 487 this.ysi = ysi = 0.2 - ysv; 488 this.zsi = zsi = 0.2 - zsv; 489 this.wsi = wsi = 0.2 - wsv; 490 this.ssiDelta = (0.8 - xsv - ysv - zsv - wsv) * 0.309016994374947; 491 } 492 } 493 494 /* 495 * Gradients 496 */ 497 498 private static class Grad2 { 499 double dx, dy; 500 public this(double dx, double dy) { 501 this.dx = dx; this.dy = dy; 502 } 503 } 504 505 private static class Grad3 { 506 double dx, dy, dz; 507 public this(double dx, double dy, double dz) { 508 this.dx = dx; this.dy = dy; this.dz = dz; 509 } 510 } 511 512 private static class Grad4 { 513 double dx, dy, dz, dw; 514 public this(double dx, double dy, double dz, double dw) { 515 this.dx = dx; this.dy = dy; this.dz = dz; this.dw = dw; 516 } 517 } 518 519 private enum double N2 = 0.01001634121365712; 520 private enum double N3 = 0.030485933181293584; 521 private enum double N4 = 0.009202377986303158; 522 private static Grad2[] GRADIENTS_2D; 523 private static Grad3[] GRADIENTS_3D; 524 private static Grad4[] GRADIENTS_4D; 525 526 static this() 527 { 528 529 GRADIENTS_2D = new Grad2[PSIZE]; 530 Grad2[] grad2 = [ 531 new Grad2( 0.130526192220052, 0.99144486137381), 532 new Grad2( 0.38268343236509, 0.923879532511287), 533 new Grad2( 0.608761429008721, 0.793353340291235), 534 new Grad2( 0.793353340291235, 0.608761429008721), 535 new Grad2( 0.923879532511287, 0.38268343236509), 536 new Grad2( 0.99144486137381, 0.130526192220051), 537 new Grad2( 0.99144486137381, -0.130526192220051), 538 new Grad2( 0.923879532511287, -0.38268343236509), 539 new Grad2( 0.793353340291235, -0.60876142900872), 540 new Grad2( 0.608761429008721, -0.793353340291235), 541 new Grad2( 0.38268343236509, -0.923879532511287), 542 new Grad2( 0.130526192220052, -0.99144486137381), 543 new Grad2(-0.130526192220052, -0.99144486137381), 544 new Grad2(-0.38268343236509, -0.923879532511287), 545 new Grad2(-0.608761429008721, -0.793353340291235), 546 new Grad2(-0.793353340291235, -0.608761429008721), 547 new Grad2(-0.923879532511287, -0.38268343236509), 548 new Grad2(-0.99144486137381, -0.130526192220052), 549 new Grad2(-0.99144486137381, 0.130526192220051), 550 new Grad2(-0.923879532511287, 0.38268343236509), 551 new Grad2(-0.793353340291235, 0.608761429008721), 552 new Grad2(-0.608761429008721, 0.793353340291235), 553 new Grad2(-0.38268343236509, 0.923879532511287), 554 new Grad2(-0.130526192220052, 0.99144486137381) 555 ]; 556 for (int i = 0; i < grad2.length; i++) { 557 grad2[i].dx /= N2; grad2[i].dy /= N2; 558 } 559 for (int i = 0; i < PSIZE; i++) { 560 GRADIENTS_2D[i] = grad2[i % grad2.length]; 561 } 562 563 GRADIENTS_3D = new Grad3[PSIZE]; 564 Grad3[] grad3 = [ 565 new Grad3(-2.22474487139, -2.22474487139, -1.0), 566 new Grad3(-2.22474487139, -2.22474487139, 1.0), 567 new Grad3(-3.0862664687972017, -1.1721513422464978, 0.0), 568 new Grad3(-1.1721513422464978, -3.0862664687972017, 0.0), 569 new Grad3(-2.22474487139, -1.0, -2.22474487139), 570 new Grad3(-2.22474487139, 1.0, -2.22474487139), 571 new Grad3(-1.1721513422464978, 0.0, -3.0862664687972017), 572 new Grad3(-3.0862664687972017, 0.0, -1.1721513422464978), 573 new Grad3(-2.22474487139, -1.0, 2.22474487139), 574 new Grad3(-2.22474487139, 1.0, 2.22474487139), 575 new Grad3(-3.0862664687972017, 0.0, 1.1721513422464978), 576 new Grad3(-1.1721513422464978, 0.0, 3.0862664687972017), 577 new Grad3(-2.22474487139, 2.22474487139, -1.0), 578 new Grad3(-2.22474487139, 2.22474487139, 1.0), 579 new Grad3(-1.1721513422464978, 3.0862664687972017, 0.0), 580 new Grad3(-3.0862664687972017, 1.1721513422464978, 0.0), 581 new Grad3(-1.0, -2.22474487139, -2.22474487139), 582 new Grad3( 1.0, -2.22474487139, -2.22474487139), 583 new Grad3( 0.0, -3.0862664687972017, -1.1721513422464978), 584 new Grad3( 0.0, -1.1721513422464978, -3.0862664687972017), 585 new Grad3(-1.0, -2.22474487139, 2.22474487139), 586 new Grad3( 1.0, -2.22474487139, 2.22474487139), 587 new Grad3( 0.0, -1.1721513422464978, 3.0862664687972017), 588 new Grad3( 0.0, -3.0862664687972017, 1.1721513422464978), 589 new Grad3(-1.0, 2.22474487139, -2.22474487139), 590 new Grad3( 1.0, 2.22474487139, -2.22474487139), 591 new Grad3( 0.0, 1.1721513422464978, -3.0862664687972017), 592 new Grad3( 0.0, 3.0862664687972017, -1.1721513422464978), 593 new Grad3(-1.0, 2.22474487139, 2.22474487139), 594 new Grad3( 1.0, 2.22474487139, 2.22474487139), 595 new Grad3( 0.0, 3.0862664687972017, 1.1721513422464978), 596 new Grad3( 0.0, 1.1721513422464978, 3.0862664687972017), 597 new Grad3( 2.22474487139, -2.22474487139, -1.0), 598 new Grad3( 2.22474487139, -2.22474487139, 1.0), 599 new Grad3( 1.1721513422464978, -3.0862664687972017, 0.0), 600 new Grad3( 3.0862664687972017, -1.1721513422464978, 0.0), 601 new Grad3( 2.22474487139, -1.0, -2.22474487139), 602 new Grad3( 2.22474487139, 1.0, -2.22474487139), 603 new Grad3( 3.0862664687972017, 0.0, -1.1721513422464978), 604 new Grad3( 1.1721513422464978, 0.0, -3.0862664687972017), 605 new Grad3( 2.22474487139, -1.0, 2.22474487139), 606 new Grad3( 2.22474487139, 1.0, 2.22474487139), 607 new Grad3( 1.1721513422464978, 0.0, 3.0862664687972017), 608 new Grad3( 3.0862664687972017, 0.0, 1.1721513422464978), 609 new Grad3( 2.22474487139, 2.22474487139, -1.0), 610 new Grad3( 2.22474487139, 2.22474487139, 1.0), 611 new Grad3( 3.0862664687972017, 1.1721513422464978, 0.0), 612 new Grad3( 1.1721513422464978, 3.0862664687972017, 0.0) 613 ]; 614 for (int i = 0; i < grad3.length; i++) { 615 grad3[i].dx /= N3; grad3[i].dy /= N3; grad3[i].dz /= N3; 616 } 617 for (int i = 0; i < PSIZE; i++) { 618 GRADIENTS_3D[i] = grad3[i % grad3.length]; 619 } 620 621 GRADIENTS_4D = new Grad4[PSIZE]; 622 Grad4[] grad4 = [ 623 new Grad4(-0.753341017856078, -0.37968289875261624, -0.37968289875261624, -0.37968289875261624), 624 new Grad4(-0.7821684431180708, -0.4321472685365301, -0.4321472685365301, 0.12128480194602098), 625 new Grad4(-0.7821684431180708, -0.4321472685365301, 0.12128480194602098, -0.4321472685365301), 626 new Grad4(-0.7821684431180708, 0.12128480194602098, -0.4321472685365301, -0.4321472685365301), 627 new Grad4(-0.8586508742123365, -0.508629699630796, 0.044802370851755174, 0.044802370851755174), 628 new Grad4(-0.8586508742123365, 0.044802370851755174, -0.508629699630796, 0.044802370851755174), 629 new Grad4(-0.8586508742123365, 0.044802370851755174, 0.044802370851755174, -0.508629699630796), 630 new Grad4(-0.9982828964265062, -0.03381941603233842, -0.03381941603233842, -0.03381941603233842), 631 new Grad4(-0.37968289875261624, -0.753341017856078, -0.37968289875261624, -0.37968289875261624), 632 new Grad4(-0.4321472685365301, -0.7821684431180708, -0.4321472685365301, 0.12128480194602098), 633 new Grad4(-0.4321472685365301, -0.7821684431180708, 0.12128480194602098, -0.4321472685365301), 634 new Grad4( 0.12128480194602098, -0.7821684431180708, -0.4321472685365301, -0.4321472685365301), 635 new Grad4(-0.508629699630796, -0.8586508742123365, 0.044802370851755174, 0.044802370851755174), 636 new Grad4( 0.044802370851755174, -0.8586508742123365, -0.508629699630796, 0.044802370851755174), 637 new Grad4( 0.044802370851755174, -0.8586508742123365, 0.044802370851755174, -0.508629699630796), 638 new Grad4(-0.03381941603233842, -0.9982828964265062, -0.03381941603233842, -0.03381941603233842), 639 new Grad4(-0.37968289875261624, -0.37968289875261624, -0.753341017856078, -0.37968289875261624), 640 new Grad4(-0.4321472685365301, -0.4321472685365301, -0.7821684431180708, 0.12128480194602098), 641 new Grad4(-0.4321472685365301, 0.12128480194602098, -0.7821684431180708, -0.4321472685365301), 642 new Grad4( 0.12128480194602098, -0.4321472685365301, -0.7821684431180708, -0.4321472685365301), 643 new Grad4(-0.508629699630796, 0.044802370851755174, -0.8586508742123365, 0.044802370851755174), 644 new Grad4( 0.044802370851755174, -0.508629699630796, -0.8586508742123365, 0.044802370851755174), 645 new Grad4( 0.044802370851755174, 0.044802370851755174, -0.8586508742123365, -0.508629699630796), 646 new Grad4(-0.03381941603233842, -0.03381941603233842, -0.9982828964265062, -0.03381941603233842), 647 new Grad4(-0.37968289875261624, -0.37968289875261624, -0.37968289875261624, -0.753341017856078), 648 new Grad4(-0.4321472685365301, -0.4321472685365301, 0.12128480194602098, -0.7821684431180708), 649 new Grad4(-0.4321472685365301, 0.12128480194602098, -0.4321472685365301, -0.7821684431180708), 650 new Grad4( 0.12128480194602098, -0.4321472685365301, -0.4321472685365301, -0.7821684431180708), 651 new Grad4(-0.508629699630796, 0.044802370851755174, 0.044802370851755174, -0.8586508742123365), 652 new Grad4( 0.044802370851755174, -0.508629699630796, 0.044802370851755174, -0.8586508742123365), 653 new Grad4( 0.044802370851755174, 0.044802370851755174, -0.508629699630796, -0.8586508742123365), 654 new Grad4(-0.03381941603233842, -0.03381941603233842, -0.03381941603233842, -0.9982828964265062), 655 new Grad4(-0.6740059517812944, -0.3239847771997537, -0.3239847771997537, 0.5794684678643381), 656 new Grad4(-0.7504883828755602, -0.4004672082940195, 0.15296486218853164, 0.5029860367700724), 657 new Grad4(-0.7504883828755602, 0.15296486218853164, -0.4004672082940195, 0.5029860367700724), 658 new Grad4(-0.8828161875373585, 0.08164729285680945, 0.08164729285680945, 0.4553054119602712), 659 new Grad4(-0.4553054119602712, -0.08164729285680945, -0.08164729285680945, 0.8828161875373585), 660 new Grad4(-0.5029860367700724, -0.15296486218853164, 0.4004672082940195, 0.7504883828755602), 661 new Grad4(-0.5029860367700724, 0.4004672082940195, -0.15296486218853164, 0.7504883828755602), 662 new Grad4(-0.5794684678643381, 0.3239847771997537, 0.3239847771997537, 0.6740059517812944), 663 new Grad4(-0.3239847771997537, -0.6740059517812944, -0.3239847771997537, 0.5794684678643381), 664 new Grad4(-0.4004672082940195, -0.7504883828755602, 0.15296486218853164, 0.5029860367700724), 665 new Grad4( 0.15296486218853164, -0.7504883828755602, -0.4004672082940195, 0.5029860367700724), 666 new Grad4( 0.08164729285680945, -0.8828161875373585, 0.08164729285680945, 0.4553054119602712), 667 new Grad4(-0.08164729285680945, -0.4553054119602712, -0.08164729285680945, 0.8828161875373585), 668 new Grad4(-0.15296486218853164, -0.5029860367700724, 0.4004672082940195, 0.7504883828755602), 669 new Grad4( 0.4004672082940195, -0.5029860367700724, -0.15296486218853164, 0.7504883828755602), 670 new Grad4( 0.3239847771997537, -0.5794684678643381, 0.3239847771997537, 0.6740059517812944), 671 new Grad4(-0.3239847771997537, -0.3239847771997537, -0.6740059517812944, 0.5794684678643381), 672 new Grad4(-0.4004672082940195, 0.15296486218853164, -0.7504883828755602, 0.5029860367700724), 673 new Grad4( 0.15296486218853164, -0.4004672082940195, -0.7504883828755602, 0.5029860367700724), 674 new Grad4( 0.08164729285680945, 0.08164729285680945, -0.8828161875373585, 0.4553054119602712), 675 new Grad4(-0.08164729285680945, -0.08164729285680945, -0.4553054119602712, 0.8828161875373585), 676 new Grad4(-0.15296486218853164, 0.4004672082940195, -0.5029860367700724, 0.7504883828755602), 677 new Grad4( 0.4004672082940195, -0.15296486218853164, -0.5029860367700724, 0.7504883828755602), 678 new Grad4( 0.3239847771997537, 0.3239847771997537, -0.5794684678643381, 0.6740059517812944), 679 new Grad4(-0.6740059517812944, -0.3239847771997537, 0.5794684678643381, -0.3239847771997537), 680 new Grad4(-0.7504883828755602, -0.4004672082940195, 0.5029860367700724, 0.15296486218853164), 681 new Grad4(-0.7504883828755602, 0.15296486218853164, 0.5029860367700724, -0.4004672082940195), 682 new Grad4(-0.8828161875373585, 0.08164729285680945, 0.4553054119602712, 0.08164729285680945), 683 new Grad4(-0.4553054119602712, -0.08164729285680945, 0.8828161875373585, -0.08164729285680945), 684 new Grad4(-0.5029860367700724, -0.15296486218853164, 0.7504883828755602, 0.4004672082940195), 685 new Grad4(-0.5029860367700724, 0.4004672082940195, 0.7504883828755602, -0.15296486218853164), 686 new Grad4(-0.5794684678643381, 0.3239847771997537, 0.6740059517812944, 0.3239847771997537), 687 new Grad4(-0.3239847771997537, -0.6740059517812944, 0.5794684678643381, -0.3239847771997537), 688 new Grad4(-0.4004672082940195, -0.7504883828755602, 0.5029860367700724, 0.15296486218853164), 689 new Grad4( 0.15296486218853164, -0.7504883828755602, 0.5029860367700724, -0.4004672082940195), 690 new Grad4( 0.08164729285680945, -0.8828161875373585, 0.4553054119602712, 0.08164729285680945), 691 new Grad4(-0.08164729285680945, -0.4553054119602712, 0.8828161875373585, -0.08164729285680945), 692 new Grad4(-0.15296486218853164, -0.5029860367700724, 0.7504883828755602, 0.4004672082940195), 693 new Grad4( 0.4004672082940195, -0.5029860367700724, 0.7504883828755602, -0.15296486218853164), 694 new Grad4( 0.3239847771997537, -0.5794684678643381, 0.6740059517812944, 0.3239847771997537), 695 new Grad4(-0.3239847771997537, -0.3239847771997537, 0.5794684678643381, -0.6740059517812944), 696 new Grad4(-0.4004672082940195, 0.15296486218853164, 0.5029860367700724, -0.7504883828755602), 697 new Grad4( 0.15296486218853164, -0.4004672082940195, 0.5029860367700724, -0.7504883828755602), 698 new Grad4( 0.08164729285680945, 0.08164729285680945, 0.4553054119602712, -0.8828161875373585), 699 new Grad4(-0.08164729285680945, -0.08164729285680945, 0.8828161875373585, -0.4553054119602712), 700 new Grad4(-0.15296486218853164, 0.4004672082940195, 0.7504883828755602, -0.5029860367700724), 701 new Grad4( 0.4004672082940195, -0.15296486218853164, 0.7504883828755602, -0.5029860367700724), 702 new Grad4( 0.3239847771997537, 0.3239847771997537, 0.6740059517812944, -0.5794684678643381), 703 new Grad4(-0.6740059517812944, 0.5794684678643381, -0.3239847771997537, -0.3239847771997537), 704 new Grad4(-0.7504883828755602, 0.5029860367700724, -0.4004672082940195, 0.15296486218853164), 705 new Grad4(-0.7504883828755602, 0.5029860367700724, 0.15296486218853164, -0.4004672082940195), 706 new Grad4(-0.8828161875373585, 0.4553054119602712, 0.08164729285680945, 0.08164729285680945), 707 new Grad4(-0.4553054119602712, 0.8828161875373585, -0.08164729285680945, -0.08164729285680945), 708 new Grad4(-0.5029860367700724, 0.7504883828755602, -0.15296486218853164, 0.4004672082940195), 709 new Grad4(-0.5029860367700724, 0.7504883828755602, 0.4004672082940195, -0.15296486218853164), 710 new Grad4(-0.5794684678643381, 0.6740059517812944, 0.3239847771997537, 0.3239847771997537), 711 new Grad4(-0.3239847771997537, 0.5794684678643381, -0.6740059517812944, -0.3239847771997537), 712 new Grad4(-0.4004672082940195, 0.5029860367700724, -0.7504883828755602, 0.15296486218853164), 713 new Grad4( 0.15296486218853164, 0.5029860367700724, -0.7504883828755602, -0.4004672082940195), 714 new Grad4( 0.08164729285680945, 0.4553054119602712, -0.8828161875373585, 0.08164729285680945), 715 new Grad4(-0.08164729285680945, 0.8828161875373585, -0.4553054119602712, -0.08164729285680945), 716 new Grad4(-0.15296486218853164, 0.7504883828755602, -0.5029860367700724, 0.4004672082940195), 717 new Grad4( 0.4004672082940195, 0.7504883828755602, -0.5029860367700724, -0.15296486218853164), 718 new Grad4( 0.3239847771997537, 0.6740059517812944, -0.5794684678643381, 0.3239847771997537), 719 new Grad4(-0.3239847771997537, 0.5794684678643381, -0.3239847771997537, -0.6740059517812944), 720 new Grad4(-0.4004672082940195, 0.5029860367700724, 0.15296486218853164, -0.7504883828755602), 721 new Grad4( 0.15296486218853164, 0.5029860367700724, -0.4004672082940195, -0.7504883828755602), 722 new Grad4( 0.08164729285680945, 0.4553054119602712, 0.08164729285680945, -0.8828161875373585), 723 new Grad4(-0.08164729285680945, 0.8828161875373585, -0.08164729285680945, -0.4553054119602712), 724 new Grad4(-0.15296486218853164, 0.7504883828755602, 0.4004672082940195, -0.5029860367700724), 725 new Grad4( 0.4004672082940195, 0.7504883828755602, -0.15296486218853164, -0.5029860367700724), 726 new Grad4( 0.3239847771997537, 0.6740059517812944, 0.3239847771997537, -0.5794684678643381), 727 new Grad4( 0.5794684678643381, -0.6740059517812944, -0.3239847771997537, -0.3239847771997537), 728 new Grad4( 0.5029860367700724, -0.7504883828755602, -0.4004672082940195, 0.15296486218853164), 729 new Grad4( 0.5029860367700724, -0.7504883828755602, 0.15296486218853164, -0.4004672082940195), 730 new Grad4( 0.4553054119602712, -0.8828161875373585, 0.08164729285680945, 0.08164729285680945), 731 new Grad4( 0.8828161875373585, -0.4553054119602712, -0.08164729285680945, -0.08164729285680945), 732 new Grad4( 0.7504883828755602, -0.5029860367700724, -0.15296486218853164, 0.4004672082940195), 733 new Grad4( 0.7504883828755602, -0.5029860367700724, 0.4004672082940195, -0.15296486218853164), 734 new Grad4( 0.6740059517812944, -0.5794684678643381, 0.3239847771997537, 0.3239847771997537), 735 new Grad4( 0.5794684678643381, -0.3239847771997537, -0.6740059517812944, -0.3239847771997537), 736 new Grad4( 0.5029860367700724, -0.4004672082940195, -0.7504883828755602, 0.15296486218853164), 737 new Grad4( 0.5029860367700724, 0.15296486218853164, -0.7504883828755602, -0.4004672082940195), 738 new Grad4( 0.4553054119602712, 0.08164729285680945, -0.8828161875373585, 0.08164729285680945), 739 new Grad4( 0.8828161875373585, -0.08164729285680945, -0.4553054119602712, -0.08164729285680945), 740 new Grad4( 0.7504883828755602, -0.15296486218853164, -0.5029860367700724, 0.4004672082940195), 741 new Grad4( 0.7504883828755602, 0.4004672082940195, -0.5029860367700724, -0.15296486218853164), 742 new Grad4( 0.6740059517812944, 0.3239847771997537, -0.5794684678643381, 0.3239847771997537), 743 new Grad4( 0.5794684678643381, -0.3239847771997537, -0.3239847771997537, -0.6740059517812944), 744 new Grad4( 0.5029860367700724, -0.4004672082940195, 0.15296486218853164, -0.7504883828755602), 745 new Grad4( 0.5029860367700724, 0.15296486218853164, -0.4004672082940195, -0.7504883828755602), 746 new Grad4( 0.4553054119602712, 0.08164729285680945, 0.08164729285680945, -0.8828161875373585), 747 new Grad4( 0.8828161875373585, -0.08164729285680945, -0.08164729285680945, -0.4553054119602712), 748 new Grad4( 0.7504883828755602, -0.15296486218853164, 0.4004672082940195, -0.5029860367700724), 749 new Grad4( 0.7504883828755602, 0.4004672082940195, -0.15296486218853164, -0.5029860367700724), 750 new Grad4( 0.6740059517812944, 0.3239847771997537, 0.3239847771997537, -0.5794684678643381), 751 new Grad4( 0.03381941603233842, 0.03381941603233842, 0.03381941603233842, 0.9982828964265062), 752 new Grad4(-0.044802370851755174, -0.044802370851755174, 0.508629699630796, 0.8586508742123365), 753 new Grad4(-0.044802370851755174, 0.508629699630796, -0.044802370851755174, 0.8586508742123365), 754 new Grad4(-0.12128480194602098, 0.4321472685365301, 0.4321472685365301, 0.7821684431180708), 755 new Grad4( 0.508629699630796, -0.044802370851755174, -0.044802370851755174, 0.8586508742123365), 756 new Grad4( 0.4321472685365301, -0.12128480194602098, 0.4321472685365301, 0.7821684431180708), 757 new Grad4( 0.4321472685365301, 0.4321472685365301, -0.12128480194602098, 0.7821684431180708), 758 new Grad4( 0.37968289875261624, 0.37968289875261624, 0.37968289875261624, 0.753341017856078), 759 new Grad4( 0.03381941603233842, 0.03381941603233842, 0.9982828964265062, 0.03381941603233842), 760 new Grad4(-0.044802370851755174, 0.044802370851755174, 0.8586508742123365, 0.508629699630796), 761 new Grad4(-0.044802370851755174, 0.508629699630796, 0.8586508742123365, -0.044802370851755174), 762 new Grad4(-0.12128480194602098, 0.4321472685365301, 0.7821684431180708, 0.4321472685365301), 763 new Grad4( 0.508629699630796, -0.044802370851755174, 0.8586508742123365, -0.044802370851755174), 764 new Grad4( 0.4321472685365301, -0.12128480194602098, 0.7821684431180708, 0.4321472685365301), 765 new Grad4( 0.4321472685365301, 0.4321472685365301, 0.7821684431180708, -0.12128480194602098), 766 new Grad4( 0.37968289875261624, 0.37968289875261624, 0.753341017856078, 0.37968289875261624), 767 new Grad4( 0.03381941603233842, 0.9982828964265062, 0.03381941603233842, 0.03381941603233842), 768 new Grad4(-0.044802370851755174, 0.8586508742123365, -0.044802370851755174, 0.508629699630796), 769 new Grad4(-0.044802370851755174, 0.8586508742123365, 0.508629699630796, -0.044802370851755174), 770 new Grad4(-0.12128480194602098, 0.7821684431180708, 0.4321472685365301, 0.4321472685365301), 771 new Grad4( 0.508629699630796, 0.8586508742123365, -0.044802370851755174, -0.044802370851755174), 772 new Grad4( 0.4321472685365301, 0.7821684431180708, -0.12128480194602098, 0.4321472685365301), 773 new Grad4( 0.4321472685365301, 0.7821684431180708, 0.4321472685365301, -0.12128480194602098), 774 new Grad4( 0.37968289875261624, 0.753341017856078, 0.37968289875261624, 0.37968289875261624), 775 new Grad4( 0.9982828964265062, 0.03381941603233842, 0.03381941603233842, 0.03381941603233842), 776 new Grad4( 0.8586508742123365, -0.044802370851755174, -0.044802370851755174, 0.508629699630796), 777 new Grad4( 0.8586508742123365, -0.044802370851755174, 0.508629699630796, -0.044802370851755174), 778 new Grad4( 0.7821684431180708, -0.12128480194602098, 0.4321472685365301, 0.4321472685365301), 779 new Grad4( 0.8586508742123365, 0.508629699630796, -0.044802370851755174, -0.044802370851755174), 780 new Grad4( 0.7821684431180708, 0.4321472685365301, -0.12128480194602098, 0.4321472685365301), 781 new Grad4( 0.7821684431180708, 0.4321472685365301, 0.4321472685365301, -0.12128480194602098), 782 new Grad4( 0.753341017856078, 0.37968289875261624, 0.37968289875261624, 0.37968289875261624) 783 ]; 784 for (int i = 0; i < grad4.length; i++) { 785 grad4[i].dx /= N4; grad4[i].dy /= N4; grad4[i].dz /= N4; grad4[i].dw /= N4; 786 } 787 for (int i = 0; i < PSIZE; i++) { 788 GRADIENTS_4D[i] = grad4[i % grad4.length]; 789 } 790 } 791 } 792 793 @("OpenSimplex2F 2D") 794 unittest 795 { 796 import imageformats : IFImage, ColFmt, write_png; 797 import std.conv : to; 798 799 OpenSimplex2F openSimplex2f = new OpenSimplex2F(3_874_6527_389_465L); 800 801 enum WIDTH = 512; 802 enum HEIGHT = 512; 803 enum SCALE = 64; 804 805 ubyte[WIDTH * HEIGHT] pixels; 806 807 foreach (size_t i, ref ubyte pixel; pixels) 808 { 809 immutable size_t x = i % WIDTH; 810 immutable size_t y = i / HEIGHT; 811 pixel = ((openSimplex2f.noise2(x.to!double / SCALE, y.to!double / SCALE) + 1) * 127).to!ubyte; 812 } 813 814 815 IFImage img = IFImage(WIDTH, HEIGHT, ColFmt.Y, pixels); 816 write_png("./test-results/OpenSimplex2F 2D.png", WIDTH, HEIGHT, img.pixels); 817 } 818 819 @("OpenSimplex2F 3D slice") 820 unittest 821 { 822 import imageformats : IFImage, ColFmt, write_png; 823 import std.conv : to; 824 825 OpenSimplex2F openSimplex2f = new OpenSimplex2F(3_874_6527_389_465L); 826 827 enum WIDTH = 512; 828 enum HEIGHT = 512; 829 enum SCALE = 64; 830 831 ubyte[WIDTH * HEIGHT] pixels; 832 833 foreach (size_t i, ref ubyte pixel; pixels) 834 { 835 immutable size_t x = i % WIDTH; 836 immutable size_t y = i / HEIGHT; 837 pixel = ((openSimplex2f.noise3_XYBeforeZ(x.to!double / SCALE, y.to!double / SCALE, 0) + 1) * 127).to!ubyte; 838 } 839 840 841 IFImage img = IFImage(WIDTH, HEIGHT, ColFmt.Y, pixels); 842 write_png("./test-results/OpenSimplex2F 3D XYbeforeZ.png", WIDTH, HEIGHT, img.pixels); 843 } 844 845 @("OpenSimplex2F 4D slice") 846 unittest 847 { 848 import imageformats : IFImage, ColFmt, write_png; 849 import std.conv : to; 850 851 OpenSimplex2F openSimplex2f = new OpenSimplex2F(3_874_6527_389_465L); 852 853 enum WIDTH = 512; 854 enum HEIGHT = 512; 855 enum SCALE = 64; 856 857 ubyte[WIDTH * HEIGHT] pixels; 858 859 foreach (size_t i, ref ubyte pixel; pixels) 860 { 861 immutable size_t x = i % WIDTH; 862 immutable size_t y = i / HEIGHT; 863 pixel = ((openSimplex2f.noise4_Classic(x.to!double / SCALE, y.to!double / SCALE, 0, 0) + 1) * 127).to!ubyte; 864 } 865 866 867 IFImage img = IFImage(WIDTH, HEIGHT, ColFmt.Y, pixels); 868 write_png("./test-results/OpenSimplex2F 4D.png", WIDTH, HEIGHT, img.pixels); 869 } 870 871 @("OpenSimplex2F 2D speed test") 872 unittest 873 { 874 // For best results, run unittests compiled with ldc2 and compiler flags "-optimize" and "-inline" 875 import std.conv : to; 876 import std.datetime.stopwatch : StopWatch, Duration; 877 import std.stdio : writeln; 878 879 OpenSimplex2F openSimplex2f = new OpenSimplex2F(3_874_6527_389_465L); 880 881 882 StopWatch stopwatch; 883 stopwatch.start(); 884 foreach (i; 0..1_000_000) 885 { 886 openSimplex2f.noise2(i.to!double, (999_999 - i).to!double); 887 } 888 writeln(stopwatch.peek().split!"nsecs".nsecs / 1_000_000.0); 889 }