psrdnoise2D.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. //
  2. // float3 psrdnoise(float2 pos, float2 per, float rot)
  3. // float3 psrdnoise(float2 pos, float2 per)
  4. // float psrnoise(float2 pos, float2 per, float rot)
  5. // float psrnoise(float2 pos, float2 per)
  6. // float3 srdnoise(float2 pos, float rot)
  7. // float3 srdnoise(float2 pos)
  8. // float srnoise(float2 pos, float rot)
  9. // float srnoise(float2 pos)
  10. //
  11. // Periodic (tiling) 2-D simplex noise (hexagonal lattice gradient noise)
  12. // with rotating gradients and analytic derivatives.
  13. // Variants also without the derivative (no "d" in the name), without
  14. // the tiling property (no "p" in the name) and without the rotating
  15. // gradients (no "r" in the name).
  16. //
  17. // This is (yet) another variation on simplex noise. It's similar to the
  18. // version presented by Ken Perlin, but the grid is axis-aligned and
  19. // slightly stretched in the y direction to permit rectangular tiling.
  20. //
  21. // The noise can be made to tile seamlessly to any integer period in x and
  22. // any even integer period in y. Odd periods may be specified for y, but
  23. // then the actual tiling period will be twice that number.
  24. //
  25. // The rotating gradients give the appearance of a swirling motion, and can
  26. // serve a similar purpose for animation as motion along z in 3-D noise.
  27. // The rotating gradients in conjunction with the analytic derivatives
  28. // can make "flow noise" effects as presented by Perlin and Neyret.
  29. //
  30. // float3 {p}s{r}dnoise(float2 pos {, float2 per} {, float rot})
  31. // "pos" is the input (x,y) coordinate
  32. // "per" is the x and y period, where per.x is a positive integer
  33. // and per.y is a positive even integer
  34. // "rot" is the angle to rotate the gradients (any float value,
  35. // where 0.0 is no rotation and 1.0 is one full turn)
  36. // The first component of the 3-element return vector is the noise value.
  37. // The second and third components are the x and y partial derivatives.
  38. //
  39. // float {p}s{r}noise(float2 pos {, float2 per} {, float rot})
  40. // "pos" is the input (x,y) coordinate
  41. // "per" is the x and y period, where per.x is a positive integer
  42. // and per.y is a positive even integer
  43. // "rot" is the angle to rotate the gradients (any float value,
  44. // where 0.0 is no rotation and 1.0 is one full turn)
  45. // The return value is the noise value.
  46. // Partial derivatives are not computed, making these functions faster.
  47. //
  48. // Author: Stefan Gustavson (stefan.gustavson@gmail.com)
  49. // Version 2016-05-10.
  50. //
  51. // Many thanks to Ian McEwan of Ashima Arts for the
  52. // idea of umath.sing a permutation polynomial.
  53. //
  54. // Copyright (c) 2016 Stefan Gustavson. All rights reserved.
  55. // Distributed under the MIT license. See LICENSE file.
  56. // https://github.com/stegu/webgl-noise
  57. //
  58. //
  59. // TODO: One-pixel wide artefacts used to occur due to precision issues with
  60. // the gradient indexing. This is specific to this variant of noise, because
  61. // one axis of the simplex grid is perfectly aligned with the input x axis.
  62. // The errors were rare, and they are now very unlikely to ever be visible
  63. // after a quick fix was introduced: a small offset is added to the y coordinate.
  64. // A proper fix would involve umath.sing round() instead of math.floor() in selected
  65. // places, but the quick fix works fine.
  66. // (If you run into problems with this, please let me know.)
  67. //
  68. using static Unity.Mathematics.math;
  69. namespace Unity.Mathematics
  70. {
  71. public static partial class noise
  72. {
  73. //
  74. // 2-D tiling simplex noise with rotating gradients and analytical derivative.
  75. // The first component of the 3-element return vector is the noise value,
  76. // and the second and third components are the x and y partial derivatives.
  77. //
  78. public static float3 psrdnoise(float2 pos, float2 per, float rot)
  79. {
  80. // Hack: offset y slightly to hide some rare artifacts
  81. pos.y += 0.01f;
  82. // Skew to hexagonal grid
  83. float2 uv = float2(pos.x + pos.y * 0.5f, pos.y);
  84. float2 i0 = floor(uv);
  85. float2 f0 = frac(uv);
  86. // Traversal order
  87. float2 i1 = (f0.x > f0.y) ? float2(1.0f, 0.0f) : float2(0.0f, 1.0f);
  88. // Unskewed grid points in (x,y) space
  89. float2 p0 = float2(i0.x - i0.y * 0.5f, i0.y);
  90. float2 p1 = float2(p0.x + i1.x - i1.y * 0.5f, p0.y + i1.y);
  91. float2 p2 = float2(p0.x + 0.5f, p0.y + 1.0f);
  92. // Vectors in unskewed (x,y) coordinates from
  93. // each of the simplex corners to the evaluation point
  94. float2 d0 = pos - p0;
  95. float2 d1 = pos - p1;
  96. float2 d2 = pos - p2;
  97. // Wrap p0, p1 and p2 to the desired period before gradient hashing:
  98. // wrap points in (x,y), map to (u,v)
  99. float3 xw = fmod(float3(p0.x, p1.x, p2.x), per.x);
  100. float3 yw = fmod(float3(p0.y, p1.y, p2.y), per.y);
  101. float3 iuw = xw + 0.5f * yw;
  102. float3 ivw = yw;
  103. // Create gradients from indices
  104. float2 g0 = rgrad2(float2(iuw.x, ivw.x), rot);
  105. float2 g1 = rgrad2(float2(iuw.y, ivw.y), rot);
  106. float2 g2 = rgrad2(float2(iuw.z, ivw.z), rot);
  107. // Gradients math.dot vectors to corresponding corners
  108. // (The derivatives of this are simply the gradients)
  109. float3 w = float3(dot(g0, d0), dot(g1, d1), dot(g2, d2));
  110. // Radial weights from corners
  111. // 0.8 is the square of 2/math.sqrt(5), the distance from
  112. // a grid point to the nearest simplex boundary
  113. float3 t = 0.8f - float3(dot(d0, d0), dot(d1, d1), dot(d2, d2));
  114. // Partial derivatives for analytical gradient computation
  115. float3 dtdx = -2.0f * float3(d0.x, d1.x, d2.x);
  116. float3 dtdy = -2.0f * float3(d0.y, d1.y, d2.y);
  117. // Set influence of each surflet to zero outside radius math.sqrt(0.8)
  118. if (t.x < 0.0f)
  119. {
  120. dtdx.x = 0.0f;
  121. dtdy.x = 0.0f;
  122. t.x = 0.0f;
  123. }
  124. if (t.y < 0.0f)
  125. {
  126. dtdx.y = 0.0f;
  127. dtdy.y = 0.0f;
  128. t.y = 0.0f;
  129. }
  130. if (t.z < 0.0f)
  131. {
  132. dtdx.z = 0.0f;
  133. dtdy.z = 0.0f;
  134. t.z = 0.0f;
  135. }
  136. // Fourth power of t (and third power for derivative)
  137. float3 t2 = t * t;
  138. float3 t4 = t2 * t2;
  139. float3 t3 = t2 * t;
  140. // Final noise value is:
  141. // sum of ((radial weights) times (gradient math.dot vector from corner))
  142. float n = dot(t4, w);
  143. // Final analytical derivative (gradient of a sum of scalar products)
  144. float2 dt0 = float2(dtdx.x, dtdy.x) * 4.0f * t3.x;
  145. float2 dn0 = t4.x * g0 + dt0 * w.x;
  146. float2 dt1 = float2(dtdx.y, dtdy.y) * 4.0f * t3.y;
  147. float2 dn1 = t4.y * g1 + dt1 * w.y;
  148. float2 dt2 = float2(dtdx.z, dtdy.z) * 4.0f * t3.z;
  149. float2 dn2 = t4.z * g2 + dt2 * w.z;
  150. return 11.0f * float3(n, dn0 + dn1 + dn2);
  151. }
  152. //
  153. // 2-D tiling simplex noise with fixed gradients
  154. // and analytical derivative.
  155. // This function is implemented as a wrapper to "psrdnoise",
  156. // at the math.minimal math.cost of three extra additions.
  157. //
  158. public static float3 psrdnoise(float2 pos, float2 per)
  159. {
  160. return psrdnoise(pos, per, 0.0f);
  161. }
  162. //
  163. // 2-D tiling simplex noise with rotating gradients,
  164. // but without the analytical derivative.
  165. //
  166. public static float psrnoise(float2 pos, float2 per, float rot)
  167. {
  168. // Offset y slightly to hide some rare artifacts
  169. pos.y += 0.001f;
  170. // Skew to hexagonal grid
  171. float2 uv = float2(pos.x + pos.y * 0.5f, pos.y);
  172. float2 i0 = floor(uv);
  173. float2 f0 = frac(uv);
  174. // Traversal order
  175. float2 i1 = (f0.x > f0.y) ? float2(1.0f, 0.0f) : float2(0.0f, 1.0f);
  176. // Unskewed grid points in (x,y) space
  177. float2 p0 = float2(i0.x - i0.y * 0.5f, i0.y);
  178. float2 p1 = float2(p0.x + i1.x - i1.y * 0.5f, p0.y + i1.y);
  179. float2 p2 = float2(p0.x + 0.5f, p0.y + 1.0f);
  180. // Vectors in unskewed (x,y) coordinates from
  181. // each of the simplex corners to the evaluation point
  182. float2 d0 = pos - p0;
  183. float2 d1 = pos - p1;
  184. float2 d2 = pos - p2;
  185. // Wrap p0, p1 and p2 to the desired period before gradient hashing:
  186. // wrap points in (x,y), map to (u,v)
  187. float3 xw = fmod(float3(p0.x, p1.x, p2.x), per.x);
  188. float3 yw = fmod(float3(p0.y, p1.y, p2.y), per.y);
  189. float3 iuw = xw + 0.5f * yw;
  190. float3 ivw = yw;
  191. // Create gradients from indices
  192. float2 g0 = rgrad2(float2(iuw.x, ivw.x), rot);
  193. float2 g1 = rgrad2(float2(iuw.y, ivw.y), rot);
  194. float2 g2 = rgrad2(float2(iuw.z, ivw.z), rot);
  195. // Gradients math.dot vectors to corresponding corners
  196. // (The derivatives of this are simply the gradients)
  197. float3 w = float3(dot(g0, d0), dot(g1, d1), dot(g2, d2));
  198. // Radial weights from corners
  199. // 0.8 is the square of 2/math.sqrt(5), the distance from
  200. // a grid point to the nearest simplex boundary
  201. float3 t = 0.8f - float3(dot(d0, d0), dot(d1, d1), dot(d2, d2));
  202. // Set influence of each surflet to zero outside radius math.sqrt(0.8)
  203. t = max(t, 0.0f);
  204. // Fourth power of t
  205. float3 t2 = t * t;
  206. float3 t4 = t2 * t2;
  207. // Final noise value is:
  208. // sum of ((radial weights) times (gradient math.dot vector from corner))
  209. float n = dot(t4, w);
  210. // Rescale to cover the range [-1,1] reasonably well
  211. return 11.0f * n;
  212. }
  213. //
  214. // 2-D tiling simplex noise with fixed gradients,
  215. // without the analytical derivative.
  216. // This function is implemented as a wrapper to "psrnoise",
  217. // at the math.minimal math.cost of three extra additions.
  218. //
  219. public static float psrnoise(float2 pos, float2 per)
  220. {
  221. return psrnoise(pos, per, 0.0f);
  222. }
  223. //
  224. // 2-D non-tiling simplex noise with rotating gradients and analytical derivative.
  225. // The first component of the 3-element return vector is the noise value,
  226. // and the second and third components are the x and y partial derivatives.
  227. //
  228. public static float3 srdnoise(float2 pos, float rot)
  229. {
  230. // Offset y slightly to hide some rare artifacts
  231. pos.y += 0.001f;
  232. // Skew to hexagonal grid
  233. float2 uv = float2(pos.x + pos.y * 0.5f, pos.y);
  234. float2 i0 = floor(uv);
  235. float2 f0 = frac(uv);
  236. // Traversal order
  237. float2 i1 = (f0.x > f0.y) ? float2(1.0f, 0.0f) : float2(0.0f, 1.0f);
  238. // Unskewed grid points in (x,y) space
  239. float2 p0 = float2(i0.x - i0.y * 0.5f, i0.y);
  240. float2 p1 = float2(p0.x + i1.x - i1.y * 0.5f, p0.y + i1.y);
  241. float2 p2 = float2(p0.x + 0.5f, p0.y + 1.0f);
  242. // Vectors in unskewed (x,y) coordinates from
  243. // each of the simplex corners to the evaluation point
  244. float2 d0 = pos - p0;
  245. float2 d1 = pos - p1;
  246. float2 d2 = pos - p2;
  247. float3 x = float3(p0.x, p1.x, p2.x);
  248. float3 y = float3(p0.y, p1.y, p2.y);
  249. float3 iuw = x + 0.5f * y;
  250. float3 ivw = y;
  251. // Avoid precision issues in permutation
  252. iuw = mod289(iuw);
  253. ivw = mod289(ivw);
  254. // Create gradients from indices
  255. float2 g0 = rgrad2(float2(iuw.x, ivw.x), rot);
  256. float2 g1 = rgrad2(float2(iuw.y, ivw.y), rot);
  257. float2 g2 = rgrad2(float2(iuw.z, ivw.z), rot);
  258. // Gradients math.dot vectors to corresponding corners
  259. // (The derivatives of this are simply the gradients)
  260. float3 w = float3(dot(g0, d0), dot(g1, d1), dot(g2, d2));
  261. // Radial weights from corners
  262. // 0.8 is the square of 2/math.sqrt(5), the distance from
  263. // a grid point to the nearest simplex boundary
  264. float3 t = 0.8f - float3(dot(d0, d0), dot(d1, d1), dot(d2, d2));
  265. // Partial derivatives for analytical gradient computation
  266. float3 dtdx = -2.0f * float3(d0.x, d1.x, d2.x);
  267. float3 dtdy = -2.0f * float3(d0.y, d1.y, d2.y);
  268. // Set influence of each surflet to zero outside radius math.sqrt(0.8)
  269. if (t.x < 0.0f)
  270. {
  271. dtdx.x = 0.0f;
  272. dtdy.x = 0.0f;
  273. t.x = 0.0f;
  274. }
  275. if (t.y < 0.0f)
  276. {
  277. dtdx.y = 0.0f;
  278. dtdy.y = 0.0f;
  279. t.y = 0.0f;
  280. }
  281. if (t.z < 0.0f)
  282. {
  283. dtdx.z = 0.0f;
  284. dtdy.z = 0.0f;
  285. t.z = 0.0f;
  286. }
  287. // Fourth power of t (and third power for derivative)
  288. float3 t2 = t * t;
  289. float3 t4 = t2 * t2;
  290. float3 t3 = t2 * t;
  291. // Final noise value is:
  292. // sum of ((radial weights) times (gradient math.dot vector from corner))
  293. float n = dot(t4, w);
  294. // Final analytical derivative (gradient of a sum of scalar products)
  295. float2 dt0 = float2(dtdx.x, dtdy.x) * 4.0f * t3.x;
  296. float2 dn0 = t4.x * g0 + dt0 * w.x;
  297. float2 dt1 = float2(dtdx.y, dtdy.y) * 4.0f * t3.y;
  298. float2 dn1 = t4.y * g1 + dt1 * w.y;
  299. float2 dt2 = float2(dtdx.z, dtdy.z) * 4.0f * t3.z;
  300. float2 dn2 = t4.z * g2 + dt2 * w.z;
  301. return 11.0f * float3(n, dn0 + dn1 + dn2);
  302. }
  303. //
  304. // 2-D non-tiling simplex noise with fixed gradients and analytical derivative.
  305. // This function is implemented as a wrapper to "srdnoise",
  306. // at the math.minimal math.cost of three extra additions.
  307. //
  308. public static float3 srdnoise(float2 pos)
  309. {
  310. return srdnoise(pos, 0.0f);
  311. }
  312. //
  313. // 2-D non-tiling simplex noise with rotating gradients,
  314. // without the analytical derivative.
  315. //
  316. public static float srnoise(float2 pos, float rot)
  317. {
  318. // Offset y slightly to hide some rare artifacts
  319. pos.y += 0.001f;
  320. // Skew to hexagonal grid
  321. float2 uv = float2(pos.x + pos.y * 0.5f, pos.y);
  322. float2 i0 = floor(uv);
  323. float2 f0 = frac(uv);
  324. // Traversal order
  325. float2 i1 = (f0.x > f0.y) ? float2(1.0f, 0.0f) : float2(0.0f, 1.0f);
  326. // Unskewed grid points in (x,y) space
  327. float2 p0 = float2(i0.x - i0.y * 0.5f, i0.y);
  328. float2 p1 = float2(p0.x + i1.x - i1.y * 0.5f, p0.y + i1.y);
  329. float2 p2 = float2(p0.x + 0.5f, p0.y + 1.0f);
  330. // Vectors in unskewed (x,y) coordinates from
  331. // each of the simplex corners to the evaluation point
  332. float2 d0 = pos - p0;
  333. float2 d1 = pos - p1;
  334. float2 d2 = pos - p2;
  335. float3 x = float3(p0.x, p1.x, p2.x);
  336. float3 y = float3(p0.y, p1.y, p2.y);
  337. float3 iuw = x + 0.5f * y;
  338. float3 ivw = y;
  339. // Avoid precision issues in permutation
  340. iuw = mod289(iuw);
  341. ivw = mod289(ivw);
  342. // Create gradients from indices
  343. float2 g0 = rgrad2(float2(iuw.x, ivw.x), rot);
  344. float2 g1 = rgrad2(float2(iuw.y, ivw.y), rot);
  345. float2 g2 = rgrad2(float2(iuw.z, ivw.z), rot);
  346. // Gradients math.dot vectors to corresponding corners
  347. // (The derivatives of this are simply the gradients)
  348. float3 w = float3(dot(g0, d0), dot(g1, d1), dot(g2, d2));
  349. // Radial weights from corners
  350. // 0.8 is the square of 2/math.sqrt(5), the distance from
  351. // a grid point to the nearest simplex boundary
  352. float3 t = 0.8f - float3(dot(d0, d0), dot(d1, d1), dot(d2, d2));
  353. // Set influence of each surflet to zero outside radius math.sqrt(0.8)
  354. t = max(t, 0.0f);
  355. // Fourth power of t
  356. float3 t2 = t * t;
  357. float3 t4 = t2 * t2;
  358. // Final noise value is:
  359. // sum of ((radial weights) times (gradient math.dot vector from corner))
  360. float n = dot(t4, w);
  361. // Rescale to cover the range [-1,1] reasonably well
  362. return 11.0f * n;
  363. }
  364. //
  365. // 2-D non-tiling simplex noise with fixed gradients,
  366. // without the analytical derivative.
  367. // This function is implemented as a wrapper to "srnoise",
  368. // at the math.minimal math.cost of three extra additions.
  369. // Note: if this kind of noise is all you want, there are faster
  370. // GLSL implementations of non-tiling simplex noise out there.
  371. // This one is included mainly for completeness and compatibility
  372. // with the other functions in the file.
  373. //
  374. public static float srnoise(float2 pos)
  375. {
  376. return srnoise(pos, 0.0f);
  377. }
  378. }
  379. }