curlNoise.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { mod, Fn, vec2, div, vec4, dot, floor, step, sub, min, max, mul, abs, vec3, inverseSqrt, add, float } from 'three/tsl';
  2. /**
  3. * Permutation polynomial for noise generation.
  4. *
  5. * @tsl
  6. * @function
  7. * @param {Node<vec4>} x - Input vector.
  8. * @return {Node<vec4>} Permuted vector.
  9. */
  10. export const permute = /*@__PURE__*/ Fn( ( [ x ] ) => {
  11. return mod( x.mul( x ).mul( 34. ).add( x ), 289. );
  12. }, { x: 'vec4', return: 'vec4' } );
  13. /**
  14. * 3D Simplex noise implementation in TSL.
  15. *
  16. * @tsl
  17. * @function
  18. * @param {Node<vec3>} v - Input coordinate vector.
  19. * @return {Node<float>} Simplex noise value.
  20. */
  21. export const snoise = /*@__PURE__*/ Fn( ( [ v ] ) => {
  22. const C = div( 1., vec2( 6, 3 ) );
  23. const D = vec4( 0, .5, 1, 2 );
  24. const i = floor( v.add( dot( v, C.yyy ) ) );
  25. const x0 = v.sub( i ).add( dot( i, C.xxx ) );
  26. const g = step( x0.yzx, x0.xyz );
  27. const l = sub( 1., g );
  28. const i1 = min( g.xyz, l.zxy );
  29. const i2 = max( g.xyz, l.zxy );
  30. const x1 = x0.sub( i1 ).add( C.x );
  31. const x2 = x0.sub( i2 ).add( C.y );
  32. const x3 = x0.sub( D.yyy );
  33. i.assign( mod( i, 289. ) );
  34. const p = permute( permute( permute( i.z.add( vec4( 0., i1.z, i2.z, 1. ) ) ).add( i.y ).add( vec4( 0., i1.y, i2.y, 1. ) ) ).add( i.x ).add( vec4( 0., i1.x, i2.x, 1. ) ) );
  35. const ns = mul( .142857142857, D.wyz ).sub( D.xzx );
  36. const j = p.sub( mul( 49., floor( p.mul( ns.z ).mul( ns.z ) ) ) );
  37. const x_ = floor( j.mul( ns.z ) );
  38. const x = x_.mul( ns.x ).add( ns.yyyy );
  39. const y = floor( j.sub( mul( 7., x_ ) ) ).mul( ns.x ).add( ns.yyyy );
  40. const h = sub( 1., abs( x ) ).sub( abs( y ) );
  41. const b0 = vec4( x.xy, y.xy );
  42. const b1 = vec4( x.zw, y.zw );
  43. const sh = step( h, vec4( 0 ) ).negate();
  44. const a0 = b0.xzyw.add( floor( b0 ).mul( 2. ).add( 1. ).xzyw.mul( sh.xxyy ) );
  45. const a1 = b1.xzyw.add( floor( b1 ).mul( 2. ).add( 1. ).xzyw.mul( sh.zzww ) );
  46. const p0 = vec3( a0.xy, h.x );
  47. const p1 = vec3( a0.zw, h.y );
  48. const p2 = vec3( a1.xy, h.z );
  49. const p3 = vec3( a1.zw, h.w );
  50. const norm = inverseSqrt( vec4( dot( p0, p0 ), dot( p1, p1 ), dot( p2, p2 ), dot( p3, p3 ) ) );
  51. p0.mulAssign( norm.x );
  52. p1.mulAssign( norm.y );
  53. p2.mulAssign( norm.z );
  54. p3.mulAssign( norm.w );
  55. const m = max( sub( .6, vec4( dot( x0, x0 ), dot( x1, x1 ), dot( x2, x2 ), dot( x3, x3 ) ) ), 0. );
  56. return add( .5, mul( 12., dot( m.mul( m ).mul( m ), vec4( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ), dot( p3, x3 ) ) ) ) );
  57. }, { v: 'vec3', return: 'float' } );
  58. /**
  59. * 3D Simplex noise vector. Returns a vec3 containing three independent noise samples.
  60. *
  61. * @tsl
  62. * @function
  63. * @param {Node<vec3>} x - Input coordinate vector.
  64. * @return {Node<vec3>} Vector of three noise values.
  65. */
  66. export const snoiseVec3 = /*@__PURE__*/ Fn( ( [ x ] ) => {
  67. return vec3( snoise( vec3( x ).mul( 2. ).sub( 1. ) ), snoise( vec3( x.y.sub( 19.1 ), x.z.add( 33.4 ), x.x.add( 47.2 ) ) ).mul( 2. ).sub( 1. ), snoise( vec3( x.z.add( 74.2 ), x.x.sub( 124.5 ), x.y.add( 99.4 ) ).mul( 2. ).sub( 1. ) ) );
  68. }, { x: 'vec3', return: 'vec3' } );
  69. /**
  70. * 3D Curl noise in TSL. Generates a divergence-free vector field from simplex noise.
  71. *
  72. * @tsl
  73. * @function
  74. * @param {Node<vec3>} p - Input coordinate vector.
  75. * @return {Node<vec3>} Curl noise vector.
  76. */
  77. export const curlNoise = /*@__PURE__*/ Fn( ( [ p ] ) => {
  78. const e = float( .1 );
  79. const dx = vec3( e, 0.0, 0.0 );
  80. const dy = vec3( 0.0, e, 0.0 );
  81. const dz = vec3( 0.0, 0.0, e );
  82. const p_x0 = snoiseVec3( p.sub( dx ) );
  83. const p_x1 = snoiseVec3( p.add( dx ) );
  84. const p_y0 = snoiseVec3( p.sub( dy ) );
  85. const p_y1 = snoiseVec3( p.add( dy ) );
  86. const p_z0 = snoiseVec3( p.sub( dz ) );
  87. const p_z1 = snoiseVec3( p.add( dz ) );
  88. const x = p_y1.z.sub( p_y0.z ).sub( p_z1.y ).add( p_z0.y );
  89. const y = p_z1.x.sub( p_z0.x ).sub( p_x1.z ).add( p_x0.z );
  90. const z = p_x1.y.sub( p_x0.y ).sub( p_y1.x ).add( p_y0.x );
  91. const divisor = div( 1.0, mul( 2.0, e ) );
  92. return vec3( x, y, z ).mul( divisor );
  93. }, { p: 'vec3', return: 'vec3' } );
粤ICP备19079148号