@dailies-studio/tsl-textures 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -0
  3. package/dist/cjs/tsl-textures.cjs +4749 -0
  4. package/dist/cjs/tsl-textures.min.cjs +2 -0
  5. package/dist/tsl-textures.js +4659 -0
  6. package/dist/tsl-textures.min.js +2 -0
  7. package/package.json +36 -0
  8. package/src/brain.js +116 -0
  9. package/src/bricks.js +116 -0
  10. package/src/camouflage.js +85 -0
  11. package/src/caustics.js +75 -0
  12. package/src/cave-art.js +83 -0
  13. package/src/circle-decor.js +76 -0
  14. package/src/circles.js +83 -0
  15. package/src/clouds.js +114 -0
  16. package/src/concrete.js +95 -0
  17. package/src/cork.js +104 -0
  18. package/src/crumpled-fabric.js +81 -0
  19. package/src/dalmatian-spots.js +80 -0
  20. package/src/darth-maul.js +84 -0
  21. package/src/dyson-sphere.js +144 -0
  22. package/src/entangled.js +75 -0
  23. package/src/fordite.js +69 -0
  24. package/src/gas-giant.js +94 -0
  25. package/src/grid.js +84 -0
  26. package/src/halftone.js +252 -0
  27. package/src/isolayers.js +79 -0
  28. package/src/isolines.js +72 -0
  29. package/src/karst-rock.js +67 -0
  30. package/src/marble.js +96 -0
  31. package/src/melter.js +76 -0
  32. package/src/neon-lights.js +107 -0
  33. package/src/perlin-noise.js +66 -0
  34. package/src/photosphere.js +73 -0
  35. package/src/planet.js +168 -0
  36. package/src/polka-dots.js +106 -0
  37. package/src/processed-wood.js +80 -0
  38. package/src/protozoa.js +110 -0
  39. package/src/reticular-veins.js +72 -0
  40. package/src/roman-paving.js +58 -0
  41. package/src/rotator.js +120 -0
  42. package/src/rough-clay.js +90 -0
  43. package/src/runny-eggs.js +180 -0
  44. package/src/rust.js +144 -0
  45. package/src/satin.js +69 -0
  46. package/src/scaler.js +111 -0
  47. package/src/scepter-head.js +94 -0
  48. package/src/scream.js +72 -0
  49. package/src/stars.js +72 -0
  50. package/src/static-noise.js +73 -0
  51. package/src/supersphere.js +108 -0
  52. package/src/tiger-fur.js +77 -0
  53. package/src/translator.js +116 -0
  54. package/src/tsl-textures.js +63 -0
  55. package/src/tsl-utils.js +344 -0
  56. package/src/turbulent-smoke.js +73 -0
  57. package/src/voronoi-cells.js +99 -0
  58. package/src/water-drops.js +96 -0
  59. package/src/watermelon.js +87 -0
  60. package/src/waves.js +150 -0
  61. package/src/wood.js +99 -0
  62. package/src/zebra-lines.js +77 -0
