UNPKG

three

Version:

JavaScript 3D library

108 lines (93 loc) 3.94 kB
import { mod, Fn, vec2, div, vec4, dot, floor, step, sub, min, max, mul, abs, vec3, inverseSqrt, add, float } from 'three/tsl'; /** * Permutation polynomial for noise generation. * * @tsl * @function * @param {Node<vec4>} x - Input vector. * @return {Node<vec4>} Permuted vector. */ export const permute = /*@__PURE__*/ Fn( ( [ x ] ) => { return mod( x.mul( x ).mul( 34. ).add( x ), 289. ); }, { x: 'vec4', return: 'vec4' } ); /** * 3D Simplex noise implementation in TSL. * * @tsl * @function * @param {Node<vec3>} v - Input coordinate vector. * @return {Node<float>} Simplex noise value. */ export const snoise = /*@__PURE__*/ Fn( ( [ v ] ) => { const C = div( 1., vec2( 6, 3 ) ); const D = vec4( 0, .5, 1, 2 ); const i = floor( v.add( dot( v, C.yyy ) ) ); const x0 = v.sub( i ).add( dot( i, C.xxx ) ); const g = step( x0.yzx, x0.xyz ); const l = sub( 1., g ); const i1 = min( g.xyz, l.zxy ); const i2 = max( g.xyz, l.zxy ); const x1 = x0.sub( i1 ).add( C.x ); const x2 = x0.sub( i2 ).add( C.y ); const x3 = x0.sub( D.yyy ); i.assign( mod( i, 289. ) ); 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. ) ) ); const ns = mul( .142857142857, D.wyz ).sub( D.xzx ); const j = p.sub( mul( 49., floor( p.mul( ns.z ).mul( ns.z ) ) ) ); const x_ = floor( j.mul( ns.z ) ); const x = x_.mul( ns.x ).add( ns.yyyy ); const y = floor( j.sub( mul( 7., x_ ) ) ).mul( ns.x ).add( ns.yyyy ); const h = sub( 1., abs( x ) ).sub( abs( y ) ); const b0 = vec4( x.xy, y.xy ); const b1 = vec4( x.zw, y.zw ); const sh = step( h, vec4( 0 ) ).negate(); const a0 = b0.xzyw.add( floor( b0 ).mul( 2. ).add( 1. ).xzyw.mul( sh.xxyy ) ); const a1 = b1.xzyw.add( floor( b1 ).mul( 2. ).add( 1. ).xzyw.mul( sh.zzww ) ); const p0 = vec3( a0.xy, h.x ); const p1 = vec3( a0.zw, h.y ); const p2 = vec3( a1.xy, h.z ); const p3 = vec3( a1.zw, h.w ); const norm = inverseSqrt( vec4( dot( p0, p0 ), dot( p1, p1 ), dot( p2, p2 ), dot( p3, p3 ) ) ); p0.mulAssign( norm.x ); p1.mulAssign( norm.y ); p2.mulAssign( norm.z ); p3.mulAssign( norm.w ); const m = max( sub( .6, vec4( dot( x0, x0 ), dot( x1, x1 ), dot( x2, x2 ), dot( x3, x3 ) ) ), 0. ); return add( .5, mul( 12., dot( m.mul( m ).mul( m ), vec4( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ), dot( p3, x3 ) ) ) ) ); }, { v: 'vec3', return: 'float' } ); /** * 3D Simplex noise vector. Returns a vec3 containing three independent noise samples. * * @tsl * @function * @param {Node<vec3>} x - Input coordinate vector. * @return {Node<vec3>} Vector of three noise values. */ export const snoiseVec3 = /*@__PURE__*/ Fn( ( [ x ] ) => { 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. ) ) ); }, { x: 'vec3', return: 'vec3' } ); /** * 3D Curl noise in TSL. Generates a divergence-free vector field from simplex noise. * * @tsl * @function * @param {Node<vec3>} p - Input coordinate vector. * @return {Node<vec3>} Curl noise vector. */ export const curlNoise = /*@__PURE__*/ Fn( ( [ p ] ) => { const e = float( .1 ); const dx = vec3( e, 0.0, 0.0 ); const dy = vec3( 0.0, e, 0.0 ); const dz = vec3( 0.0, 0.0, e ); const p_x0 = snoiseVec3( p.sub( dx ) ); const p_x1 = snoiseVec3( p.add( dx ) ); const p_y0 = snoiseVec3( p.sub( dy ) ); const p_y1 = snoiseVec3( p.add( dy ) ); const p_z0 = snoiseVec3( p.sub( dz ) ); const p_z1 = snoiseVec3( p.add( dz ) ); const x = p_y1.z.sub( p_y0.z ).sub( p_z1.y ).add( p_z0.y ); const y = p_z1.x.sub( p_z0.x ).sub( p_x1.z ).add( p_x0.z ); const z = p_x1.y.sub( p_x0.y ).sub( p_y1.x ).add( p_y0.x ); const divisor = div( 1.0, mul( 2.0, e ) ); return vec3( x, y, z ).mul( divisor ); }, { p: 'vec3', return: 'vec3' } );