tsl-textures 2.5.1 → 3.0.1

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 (59) hide show
  1. package/dist/cjs/tsl-textures.js +2449 -1426
  2. package/dist/cjs/tsl-textures.min.js +2 -2
  3. package/dist/tsl-textures.js +2435 -1421
  4. package/dist/tsl-textures.min.js +2 -2
  5. package/package.json +1 -1
  6. package/src/brain.js +72 -21
  7. package/src/bricks.js +56 -23
  8. package/src/camouflage.js +39 -20
  9. package/src/caustics.js +39 -14
  10. package/src/cave-art.js +39 -13
  11. package/src/circle-decor.js +39 -13
  12. package/src/circles.js +36 -16
  13. package/src/clouds.js +69 -28
  14. package/src/concrete.js +57 -23
  15. package/src/cork.js +54 -35
  16. package/src/crumpled-fabric.js +39 -14
  17. package/src/dalmatian-spots.js +37 -12
  18. package/src/darth-maul.js +43 -15
  19. package/src/dyson-sphere.js +61 -18
  20. package/src/entangled.js +36 -12
  21. package/src/fordite.js +36 -12
  22. package/src/gas-giant.js +42 -16
  23. package/src/grid.js +45 -17
  24. package/src/isolayers.js +41 -15
  25. package/src/isolines.js +36 -10
  26. package/src/karst-rock.js +31 -8
  27. package/src/marble.js +36 -11
  28. package/src/melter.js +0 -1
  29. package/src/neon-lights.js +51 -23
  30. package/src/perlin-noise.js +66 -0
  31. package/src/photosphere.js +34 -11
  32. package/src/planet.js +66 -30
  33. package/src/polka-dots.js +42 -17
  34. package/src/processed-wood.js +42 -16
  35. package/src/protozoa.js +51 -16
  36. package/src/reticular-veins.js +37 -11
  37. package/src/roman-paving.js +30 -8
  38. package/src/rotator.js +71 -27
  39. package/src/rough-clay.js +50 -22
  40. package/src/runny-eggs.js +120 -44
  41. package/src/rust.js +81 -19
  42. package/src/satin.js +27 -20
  43. package/src/scaler.js +61 -26
  44. package/src/scepter-head.js +46 -20
  45. package/src/scream.js +29 -19
  46. package/src/stars.js +36 -11
  47. package/src/static-noise.js +36 -9
  48. package/src/supersphere.js +63 -26
  49. package/src/tiger-fur.js +41 -14
  50. package/src/translator.js +67 -24
  51. package/src/tsl-textures.js +2 -1
  52. package/src/tsl-utils.js +172 -623
  53. package/src/turbulent-smoke.js +38 -13
  54. package/src/voronoi-cells.js +44 -26
  55. package/src/water-drops.js +55 -22
  56. package/src/watermelon.js +43 -18
  57. package/src/wood.js +48 -15
  58. package/src/zebra-lines.js +38 -12
  59. package/src/simplex-noise.js +0 -41
package/src/tsl-utils.js CHANGED
@@ -1,16 +1,144 @@
1
1
  
2
- // Equirectangular Texture Generator - TSL Utility Functions
3
- //
4
- // hsl( h, s, l ):vec3 - convert from hsl to rgb
5
- // toHsl( rgb:vec3 ):vec3 - convert from rgb to hsl
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( )
6
16
  // spherical( phi, theta ):vec3 - from angles to point on unit sphere
7
- // applyEuler( vec:vec3, eu:vec3 ):vec3 - apply Euler rotation to a vector
17
+ // rotatePivot( vector, pivot, angle ) - rotate around pivot point
8
18
 
9
19
 
10
20
 