@@ -0,0 +1,116 @@
1
+ 
2
+ // TSL-Textures: Translator
3
+
4
+
5
+
6
+ import { Vector2, Vector3 } from "three";
7
+ import { cross, Fn, normalLocal, positionGeometry, tangentLocal } from 'three/tsl';
8
+ import { approximateNormal, selectPlanar } from './tsl-utils.js';
9
+
10
+
11
+
12
+ var defaults = {
13
+ $name: 'Translator',
14
+ $positionNode: true,
15
+ $selectorPlanar: true,
16
+
17
+ distance: new Vector3( -0.5, 0, 0.2 ),
18
+
19
+ selectorCenter: new Vector3( 0, 0, 0 ),
20
+ selectorAngles: new Vector2( 0, 0 ),
21
+ selectorWidth: 0.7,
22
+
23
+ };
24
+
25
+
26
+
27
+ var surfacePos = Fn( ([ pos, distance, selectorAngles, selectorCenter, selectorWidth ])=>{
28
+
29
+ var zone = selectPlanar( pos, selectorAngles, selectorCenter, selectorWidth );
30
+
31
+ return pos.add( distance.mul( zone ) );
32
+
33
+ } ).setLayout( {
34
+ name: 'surfacePos',
35
+ type: 'vec3',
36
+ inputs: [
37
+ { name: 'pos', type: 'vec3' },
38
+ { name: 'distance', type: 'vec3' },
39
+ { name: 'selectorAngles', type: 'vec2' },
40
+ { name: 'selectorCenter', type: 'vec3' },
41
+ { name: 'selectorWidth', type: 'float' },
42
+ ]
43
+ } );
44
+
45
+
46
+
47
+ var translatorRaw = Fn( ([ distance, selectorAngles, selectorCenter, selectorWidth ])=>{
48
+
49
+ return surfacePos( positionGeometry, distance, selectorAngles, selectorCenter, selectorWidth );
50
+
51
+ } ).setLayout( {
52
+ name: 'translatorRaw',
53
+ type: 'vec3',
54
+ inputs: [
55
+ { name: 'distance', type: 'vec3' },
56
+ { name: 'selectorAngles', type: 'vec2' },
57
+ { name: 'selectorCenter', type: 'vec3' },
58
+ { name: 'selectorWidth', type: 'float' },
59
+ ]
60
+ } );
61
+
62
+
63
+
64
+ var translatorNormalRaw = Fn( ([ distance, selectorAngles, selectorCenter, selectorWidth ])=>{
65
+
66
+ var EPS = 0.01;
67
+
68
+ var position = positionGeometry,
69
+ normal = normalLocal.normalize().toVar(),
70
+ tangent = tangentLocal.normalize().mul( EPS ).toVar(),
71
+ bitangent = cross( normal, tangent ).normalize().mul( EPS ).toVar();
72
+
73
+ var pos = surfacePos( position, distance, selectorAngles, selectorCenter, selectorWidth );
74
+ var posU = surfacePos( position.add( tangent ), distance, selectorAngles, selectorCenter, selectorWidth );
75
+ var posV = surfacePos( position.add( bitangent ), distance, selectorAngles, selectorCenter, selectorWidth );
76
+
77
+ return approximateNormal( pos, posU, posV );
78
+
79
+ } ).setLayout( {
80
+ name: 'translatorNormalRaw',
81
+ type: 'vec3',
82
+ inputs: [
83
+ { name: 'distance', type: 'vec3' },
84
+ { name: 'selectorAngles', type: 'vec2' },
85
+ { name: 'selectorCenter', type: 'vec3' },
86
+ { name: 'selectorWidth', type: 'float' },
87
+ ]
88
+ } );
89
+
90
+
91
+
92
+ function translator( params={} ) {
93
+
94
+ var { distance, selectorAngles, selectorCenter, selectorWidth } = { ...defaults, ...params };
95
+
96
+ return translatorRaw( distance, selectorAngles, selectorCenter, selectorWidth );
97
+
98
+ }
99
+
100
+
101
+
102
+ translator.normal = function ( params={} ) {
103
+
104
+ var { distance, selectorAngles, selectorCenter, selectorWidth } = { ...defaults, ...params };
105
+
106
+ return translatorNormalRaw( distance, selectorAngles, selectorCenter, selectorWidth );
107
+
108
+ };
109
+
110
+
111
+
112
+ translator.defaults = defaults;
113
+
114
+
115
+
116
+ export { translator };
@@ -0,0 +1,63 @@
1
+ if ( typeof window !== 'undefined' ) {
2
+
3
+ window.__TSL_TEXTURES__ = 3.0;
4
+
5
+ }
6
+
7
+ export * from './tsl-utils.js';
8
+
9
+
10
+ export { brain } from './brain.js';
11
+ export { camouflage } from './camouflage.js';
12
+ export { caveArt } from './cave-art.js';
13
+ export { circles } from './circles.js';
14
+ export { clouds } from './clouds.js';
15
+ export { concrete } from './concrete.js';
16
+ export { cork } from './cork.js';
17
+ export { dalmatianSpots } from './dalmatian-spots.js';
18
+ export { darthMaul } from './darth-maul.js';
19
+ export { dysonSphere } from './dyson-sphere.js';
20
+ export { entangled } from './entangled.js';
21
+ export { fordite } from './fordite.js';
22
+ export { gasGiant } from './gas-giant.js';
23
+ export { grid } from './grid.js';
24
+ export { isolines } from './isolines.js';
25
+ export { karstRock } from './karst-rock.js';
26
+ export { marble } from './marble.js';
27
+ //export { melter } from './melter.js';
28
+ export { neonLights } from './neon-lights.js';
29
+ export { perlinNoise } from './perlin-noise.js';
30
+ export { photosphere } from './photosphere.js';
31
+ export { planet } from './planet.js';
32
+ export { polkaDots } from './polka-dots.js';
33
+ export { processedWood } from './processed-wood.js';
34
+ export { protozoa } from './protozoa.js';
35
+ export { rotator } from './rotator.js';
36
+ export { roughClay } from './rough-clay.js';
37
+ export { runnyEggs } from './runny-eggs.js';
38
+ export { rust } from './rust.js';
39
+ export { satin } from './satin.js';
40
+ export { scaler } from './scaler.js';
41
+ export { scepterHead } from './scepter-head.js';
42
+ export { scream } from './scream.js';
43
+ export { stars } from './stars.js';
44
+ export { staticNoise } from './static-noise.js';
45
+ export { supersphere } from './supersphere.js';
46
+ export { tigerFur } from './tiger-fur.js';
47
+ export { translator } from './translator.js';
48
+ export { voronoiCells } from './voronoi-cells.js';
49
+ export { waterDrops } from './water-drops.js';
50
+ export { watermelon } from './watermelon.js';
51
+ export { waves } from './waves.js';
52
+ export { wood } from './wood.js';
53
+ export { zebraLines } from './zebra-lines.js';
54
+ export { circleDecor } from './circle-decor.js';
55
+ export { reticularVeins } from './reticular-veins.js';
56
+ export { romanPaving } from './roman-paving.js';
57
+ export { crumpledFabric } from './crumpled-fabric.js';
58
+ export { isolayers } from './isolayers.js';
59
+ export { turbulentSmoke } from './turbulent-smoke.js';
60
+ export { caustics } from './caustics.js';
61
+ export { bricks } from './bricks.js';
62
+ export { halftone } from './halftone.js';
63
+ //export { aaa } from './aaa.js';
@@ -0,0 +1,344 @@
1
+ 
2
+ // TSL Utility Functions
3
+
4
+ // noise(pos,mul,add) - perlin noise (x*mul+add), x->[-1,1]
5
+ // fractal(pos,octaves,...) - fractal noise
6
+ // voronoi(pos,jitter,...) - voronoi cells (worley noise)
7
+ // voronoi2(pos,jitter,...) - voronoi cells but returns vec2
8
+ // voronoi3(pos,jitter,...) - voronoi cells but returns vec3
9
+ // vnoise(pos) - simple noise -> [-1,1]
10
+ // approximateNormal(pos,posU,posV) - approximate normal vector
11
+ // toHsl(vec3) - convert rgb to hsl
12
+ // hsl(vec3) - convert hsl to rgb
13
+ // remapExp(x,fromMin,fromMax,toMin,toMax) - exponential version of remap
14
+ // showFallbackWarning( )
15
+ // hideFallbackWarning( )
16
+ // spherical( phi, theta ):vec3 - from angles to point on unit sphere
17
+ // rotatePivot( vector, pivot, angle ) - rotate around pivot point
18
+
19
+
20
+
21
+ import { add, cos, cross, float, Fn, If, log2, max, min, mul, pow, remap, rotate, select, sin, smoothstep, sub, transformNormalToView, vec3 } from 'three/tsl';
22
+
23
+
24
+
25
+ // simple vector noise, vec3->float[-1,1]
26
+ const vnoise = Fn( ([ v ])=>{
27
+
28
+ return v.dot( vec3( 12.9898, 78.233, -97.5123 ) ).sin().mul( 43758.5453 ).fract().mul( 2 ).sub( 1 );
29
+
30
+ } ).setLayout( {
31
+ name: 'vnoise',
32
+ type: 'float',
33
+ inputs: [
34
+ { name: 'v', type: 'vec3' },
35
+ ]
36
+ } );
37
+
38
+
39
+
40
+ // approximate normal vector given point and two neighbout points
41
+ const approximateNormal = Fn( ([ pos, posU, posV ])=>{
42
+
43
+ var dU = sub( posU, pos ),
44
+ dV = sub( posV, pos );
45
+
46
+ return transformNormalToView( cross( dU, dV ).normalize() );
47
+
48
+ } ).setLayout( {
49
+ name: 'approximateNormal',
50
+ type: 'vec3',
51
+ inputs: [
52
+ { name: 'pos', type: 'vec3' },
53
+ { name: 'posU', type: 'vec3' },
54
+ { name: 'posV', type: 'vec3' },
55
+ ]
56
+ } );
57
+
58
+
59
+
60
+
61
+ // exponential version of remap
62
+ const remapExp = Fn( ([ x, fromMin, fromMax, toMin, toMax ]) => {
63
+
64
+ x = remap( x, fromMin, fromMax, 0, 1 );
65
+ x = pow( 2, mul( x, log2( toMax.div( toMin ) ) ).add( log2( toMin ) ) );
66
+ return x;
67
+
68
+ } ).setLayout( {
69
+ name: 'remapExp',
70
+ type: 'float',
71
+ inputs: [
72
+ { name: 'x', type: 'float' },
73
+ { name: 'fromMin', type: 'float' },
74
+ { name: 'fromMax', type: 'float' },
75
+ { name: 'toMin', type: 'float' },
76
+ { name: 'toMax', type: 'float' },
77
+ ]
78
+ } );
79
+
80
+
81
+
82
+ // show notification that
83
+ var banner = null;
84
+ var bannerCounter = 10;
85
+ async function showFallbackWarning( ) {
86
+
87
+ if ( navigator.gpu != undefined ) {
88
+
89
+ var adapter = await navigator.gpu.requestAdapter();
90
+ if ( adapter ) return;
91
+
92
+ }
93
+
94
+ var html = `
95
+ <div style="font-size:1.25em; font-weight:bold;">PLEASE, WAIT</div>
96
+ <div style="font-size:0.85em; font-weight:100;" >NO WEBGPU &mdash; TRYING WEBGL2</div>
97
+ <div id="counter"></div>
98
+ `;
99
+
100
+ banner = document.createElement( 'div' );
101
+ banner.innerHTML = html;
102
+
103
+ banner.style.left = 'calc(50% - 8em)';
104
+ banner.style.width = '16em';
105
+
106
+ banner.style.fontFamily = 'Bahnschrifts, Arial';
107
+ banner.style.position = 'absolute';
108
+ banner.style.bottom = '20px';
109
+ banner.style.padding = '12px 6px';
110
+ banner.style.border = '1px solid white';
111
+ banner.style.borderRadius = '4px';
112
+ banner.style.background = 'rgba(0,0,0,0.5)';
113
+ banner.style.color = 'white';
114
+ banner.style.textAlign = 'center';
115
+ banner.style.opacity = '0.8';
116
+ banner.style.outline = 'none';
117
+ banner.style.zIndex = '999';
118
+
119
+ document.body.appendChild( banner );
120
+
121
+ }
122
+
123
+
124
+
125
+ function hideFallbackWarning( ) {
126
+
127
+ if ( banner ) {
128
+
129
+ if ( bannerCounter>0 )
130
+ bannerCounter--;
131
+ else {
132
+
133
+ banner.style.display = 'none';
134
+ banner = null;
135
+
136
+ }
137
+
138
+ }
139
+
140
+ }
141
+
142
+
143
+
144
+ // helper function - convert hsl to rgb, ported to TSL from:
145
+ // https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative
146
+
147
+ const hslHelper = Fn( ([ h, s, l, n ])=>{
148
+
149
+ var k = n.add( h.mul( 12 ) ).mod( 12 );
150
+ var a = s.mul( min( l, sub( 1, l ) ) );
151
+ return l.sub( a.mul( max( -1, min( min( k.sub( 3 ), sub( 9, k ) ), 1 ) ) ) );
152
+
153
+ } ).setLayout( {
154
+ name: 'hslHelper',
155
+ type: 'float',
156
+ inputs: [
157
+ { name: 'h', type: 'float' },
158
+ { name: 's', type: 'float' },
159
+ { name: 'l', type: 'float' },
160
+ { name: 'n', type: 'float' },
161
+ ]
162
+ } );
163
+
164
+
165
+
166
+ // convert from hsl to rgb
167
+ const hsl = Fn( ([ col ]) => {
168
+
169
+ var h = col.x.fract().add( 1 ).fract();
170
+ var s = col.y.clamp( 0, 1 );
171
+ var l = col.z.clamp( 0, 1 );
172
+
173
+ var r = hslHelper( h, s, l, 0 );
174
+ var g = hslHelper( h, s, l, 8 );
175
+ var b = hslHelper( h, s, l, 4 );
176
+
177
+ return vec3( r, g, b );
178
+
179
+ } ).setLayout( {
180
+ name: 'hsl',
181
+ type: 'vec3',
182
+ inputs: [
183
+ { name: 'col', type: 'vec3' },
184
+ ]
185
+ } );
186
+
187
+
188
+
189
+ // convert from rgb to hsl
190
+ const toHsl = Fn( ([ rgb ]) => {
191
+
192
+ var R = float( rgb.x ).toVar(),
193
+ G = float( rgb.y ).toVar(),
194
+ B = float( rgb.z ).toVar();
195
+
196
+ var mx = max( R, max( G, B ) ).toVar();
197
+ var mn = min( R, min( G, B ) ).toVar();
198
+
199
+ var H = float( 0 ).toVar(),
200
+ S = float( 0 ).toVar(),
201
+ L = add( mx, mn ).div( 2 );
202
+
203
+ If( mn.notEqual( mx ), ()=>{
204
+
205
+ const delta = sub( mx, mn ).toVar();
206
+
207
+ S.assign( select( L.lessThanEqual( 0.5 ), delta.div( add( mn, mx ) ), delta.div( sub( 2, add( mn, mx ) ) ) ) );
208
+ If( mx.equal( R ), ()=>{
209
+
210
+ H.assign( sub( G, B ).div( delta ).add( select( G.lessThanEqual( B ), 6, 0 ) ) );
211
+
212
+ } )
213
+ .ElseIf( mx.equal( G ), ()=>{
214
+
215
+ H.assign( sub( B, R ).div( delta ).add( 2 ) );
216
+
217
+ } )
218
+ .Else( ()=>{
219
+
220
+ H.assign( sub( R, G ).div( delta ).add( 4 ) );
221
+
222
+ } );
223
+ H.divAssign( 6 );
224
+
225
+ } );
226
+ return vec3( H, S, L );
227
+
228
+ } );
229
+
230
+ toHsl.setLayout( {
231
+ name: 'toHsl',
232
+ type: 'vec3',
233
+ inputs: [
234
+ { name: 'rgb', type: 'vec3' },
235
+ ]
236
+ } );
237
+
238
+
239
+
240
+ const spherical = Fn( ([ phi, theta ]) => {
241
+
242
+ return vec3(
243
+ sin( theta ).mul( sin( phi ) ),
244
+ cos( phi ),
245
+ cos( theta ).mul( sin( phi ) )
246
+ );
247
+
248
+ } ).setLayout( {
249
+ name: 'spherical',
250
+ type: 'vec3',
251
+ inputs: [
252
+ { name: 'phi', type: 'float' },
253
+ { name: 'theta', type: 'float' },
254
+ ]
255
+ } );
256
+
257
+
258
+
259
+ const rotatePivot = Fn( ([ vector, pivot, angle ])=>{
260
+
261
+ return rotate( vector.sub( pivot ), angle ).add( pivot );
262
+
263
+ } ).setLayout( {
264
+ name: 'rotatePivot',
265
+ type: 'vec3',
266
+ inputs: [
267
+ { name: 'vector', type: 'vec3' },
268
+ { name: 'pivot', type: 'vec3' },
269
+ { name: 'angle', type: 'vec3' },
270
+ ]
271
+ } );
272
+
273
+
274
+
275
+ const selectPlanar = Fn( ([ pos, selAngles, selCenter, selWidth ])=>{
276
+
277
+ // select zone in a plane through point selCenter,
278
+ // rotated according to selAngles and selWidth thick
279
+ // result is [0,1] inside plane, 0 below plane, 1 above plane
280
+
281
+ // C is projected on segment AB
282
+ // result is [0,1] inside AB, 0 before A, 1 after B
283
+
284
+ /* non-optimized version
285
+ var s = spherical(selAngles.x,selAngles.y).mul(selWidth).toVar(),
286
+ c = pos,
287
+ a = selCenter.sub(s.div(2)),
288
+ b = selCenter.add(s.div(2));
289
+
290
+ var ca = a.sub(c),
291
+ ab = b.sub(a).toVar();
292
+
293
+ var caab = ca.dot(s),
294
+ abab = ab.dot(ab);
295
+
296
+ var k = caab.div(abab).negate();
297
+ */
298
+
299
+ var s = spherical( selAngles.x, selAngles.y ).mul( selWidth ).toVar();
300
+
301
+ var k = selCenter.sub( s.div( 2 ) ).sub( pos ).dot( s ).div( s.dot( s ) ).negate();
302
+
303
+ return smoothstep( 0, 1, k );
304
+
305
+ } ).setLayout( {
306
+ name: 'selectPlanar',
307
+ type: 'float',
308
+ inputs: [
309
+ { name: 'pos', type: 'vec3' },
310
+ { name: 'selAngles', type: 'vec2' },
311
+ { name: 'selCenter', type: 'vec3' },
312
+ { name: 'selWidth', type: 'float' },
313
+ ]
314
+ } );
315
+
316
+
317
+
318
+ export
319
+ {
320
+ approximateNormal,
321
+ showFallbackWarning,
322
+ hideFallbackWarning,
323
+ remapExp,
324
+ hsl,
325
+ toHsl,
326
+ rotatePivot,
327
+ vnoise,
328
+ spherical,
329
+ selectPlanar,
330
+ };
331
+
332
+
333
+
334
+ export
335
+ {
336
+ mx_noise_float as noise,
337
+ mx_noise_vec3 as noise3,
338
+ mx_fractal_noise_float as fractal,
339
+ mx_fractal_noise_vec3 as fractal3,
340
+ mx_worley_noise_float as voronoi,
341
+ mx_worley_noise_vec2 as voronoi2,
342
+ mx_worley_noise_vec3 as voronoi3,
343
+
344
+ } from 'three/tsl';
@@ -0,0 +1,73 @@
1
+ 
2
+ // TSL-Textures: Turbulent smoke
3
+
4
+
5
+
6
+ import { exp, Fn, positionGeometry, time, vec3 } from 'three/tsl';
7
+ import { fractal, fractal3, voronoi } from './tsl-utils.js';
8
+
9
+
10
+
11
+ var defaults = {
12
+ $name: 'Turbulent smoke',
13
+ $width: 260,
14
+
15
+ position: positionGeometry,
16
+ scale: 2,
17
+ speed: 0,
18
+ details: 5,
19
+ time: time,
20
+
21
+ seed: 0,
22
+ };
23
+
24
+
25
+
26
+ var turbulentSmokeRaw = Fn( ([ position, scale, speed, details, time, seed ])=>{
27
+
28
+ var pos = position.mul( exp( scale.sub( 1 ) ) ).add( seed ).toVar( );
29
+
30
+ var t = time.mul( speed.sub( 1 ).exp() );
31
+
32
+ var q = pos.add( vec3(
33
+ fractal( pos.add( vec3( 1, t.sin(), -1 ) ) ),
34
+ fractal( pos.add( vec3( t.add( 2*Math.PI/3 ).sin(), 1, -1 ) ) ),
35
+ fractal( pos.add( vec3( 1, -1, t.add( 4*Math.PI/3 ).sin() ) ) ),
36
+ ) );
37
+
38
+ var p = fractal3( q, details );
39
+
40
+ var k = voronoi( pos.add( p.div( 2 ) ) ).pow( 4 ).mul( 4 ).oneMinus();
41
+
42
+ return k;
43
+
44
+ } ).setLayout( {
45
+ name: 'turbulentSmokeRaw',
46
+ type: 'vec3',
47
+ inputs: [
48
+ { name: 'position', type: 'vec3' },
49
+ { name: 'scale', type: 'float' },
50
+ { name: 'speed', type: 'float' },
51
+ { name: 'details', type: 'int' },
52
+ { name: 'time', type: 'float' },
53
+ { name: 'seed', type: 'float' },
54
+ ] }
55
+ );
56
+
57
+
58
+
59
+ function turbulentSmoke( params={} ) {
60
+
61
+ var { position, scale, speed, details, time, seed } = { ...defaults, ...params };
62
+
63
+ return turbulentSmokeRaw( position, scale, speed, details, time, seed );
64
+
65
+ }
66
+
67
+
68
+
69
+ turbulentSmoke.defaults = defaults;
70
+
71
+
72
+
73
+ export { turbulentSmoke };
@@ -0,0 +1,99 @@
1
+ 
2
+ // TSL-Textures: Voronoi Cells
3
+
4
+
5
+
6
+ import { Color } from 'three';
7
+ import { exp, float, Fn, If, int, Loop, mix, positionGeometry, vec3 } from 'three/tsl';
8
+ import { noise, vnoise } from './tsl-utils.js';
9
+
10
+
11
+
12
+ var defaults = {
13
+ $name: 'Voronoi cells',
14
+
15
+ position: positionGeometry,
16
+ scale: 2,
17
+ variation: 0,
18
+ facet: 0,
19
+
20
+ color: new Color( 0 ),
21
+ background: new Color( 0xc0d0ff ),
22
+
23
+ seed: 0,
24
+ };
25
+
26
+
27
+
28
+ var voronoiCellsRaw = Fn( ([ position, scale, variation, facet, color, background, seed ])=>{
29
+
30
+ var pos = position.mul( exp( scale.div( 2 ).add( 0.5 ) ) ).add( seed ).toVar( );
31
+
32
+ var midCell = pos.round().toVar();
33
+
34
+ var minCell = midCell.toVar();
35
+ var minDist = float( 1 ).toVar();
36
+
37
+ var cell = vec3().toVar();
38
+ var dist = float().toVar();
39
+
40
+ var i=int( 0 ).toVar( 'i' ),
41
+ j=int( 0 ).toVar( 'j' ),
42
+ k=int( 0 ).toVar( 'k' );
43
+
44
+ // Loop uses hard-coded i, j, k as indices
45
+ Loop( 3, 3, 3, () => {
46
+
47
+ cell.assign( midCell.add( vec3( i, j, k ).sub( 1 ) ) );
48
+ //var cellCenter = cell.add( noise( cell.mul( Math.PI ) ) ); // too slow on WebGL2
49
+ var cellCenter = cell.add( vnoise( cell.mul( Math.PI*2 ) ).div( 2 ) );
50
+ dist.assign( pos.distance( cellCenter ) );
51
+
52
+ If( dist.lessThan( minDist ), ()=>{
53
+
54
+ minDist.assign( dist );
55
+ minCell.assign( cell );
56
+
57
+ } );
58
+
59
+ } );
60
+
61
+ var n = noise( minCell.mul( Math.PI ) ).toVar();
62
+ var m = mix( minDist, n.add( 1 ).div( 2 ), facet );
63
+
64
+ var color = mix( color, background, m ).toVar();
65
+ var randomColor = vec3( n.mul( 16.8 ), n.mul( 31.4159 ), n.mul( 27.1828 ) ).sin().add( 1 ).div( 2 );
66
+
67
+ return mix( color, mix( color, randomColor, variation ), variation );
68
+
69
+ } ).setLayout( {
70
+ name: 'voronoiCellsRaw',
71
+ type: 'vec3',
72
+ inputs: [
73
+ { name: 'position', type: 'vec3' },
74
+ { name: 'scale', type: 'float' },
75
+ { name: 'variation', type: 'float' },
76
+ { name: 'facet', type: 'float' },
77
+ { name: 'color', type: 'vec3' },
78
+ { name: 'background', type: 'vec3' },
79
+ { name: 'seed', type: 'float' },
80
+ ] }
81
+ );
82
+
83
+
84
+
85
+ function voronoiCells( params={} ) {
86
+
87
+ var { position, scale, variation, facet, color, background, seed } = { ...defaults, ...params };
88
+
89
+ return voronoiCellsRaw( position, scale, variation, facet, color, background, seed );
90
+
91
+ }
92
+
93
+
94
+
95
+ voronoiCells.defaults = defaults;
96
+
97
+
98
+
99
+ export { voronoiCells };