11
- import { add, cos, cross, dFdx, dFdy, float, Fn, If, log2, mat4, max, min, mul, mx_noise_float, positionGeometry, pow, remap, select, sin, smoothstep, sub, transformNormalToView, uniform, vec3, vec4 } from 'three/tsl';
12
- import { Color, Vector3 } from 'three';
13
- //import { mx_perlin_noise_float as noise } from 'https://cdn.jsdelivr.net/npm/three@0.167.0/src/nodes/materialx/lib/mx_noise.js';
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
+
14
142
 
15
143
 
16
144
  // helper function - convert hsl to rgb, ported to TSL from:
@@ -22,9 +150,7 @@ const hslHelper = Fn( ([ h, s, l, n ])=>{
22
150
  var a = s.mul( min( l, sub( 1, l ) ) );
23
151
  return l.sub( a.mul( max( -1, min( min( k.sub( 3 ), sub( 9, k ) ), 1 ) ) ) );
24
152
 
25
- } );
26
-
27
- hslHelper.setLayout( {
153
+ } ).setLayout( {
28
154
  name: 'hslHelper',
29
155
  type: 'float',
30
156
  inputs: [
@@ -38,11 +164,11 @@ hslHelper.setLayout( {
38
164
 
39
165
 
40
166
  // convert from hsl to rgb
41
- const hsl = Fn( ([ h, s, l ]) => {
167
+ const hsl = Fn( ([ col ]) => {
42
168
 
43
- h = h.fract().add( 1 ).fract();
44
- s = s.clamp( 0, 1 );
45
- l = l.clamp( 0, 1 );
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 );
46
172
 
47
173
  var r = hslHelper( h, s, l, 0 );
48
174
  var g = hslHelper( h, s, l, 8 );
@@ -50,19 +176,16 @@ const hsl = Fn( ([ h, s, l ]) => {
50
176
 
51
177
  return vec3( r, g, b );
52
178
 
53
- } );
54
-
55
- hsl.setLayout( {
179
+ } ).setLayout( {
56
180
  name: 'hsl',
57
181
  type: 'vec3',
58
182
  inputs: [
59
- { name: 'h', type: 'float' },
60
- { name: 's', type: 'float' },
61
- { name: 'l', type: 'float' },
183
+ { name: 'col', type: 'vec3' },
62
184
  ]
63
185
  } );
64
186
 
65
187
 
188
+
66
189
  // convert from rgb to hsl
67
190
  const toHsl = Fn( ([ rgb ]) => {
68
191
 
@@ -114,32 +237,6 @@ toHsl.setLayout( {
114
237
 
115
238
 
116
239
 
117
-
118
- // make all elements dynamic (i.e. uniform)
119
- function dynamic( params ) {
120
-
121
- var result = {};
122
-
123
- for ( var [ key, value ] of Object.entries( params ) ) {
124
-
125
- if ( key[ 0 ]!='$' ) {
126
-
127
- if ( value instanceof Vector3 )
128
- result[ key ] = uniform( value, 'vec3' );
129
- else
130
- result[ key ] = uniform( value );
131
-
132
- }
133
-
134
- }
135
-
136
- return result;
137
-
138
- }
139
-
140
-
141
-
142
- // convert phi-theta angles to position on unit sphere
143
240
  const spherical = Fn( ([ phi, theta ]) => {
144
241
 
145
242
  return vec3(
@@ -148,9 +245,7 @@ const spherical = Fn( ([ phi, theta ]) => {
148
245
  cos( theta ).mul( sin( phi ) )
149
246
  );
150
247
 
151
- } );
152
-
153
- spherical.setLayout( {
248
+ } ).setLayout( {
154
249
  name: 'spherical',
155
250
  type: 'vec3',
156
251
  inputs: [
@@ -161,246 +256,22 @@ spherical.setLayout( {
161
256
 
162
257
 
163
258
 
164
- // apply Euler rotation to a vector
165
- const applyEuler = Fn( ([ vec, eu ]) => {
166
-
167
- var quat = quaternionFromEuler( eu );
168
- return applyQuaternion( vec, quat );
169
-
170
- } );
171
-
172
- applyEuler.setLayout( {
173
- name: 'applyEuler',
174
- type: 'vec4',
175
- inputs: [
176
- { name: 'vec', type: 'vec3' },
177
- { name: 'eu', type: 'vec3' },
178
- ]
179
- } );
180
-
181
-
182
- // convert Euler XYZ angles to quaternion
183
- const quaternionFromEuler = Fn( ([ eu ]) => {
184
-
185
- var c1 = cos( eu.x.div( 2 ) );
186
- var c2 = cos( eu.y.div( 2 ) );
187
- var c3 = cos( eu.z.div( 2 ) );
188
-
189
- var s1 = sin( eu.x.div( 2 ) );
190
- var s2 = sin( eu.y.div( 2 ) );
191
- var s3 = sin( eu.z.div( 2 ) );
259
+ const rotatePivot = Fn( ([ vector, pivot, angle ])=>{
192
260
 
193
- return vec4(
194
- add( mul( s1, c2, c3 ), mul( c1, s2, s3 ) ),
195
- sub( mul( c1, s2, c3 ), mul( s1, c2, s3 ) ),
196
- add( mul( c1, c2, s3 ), mul( s1, s2, c3 ) ),
197
- sub( mul( c1, c2, c3 ), mul( s1, s2, s3 ) ),
198
- );
261
+ return rotate( vector.sub( pivot ), angle ).add( pivot );
199
262
 
200
- } );
201
-
202
- quaternionFromEuler.setLayout( {
203
- name: 'quaternionFromEuler',
204
- type: 'vec4',
205
- inputs: [
206
- { name: 'eu', type: 'vec3' },
207
- ]
208
- } );
209
-
210
-
211
- // apply quaternion rotation to a vector
212
- const applyQuaternion = Fn( ([ vec, quat ]) => {
213
-
214
- var t = cross( quat.xyz, vec ).mul( 2 ).toVar( );
215
-
216
- return add( vec, t.mul( quat.w ), cross( quat.xyz, t ) );
217
-
218
- } );
219
-
220
- applyQuaternion.setLayout( {
221
- name: 'applyQuaternion',
263
+ } ).setLayout( {
264
+ name: 'rotatePivot',
222
265
  type: 'vec3',
223
- inputs: [
224
- { name: 'vec', type: 'vec3' },
225
- { name: 'quat', type: 'vec4' },
226
- ]
227
- } );
228
-
229
-
230
- // exponential version of remap
231
- const remapExp = Fn( ([ x, fromMin, fromMax, toMin, toMax ]) => {
232
-
233
- x = remap( x, fromMin, fromMax, 0, 1 );
234
- x = pow( 2, mul( x, log2( toMax.div( toMin ) ) ).add( log2( toMin ) ) );
235
- return x;
236
-
237
- } );
238
-
239
- remapExp.setLayout( {
240
- name: 'remapExp',
241
- type: 'float',
242
- inputs: [
243
- { name: 'x', type: 'float' },
244
- { name: 'fromMin', type: 'float' },
245
- { name: 'fromMax', type: 'float' },
246
- { name: 'toMin', type: 'float' },
247
- { name: 'toMax', type: 'float' },
248
- ]
249
- } );
250
-
251
-
252
-
253
- // simple vector noise, vec3->float[-1,1]
254
- const vnoise = Fn( ([ v ])=>{
255
-
256
- return v.dot( vec3( 12.9898, 78.233, -97.5123 ) ).sin().mul( 43758.5453 ).fract().mul( 2 ).sub( 1 );
257
-
258
- } );
259
-
260
- vnoise.setLayout( {
261
- name: 'vnoise',
262
- type: 'float',
263
- inputs: [
264
- { name: 'v', type: 'vec3' },
265
- ]
266
- } );
267
-
268
-
269
-
270
- // generate X-rotation matrix
271
- const matRotX = Fn( ([ angle ])=>{
272
-
273
- var cos = angle.cos().toVar(),
274
- sin = angle.sin().toVar();
275
-
276
- return mat4(
277
- 1, 0, 0, 0,
278
- 0, cos, sin, 0,
279
- 0, sin.negate(), cos, 0,
280
- 0, 0, 0, 1 );
281
-
282
- } );
283
-
284
- matRotX.setLayout( {
285
- name: 'matRotX',
286
- type: 'mat4',
287
- inputs: [
288
- { name: 'angle', type: 'float' },
289
- ]
290
- } );
291
-
292
-
293
-
294
- // generate Y-rotation matrix
295
- const matRotY = Fn( ([ angle ])=>{
296
-
297
- var cos = angle.cos().toVar(),
298
- sin = angle.sin().toVar();
299
-
300
- return mat4(
301
- cos, 0, sin.negate(), 0,
302
- 0, 1, 0, 0,
303
- sin, 0, cos, 0,
304
- 0, 0, 0, 1 );
305
-
306
- } );
307
-
308
- matRotY.setLayout( {
309
- name: 'matRotY',
310
- type: 'mat4',
311
- inputs: [
312
- { name: 'angle', type: 'float' },
313
- ]
314
- } );
315
-
316
-
317
-
318
- // generate Z-rotation matrix
319
- const matRotZ = Fn( ([ angle ])=>{
320
-
321
- var cos = angle.cos().toVar(),
322
- sin = angle.sin().toVar();
323
-
324
- return mat4(
325
- cos, sin, 0, 0,
326
- sin.negate(), cos, 0, 0,
327
- 0, 0, 1, 0,
328
- 0, 0, 0, 1 );
329
-
330
- } );
331
-
332
- matRotZ.setLayout( {
333
- name: 'matRotZ',
334
- type: 'mat4',
335
- inputs: [
336
- { name: 'angle', type: 'float' },
337
- ]
338
- } );
339
-
340
-
341
-
342
- // generate YXZ rotation matrix
343
- const matRotYXZ = Fn( ([ angles ])=>{
344
-
345
- var RX = matRotX( angles.x ),
346
- RY = matRotY( angles.y ),
347
- RZ = matRotZ( angles.z );
348
-
349
- return RY.mul( RX ).mul( RZ );
350
-
351
- } );
352
-
353
- matRotYXZ.setLayout( {
354
- name: 'matRotYXZ',
355
- type: 'mat4',
356
- inputs: [
357
- { name: 'angles', type: 'vec3' },
358
- ]
359
- } );
360
-
361
-
362
-
363
- // generate scaling matrix
364
- const matScale = Fn( ([ scales ])=>{
365
-
366
- return mat4(
367
- scales.x, 0, 0, 0,
368
- 0, scales.y, 0, 0,
369
- 0, 0, scales.z, 0,
370
- 0, 0, 0, 1 );
371
-
372
- } );
373
-
374
- matScale.setLayout( {
375
- name: 'matScale',
376
- type: 'mat4',
377
- inputs: [
378
- { name: 'scales', type: 'vec3' },
379
- ]
380
- } );
381
-
382
-
383
-
384
- // generate translation matrix
385
- const matTrans = Fn( ([ vector ])=>{
386
-
387
- return mat4(
388
- 1, 0, 0, 0,
389
- 0, 1, 0, 0,
390
- 0, 0, 1, 0,
391
- vector.x, vector.y, vector.z, 1 );
392
-
393
- } );
394
-
395
- matTrans.setLayout( {
396
- name: 'matTrans',
397
- type: 'mat4',
398
266
  inputs: [
399
267
  { name: 'vector', type: 'vec3' },
268
+ { name: 'pivot', type: 'vec3' },
269
+ { name: 'angle', type: 'vec3' },
400
270
  ]
401
271
  } );
402
272
 
403
273
 
274
+
404
275
  const selectPlanar = Fn( ([ pos, selAngles, selCenter, selWidth ])=>{
405
276
 
406
277
  // select zone in a plane through point selCenter,
@@ -431,9 +302,7 @@ const selectPlanar = Fn( ([ pos, selAngles, selCenter, selWidth ])=>{
431
302
 
432
303
  return smoothstep( 0, 1, k );
433
304
 
434
- } );
435
-
436
- selectPlanar.setLayout( {
305
+ } ).setLayout( {
437
306
  name: 'selectPlanar',
438
307
  type: 'float',
439
308
  inputs: [
@@ -445,350 +314,30 @@ selectPlanar.setLayout( {
445
314
  } );
446
315
 
447
316
 
448
- const overlayPlanar = Fn( ( params )=>{
449
-
450
- var zone = selectPlanar(
451
- positionGeometry,
452
- params.selectorAngles,
453
- params.selectorCenter,
454
- params.selectorWidth
455
- ).sub( 0.5 ).mul( 2 ).abs().oneMinus().pow( 0.25 ).negate().mul(
456
- params.selectorShow
457
- );
458
-
459
- return vec3( 0, zone, zone );
460
-
461
- } );
462
-
463
-
464
-
465
- const normalVector = Fn( ([ pos ])=>{
466
-
467
- var dU = dFdx( pos ),
468
- dV = dFdy( pos );
469
-
470
- return transformNormalToView( cross( dU, dV ).normalize() );
471
-
472
- } );
473
-
474
- normalVector.setLayout( {
475
- name: 'normalVector',
476
- type: 'vec3',
477
- inputs: [
478
- { name: 'pos', type: 'vec3' },
479
- ]
480
- } );
481
-
482
-
483
- var banner = null;
484
- var bannerCounter = 10;
485
- async function showFallbackWarning( ) {
486
-
487
- if ( navigator.gpu != undefined ) {
488
-
489
- var adapter = await navigator.gpu.requestAdapter();
490
- if ( adapter ) return;
491
-
492
- }
493
-
494
- var html = `
495
- <div style="font-size:1.25em; font-weight:bold;">PLEASE, WAIT</div>
496
- <div style="font-size:0.85em; font-weight:100;" >NO WEBGPU &mdash; TRYING WEBGL2</div>
497
- <div id="counter"></div>
498
- `;
499
-
500
- banner = document.createElement( 'div' );
501
- banner.innerHTML = html;
502
-
503
- banner.style.left = 'calc(50% - 8em)';
504
- banner.style.width = '16em';
505
-
506
- banner.style.fontFamily = 'Bahnschrifts, Arial';
507
- banner.style.position = 'absolute';
508
- banner.style.bottom = '20px';
509
- banner.style.padding = '12px 6px';
510
- banner.style.border = '1px solid white';
511
- banner.style.borderRadius = '4px';
512
- banner.style.background = 'rgba(0,0,0,0.5)';
513
- banner.style.color = 'white';
514
- banner.style.textAlign = 'center';
515
- banner.style.opacity = '0.8';
516
- banner.style.outline = 'none';
517
- banner.style.zIndex = '999';
518
-
519
- document.body.appendChild( banner );
520
-
521
- }
522
-
523
-
524
-
525
- function hideFallbackWarning( ) {
526
-
527
- if ( banner ) {
528
-
529
- if ( bannerCounter>0 )
530
- bannerCounter--;
531
- else {
532
-
533
- banner.style.display = 'none';
534
- // document.removeChild( banner );
535
- banner = null;
536
-
537
- }
538
-
539
- }
540
-
541
- }
542
-
543
-
544
-
545
- // converts all numeric, color and vector properties to nodes
546
- function prepare( userParams, defaults ) {
547
-
548
- var propertyNames = [];
549
- for ( var item of userParams ) {
550
-
551
- if ( item && typeof item === 'object' ) {
552
-
553
- propertyNames = Object.keys( item );
554
- break;
555
-
556
- }
557
-
558
- }
559
-
560
- var params = { ...defaults };
561
-
562
- for ( var key of propertyNames ) {
563
-
564
- if ( typeof userParams[ key ] !== 'undefined' )
565
- params[ key ] = userParams[ key ];
566
-
567
- }
568
-
569
- for ( var name of Object.keys( params ) ) {
570
-
571
- if ( typeof params[ name ] === 'number' )
572
- params[ name ] = float( params[ name ]);
573
- else
574
- if ( params[ name ] instanceof Color )
575
- params[ name ] = vec3( params[ name ].r, params[ name ].g, params[ name ].b );
576
- else
577
- if ( params[ name ] instanceof Vector3 )
578
- params[ name ] = vec3( params[ name ].x, params[ name ].y, params[ name ].z );
579
-
580
- }
581
-
582
- return params;
583
-
584
- }
585
-
586
-
587
-
588
- // generate scaled noise
589
- function noised( pos, scale=1, octave=1, seed=0 ) {
590
-
591
- return mx_noise_float( pos.mul( scale, octave ).add( seed ) );
592
-
593
- }
594
-
595
-
596
-
597
- // a shim (proposed by Grok) to recover from a change of how Fn
598
- // is proxied since Three.js v0.180.0
599
-
600
- // explanation from Grok:
601
- /*
602
- In 0.179.0, TSL.Fn likely returned a plain function, allowing a.defaults
603
- to work without Proxy interference. In 0.180.0, the Proxy wrapping an FnNode
604
- instance blocks defaults access (returns undefined) and requires specific FnNode
605
- behavior, making the wrapper incompatible.
606
-
607
- Solutions to Fix the Error and Access a.defaultsWe need a solution that:
608
-
609
- * Makes a.defaults directly accessible.
610
- * Preserves TSL compatibility by ensuring the object passed to TSL behaves
611
- like a TSL.Fn Proxy.
612
- * Avoids separate defaults variables.
613
- * Mimics the 0.179.0 API where a.defaults worked.
614
-
615
- Given the error, direct property access on the TSL.Fn Proxy (e.g., Object.defineProperty(a, 'defaults', {...})) fails because the get trap
616
- returns undefined for unknown properties on FnNode. The non-Proxy wrapper
617
- breaks TSL, so let’s try a refined approach that balances compatibility and
618
- accessibility.1. Proxy Wrapper with FnNode PrototypeInstead of a non-Proxy
619
- wrapper, create a Proxy that mimics TSL.Fn but stores defaults separately to
620
- bypass FnNode’s get behavior. To avoid breaking TSL, ensure the Proxy’s target
621
- has the FnNode prototype.
622
-
623
- Why This Might Work:
624
-
625
- * The Proxy’s target inherits the FnNode prototype (via fn.call), making it
626
- appear more like the original TSL.Fn Proxy to TSL’s checks.
627
- * defaults is stored in a Map, bypassing FnNode’s get trap that returns
628
- undefined.
629
- * a.fn exposes the original TSL.Fn Proxy for TSL operations.
630
- * Function calls (a(...)) are forwarded to the original Proxy.
631
- * Matches Object.getOwnPropertyDescriptor behavior.
632
-
633
- */
634
-
635
- function TSLFn( jsFunc, defaults, layout = null ) {
636
-
637
- var opacity = null;
638
- var roughness = null;
639
- var normal = null;
640
-
641
- const fn = Fn( jsFunc, layout );
642
- const customProps = new Map();
643
- customProps.set( 'defaults', defaults );
644
- customProps.set( 'opacity', opacity );
645
- customProps.set( 'roughness', roughness );
646
- customProps.set( 'normal', normal );
647
-
648
- // Create a target with FnNode prototype to mimic TSL.Fn
649
- const target = function () {};
650
-
651
- Object.setPrototypeOf( target, Object.getPrototypeOf( fn.call ) ); // Inherit FnNode prototype
652
-
653
- return new Proxy( target, {
654
- get( target, prop, receiver ) {
655
-
656
- if ( prop === 'defaults' ) {
657
-
658
- return customProps.get( 'defaults' );
659
-
660
- }
661
-
662
- if ( prop === 'opacity' ) {
663
-
664
- return customProps.get( 'opacity' );
665
-
666
- }
667
-
668
- if ( prop === 'roughness' ) {
669
-
670
- return customProps.get( 'roughness' );
671
-
672
- }
673
-
674
- if ( prop === 'normal' ) {
675
-
676
- return customProps.get( 'normal' );
677
-
678
- }
679
-
680
- if ( prop === 'fn' ) {
681
-
682
- return fn; // Expose original TSL.Fn Proxy
683
-
684
- }
685
-
686
- return Reflect.get( fn, prop, receiver ); // Forward to original Proxy
687
-
688
- },
689
- set( target, prop, value, receiver ) {
690
-
691
- if ( prop === 'defaults' ) {
692
-
693
- customProps.set( 'defaults', value );
694
- return true;
695
-
696
- }
697
-
698
- if ( prop === 'opacity' ) {
699
-
700
- customProps.set( 'opacity', value );
701
- return true;
702
-
703
- }
704
-
705
- if ( prop === 'roughness' ) {
706
-
707
- customProps.set( 'roughness', value );
708
- return true;
709
-
710
- }
711
-
712
- if ( prop === 'normal' ) {
713
-
714
- customProps.set( 'normal', value );
715
- return true;
716
-
717
- }
718
-
719
- return Reflect.set( fn, prop, value, receiver );
720
-
721
- },
722
- apply( target, thisArg, args ) {
723
-
724
- return Reflect.apply( fn, thisArg, args ); // Delegate calls to original Proxy
725
-
726
- },
727
- getOwnPropertyDescriptor( target, prop ) {
728
-
729
- if ( prop === 'defaults' ) {
730
-
731
- return {
732
- value: customProps.get( 'defaults' ),
733
- writable: true,
734
- enumerable: true,
735
- configurable: true,
736
- };
737
-
738
- }
739
-
740
- if ( prop === 'opacity' ) {
741
-
742
- Reflect.getOwnPropertyDescriptor( opacity, prop );
743
-
744
- }
745
-
746
- if ( prop === 'roughness' ) {
747
-
748
- Reflect.getOwnPropertyDescriptor( roughness, prop );
749
-
750
- }
751
-
752
- if ( prop === 'normal' ) {
753
-
754
- Reflect.getOwnPropertyDescriptor( normal, prop );
755
-
756
- }
757
-
758
- return Reflect.getOwnPropertyDescriptor( fn, prop );
759
-
760
- }
761
- } );
762
-
763
- } // TSLFn
764
-
765
317
 
766
318
  export
767
319
  {
768
- mx_noise_float as noise
769
- } from 'three/tsl';
770
-
771
- export
772
- {
773
- noised,
774
- vnoise,
320
+ approximateNormal,
321
+ showFallbackWarning,
322
+ hideFallbackWarning,
323
+ remapExp,
775
324
  hsl,
776
325
  toHsl,
777
- dynamic,
326
+ rotatePivot,
327
+ vnoise,
778
328
  spherical,
779
- applyEuler,
780
- remapExp,
781
- matRotX,
782
- matRotY,
783
- matRotZ,
784
- matRotYXZ,
785
- matTrans,
786
- matScale,
787
329
  selectPlanar,
788
- overlayPlanar,
789
- showFallbackWarning,
790
- hideFallbackWarning,
791
- normalVector,
792
- prepare,
793
- TSLFn
794
330
  };
331
+
332
+
333
+
334
+ export
335
+ {
336
+ mx_noise_float as noise,
337
+ mx_fractal_noise_float as fractal,
338
+ mx_fractal_noise_vec3 as fractal3,
339
+ mx_worley_noise_float as voronoi,
340
+ mx_worley_noise_vec2 as voronoi2,
341
+ mx_worley_noise_vec3 as voronoi3,
342
+
343
+ } from 'three/tsl';