tsl-textures 2.0.0 → 2.1.0

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.
@@ -0,0 +1,2657 @@
1
+ // TSL Textures v2.1.0
2
+
3
+ 'use strict';
4
+
5
+ var tsl = require('three/tsl');
6
+ var three = require('three');
7
+
8
+ //import { mx_perlin_noise_float as noise } from 'https://cdn.jsdelivr.net/npm/three@0.167.0/src/nodes/materialx/lib/mx_noise.js';
9
+
10
+
11
+ // helper function - convert hsl to rgb, ported to TSL from:
12
+ // https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative
13
+
14
+ const hslHelper = tsl.Fn( ([ h, s, l, n ])=>{
15
+
16
+ var k = n.add( h.mul( 12 ) ).mod( 12 );
17
+ var a = s.mul( tsl.min( l, tsl.sub( 1, l ) ) );
18
+ return l.sub( a.mul( tsl.max( -1, tsl.min( tsl.min( k.sub( 3 ), tsl.sub( 9, k ) ), 1 ) ) ) );
19
+
20
+ } );
21
+
22
+ hslHelper.setLayout( {
23
+ name: 'hslHelper',
24
+ type: 'float',
25
+ inputs: [
26
+ { name: 'h', type: 'float' },
27
+ { name: 's', type: 'float' },
28
+ { name: 'l', type: 'float' },
29
+ { name: 'n', type: 'float' },
30
+ ]
31
+ } );
32
+
33
+
34
+
35
+ // convert from hsl to rgb
36
+ const hsl = tsl.Fn( ([ h, s, l ]) => {
37
+
38
+ h = h.fract().add( 1 ).fract();
39
+ s = s.clamp( 0, 1 );
40
+ l = l.clamp( 0, 1 );
41
+
42
+ var r = hslHelper( h, s, l, 0 );
43
+ var g = hslHelper( h, s, l, 8 );
44
+ var b = hslHelper( h, s, l, 4 );
45
+
46
+ return tsl.vec3( r, g, b );
47
+
48
+ } );
49
+
50
+ hsl.setLayout( {
51
+ name: 'hsl',
52
+ type: 'vec3',
53
+ inputs: [
54
+ { name: 'h', type: 'float' },
55
+ { name: 's', type: 'float' },
56
+ { name: 'l', type: 'float' },
57
+ ]
58
+ } );
59
+
60
+
61
+ // convert from rgb to hsl
62
+ const toHsl = tsl.Fn( ([ rgb ]) => {
63
+
64
+ var R = tsl.float( rgb.x ).toVar(),
65
+ G = tsl.float( rgb.y ).toVar(),
66
+ B = tsl.float( rgb.z ).toVar();
67
+
68
+ var mx = tsl.max( R, tsl.max( G, B ) ).toVar();
69
+ var mn = tsl.min( R, tsl.min( G, B ) ).toVar();
70
+
71
+ var H = tsl.float( 0 ).toVar(),
72
+ S = tsl.float( 0 ).toVar(),
73
+ L = tsl.add( mx, mn ).div( 2 );
74
+
75
+ tsl.If( mn.notEqual( mx ), ()=>{
76
+
77
+ const delta = tsl.sub( mx, mn ).toVar();
78
+
79
+ S.assign( tsl.select( L.lessThanEqual( 0.5 ), delta.div( tsl.add( mn, mx ) ), delta.div( tsl.sub( 2, tsl.add( mn, mx ) ) ) ) );
80
+ tsl.If( mx.equal( R ), ()=>{
81
+
82
+ H.assign( tsl.sub( G, B ).div( delta ).add( tsl.select( G.lessThanEqual( B ), 6, 0 ) ) );
83
+
84
+ } )
85
+ .ElseIf( mx.equal( G ), ()=>{
86
+
87
+ H.assign( tsl.sub( B, R ).div( delta ).add( 2 ) );
88
+
89
+ } )
90
+ .Else( ()=>{
91
+
92
+ H.assign( tsl.sub( R, G ).div( delta ).add( 4 ) );
93
+
94
+ } );
95
+ H.divAssign( 6 );
96
+
97
+ } );
98
+ return tsl.vec3( H, S, L );
99
+
100
+ } );
101
+
102
+ toHsl.setLayout( {
103
+ name: 'toHsl',
104
+ type: 'vec3',
105
+ inputs: [
106
+ { name: 'rgb', type: 'vec3' },
107
+ ]
108
+ } );
109
+
110
+
111
+
112
+
113
+ // make all elements dynamic (i.e. uniform)
114
+ function dynamic( params ) {
115
+
116
+ var result = {};
117
+
118
+ for ( var [ key, value ] of Object.entries( params ) ) {
119
+
120
+ if ( key[ 0 ]!='$' ) {
121
+
122
+ if ( value instanceof three.Vector3 )
123
+ result[ key ] = tsl.uniform( value, 'vec3' );
124
+ else
125
+ result[ key ] = tsl.uniform( value );
126
+
127
+ }
128
+
129
+ }
130
+
131
+ return result;
132
+
133
+ }
134
+
135
+
136
+
137
+ // convert phi-theta angles to position on unit sphere
138
+ const spherical = tsl.Fn( ([ phi, theta ]) => {
139
+
140
+ return tsl.vec3(
141
+ tsl.sin( theta ).mul( tsl.sin( phi ) ),
142
+ tsl.cos( phi ),
143
+ tsl.cos( theta ).mul( tsl.sin( phi ) )
144
+ );
145
+
146
+ } );
147
+
148
+ spherical.setLayout( {
149
+ name: 'spherical',
150
+ type: 'vec3',
151
+ inputs: [
152
+ { name: 'phi', type: 'float' },
153
+ { name: 'theta', type: 'float' },
154
+ ]
155
+ } );
156
+
157
+
158
+
159
+ // apply Euler rotation to a vector
160
+ const applyEuler = tsl.Fn( ([ vec, eu ]) => {
161
+
162
+ var quat = quaternionFromEuler( eu );
163
+ return applyQuaternion( vec, quat );
164
+
165
+ } );
166
+
167
+ applyEuler.setLayout( {
168
+ name: 'applyEuler',
169
+ type: 'vec4',
170
+ inputs: [
171
+ { name: 'vec', type: 'vec3' },
172
+ { name: 'eu', type: 'vec3' },
173
+ ]
174
+ } );
175
+
176
+
177
+ // convert Euler XYZ angles to quaternion
178
+ const quaternionFromEuler = tsl.Fn( ([ eu ]) => {
179
+
180
+ var c1 = tsl.cos( eu.x.div( 2 ) );
181
+ var c2 = tsl.cos( eu.y.div( 2 ) );
182
+ var c3 = tsl.cos( eu.z.div( 2 ) );
183
+
184
+ var s1 = tsl.sin( eu.x.div( 2 ) );
185
+ var s2 = tsl.sin( eu.y.div( 2 ) );
186
+ var s3 = tsl.sin( eu.z.div( 2 ) );
187
+
188
+ return tsl.vec4(
189
+ tsl.add( tsl.mul( s1, c2, c3 ), tsl.mul( c1, s2, s3 ) ),
190
+ tsl.sub( tsl.mul( c1, s2, c3 ), tsl.mul( s1, c2, s3 ) ),
191
+ tsl.add( tsl.mul( c1, c2, s3 ), tsl.mul( s1, s2, c3 ) ),
192
+ tsl.sub( tsl.mul( c1, c2, c3 ), tsl.mul( s1, s2, s3 ) ),
193
+ );
194
+
195
+ } );
196
+
197
+ quaternionFromEuler.setLayout( {
198
+ name: 'quaternionFromEuler',
199
+ type: 'vec4',
200
+ inputs: [
201
+ { name: 'eu', type: 'vec3' },
202
+ ]
203
+ } );
204
+
205
+
206
+ // apply quaternion rotation to a vector
207
+ const applyQuaternion = tsl.Fn( ([ vec, quat ]) => {
208
+
209
+ var t = tsl.cross( quat.xyz, vec ).mul( 2 ).toVar( );
210
+
211
+ return tsl.add( vec, t.mul( quat.w ), tsl.cross( quat.xyz, t ) );
212
+
213
+ } );
214
+
215
+ applyQuaternion.setLayout( {
216
+ name: 'applyQuaternion',
217
+ type: 'vec3',
218
+ inputs: [
219
+ { name: 'vec', type: 'vec3' },
220
+ { name: 'quat', type: 'vec4' },
221
+ ]
222
+ } );
223
+
224
+
225
+ // exponential version of remap
226
+ const remapExp = tsl.Fn( ([ x, fromMin, fromMax, toMin, toMax ]) => {
227
+
228
+ x = tsl.remap( x, fromMin, fromMax, 0, 1 );
229
+ x = tsl.pow( 2, tsl.mul( x, tsl.log2( toMax.div( toMin ) ) ).add( tsl.log2( toMin ) ) );
230
+ return x;
231
+
232
+ } );
233
+
234
+ remapExp.setLayout( {
235
+ name: 'remapExp',
236
+ type: 'float',
237
+ inputs: [
238
+ { name: 'x', type: 'float' },
239
+ { name: 'fromMin', type: 'float' },
240
+ { name: 'fromMax', type: 'float' },
241
+ { name: 'toMin', type: 'float' },
242
+ { name: 'toMax', type: 'float' },
243
+ ]
244
+ } );
245
+
246
+
247
+
248
+ // simple vector noise, vec3->float[-1,1]
249
+ const vnoise = tsl.Fn( ([ v ])=>{
250
+
251
+ return v.dot( tsl.vec3( 12.9898, 78.233, -97.5123 ) ).sin().mul( 43758.5453 ).fract().mul( 2 ).sub( 1 );
252
+
253
+ } );
254
+
255
+ vnoise.setLayout( {
256
+ name: 'vnoise',
257
+ type: 'float',
258
+ inputs: [
259
+ { name: 'v', type: 'vec3' },
260
+ ]
261
+ } );
262
+
263
+
264
+
265
+ // generate X-rotation matrix
266
+ const matRotX = tsl.Fn( ([ angle ])=>{
267
+
268
+ var cos = angle.cos().toVar(),
269
+ sin = angle.sin().toVar();
270
+
271
+ return tsl.mat4(
272
+ 1, 0, 0, 0,
273
+ 0, cos, sin, 0,
274
+ 0, sin.negate(), cos, 0,
275
+ 0, 0, 0, 1 );
276
+
277
+ } );
278
+
279
+ matRotX.setLayout( {
280
+ name: 'matRotX',
281
+ type: 'mat4',
282
+ inputs: [
283
+ { name: 'angle', type: 'float' },
284
+ ]
285
+ } );
286
+
287
+
288
+
289
+ // generate Y-rotation matrix
290
+ const matRotY = tsl.Fn( ([ angle ])=>{
291
+
292
+ var cos = angle.cos().toVar(),
293
+ sin = angle.sin().toVar();
294
+
295
+ return tsl.mat4(
296
+ cos, 0, sin.negate(), 0,
297
+ 0, 1, 0, 0,
298
+ sin, 0, cos, 0,
299
+ 0, 0, 0, 1 );
300
+
301
+ } );
302
+
303
+ matRotY.setLayout( {
304
+ name: 'matRotY',
305
+ type: 'mat4',
306
+ inputs: [
307
+ { name: 'angle', type: 'float' },
308
+ ]
309
+ } );
310
+
311
+
312
+
313
+ // generate Z-rotation matrix
314
+ const matRotZ = tsl.Fn( ([ angle ])=>{
315
+
316
+ var cos = angle.cos().toVar(),
317
+ sin = angle.sin().toVar();
318
+
319
+ return tsl.mat4(
320
+ cos, sin, 0, 0,
321
+ sin.negate(), cos, 0, 0,
322
+ 0, 0, 1, 0,
323
+ 0, 0, 0, 1 );
324
+
325
+ } );
326
+
327
+ matRotZ.setLayout( {
328
+ name: 'matRotZ',
329
+ type: 'mat4',
330
+ inputs: [
331
+ { name: 'angle', type: 'float' },
332
+ ]
333
+ } );
334
+
335
+
336
+
337
+ // generate YXZ rotation matrix
338
+ const matRotYXZ = tsl.Fn( ([ angles ])=>{
339
+
340
+ var RX = matRotX( angles.x ),
341
+ RY = matRotY( angles.y ),
342
+ RZ = matRotZ( angles.z );
343
+
344
+ return RY.mul( RX ).mul( RZ );
345
+
346
+ } );
347
+
348
+ matRotYXZ.setLayout( {
349
+ name: 'matRotYXZ',
350
+ type: 'mat4',
351
+ inputs: [
352
+ { name: 'angles', type: 'vec3' },
353
+ ]
354
+ } );
355
+
356
+
357
+
358
+ // generate scaling matrix
359
+ const matScale = tsl.Fn( ([ scales ])=>{
360
+
361
+ return tsl.mat4(
362
+ scales.x, 0, 0, 0,
363
+ 0, scales.y, 0, 0,
364
+ 0, 0, scales.z, 0,
365
+ 0, 0, 0, 1 );
366
+
367
+ } );
368
+
369
+ matScale.setLayout( {
370
+ name: 'matScale',
371
+ type: 'mat4',
372
+ inputs: [
373
+ { name: 'scales', type: 'vec3' },
374
+ ]
375
+ } );
376
+
377
+
378
+
379
+ // generate translation matrix
380
+ const matTrans = tsl.Fn( ([ vector ])=>{
381
+
382
+ return tsl.mat4(
383
+ 1, 0, 0, 0,
384
+ 0, 1, 0, 0,
385
+ 0, 0, 1, 0,
386
+ vector.x, vector.y, vector.z, 1 );
387
+
388
+ } );
389
+
390
+ matTrans.setLayout( {
391
+ name: 'matTrans',
392
+ type: 'mat4',
393
+ inputs: [
394
+ { name: 'vector', type: 'vec3' },
395
+ ]
396
+ } );
397
+
398
+
399
+ const selectPlanar = tsl.Fn( ([ pos, selAngles, selCenter, selWidth ])=>{
400
+
401
+ // select zone in a plane through point selCenter,
402
+ // rotated according to selAngles and selWidth thick
403
+ // result is [0,1] inside plane, 0 below plane, 1 above plane
404
+
405
+ // C is projected on segment AB
406
+ // result is [0,1] inside AB, 0 before A, 1 after B
407
+
408
+ /* non-optimized version
409
+ var s = spherical(selAngles.x,selAngles.y).mul(selWidth).toVar(),
410
+ c = pos,
411
+ a = selCenter.sub(s.div(2)),
412
+ b = selCenter.add(s.div(2));
413
+
414
+ var ca = a.sub(c),
415
+ ab = b.sub(a).toVar();
416
+
417
+ var caab = ca.dot(s),
418
+ abab = ab.dot(ab);
419
+
420
+ var k = caab.div(abab).negate();
421
+ */
422
+
423
+ var s = spherical( selAngles.x, selAngles.y ).mul( selWidth ).toVar();
424
+
425
+ var k = selCenter.sub( s.div( 2 ) ).sub( pos ).dot( s ).div( s.dot( s ) ).negate();
426
+
427
+ return tsl.smoothstep( 0, 1, k );
428
+
429
+ } );
430
+
431
+ selectPlanar.setLayout( {
432
+ name: 'selectPlanar',
433
+ type: 'float',
434
+ inputs: [
435
+ { name: 'pos', type: 'vec3' },
436
+ { name: 'selAngles', type: 'vec2' },
437
+ { name: 'selCenter', type: 'vec3' },
438
+ { name: 'selWidth', type: 'float' },
439
+ ]
440
+ } );
441
+
442
+
443
+ const overlayPlanar = tsl.Fn( ( params )=>{
444
+
445
+ var zone = selectPlanar(
446
+ tsl.positionGeometry,
447
+ params.selectorAngles,
448
+ params.selectorCenter,
449
+ params.selectorWidth
450
+ ).sub( 0.5 ).mul( 2 ).abs().oneMinus().pow( 0.25 ).negate().mul(
451
+ params.selectorShow
452
+ );
453
+
454
+ return tsl.vec3( 0, zone, zone );
455
+
456
+ } );
457
+
458
+
459
+
460
+ const normalVector = tsl.Fn( ([ pos ])=>{
461
+
462
+ var dU = tsl.dFdx( pos ),
463
+ dV = tsl.dFdy( pos );
464
+
465
+ return tsl.transformNormalToView( tsl.cross( dU, dV ).normalize() );
466
+
467
+ } );
468
+
469
+ normalVector.setLayout( {
470
+ name: 'normalVector',
471
+ type: 'vec3',
472
+ inputs: [
473
+ { name: 'pos', type: 'vec3' },
474
+ ]
475
+ } );
476
+
477
+
478
+ var banner = null;
479
+ var bannerCounter = 10;
480
+ async function showFallbackWarning( ) {
481
+
482
+ if ( navigator.gpu != undefined ) {
483
+
484
+ var adapter = await navigator.gpu.requestAdapter();
485
+ if ( adapter ) return;
486
+
487
+ }
488
+
489
+ var html = `
490
+ <div style="font-size:1.25em; font-weight:bold;">PLEASE, WAIT</div>
491
+ <div style="font-size:0.85em; font-weight:100;" >NO WEBGPU &mdash; TRYING WEBGL2</div>
492
+ <div id="counter"></div>
493
+ `;
494
+
495
+ banner = document.createElement( 'div' );
496
+ banner.innerHTML = html;
497
+
498
+ banner.style.left = 'calc(50% - 8em)';
499
+ banner.style.width = '16em';
500
+
501
+ banner.style.fontFamily = 'Bahnschrifts, Arial';
502
+ banner.style.position = 'absolute';
503
+ banner.style.bottom = '20px';
504
+ banner.style.padding = '12px 6px';
505
+ banner.style.border = '1px solid white';
506
+ banner.style.borderRadius = '4px';
507
+ banner.style.background = 'rgba(0,0,0,0.5)';
508
+ banner.style.color = 'white';
509
+ banner.style.textAlign = 'center';
510
+ banner.style.opacity = '0.8';
511
+ banner.style.outline = 'none';
512
+ banner.style.zIndex = '999';
513
+
514
+ document.body.appendChild( banner );
515
+
516
+ }
517
+
518
+
519
+
520
+ function hideFallbackWarning( ) {
521
+
522
+ if ( banner ) {
523
+
524
+ if ( bannerCounter>0 )
525
+ bannerCounter--;
526
+ else {
527
+
528
+ banner.style.display = 'none';
529
+ // document.removeChild( banner );
530
+ banner = null;
531
+
532
+ }
533
+
534
+ }
535
+
536
+ }
537
+
538
+
539
+
540
+ // converts all numeric, color and vector properties to nodes
541
+ function prepare( params ) {
542
+
543
+ for ( var name of Object.keys( params ) ) {
544
+
545
+ if ( typeof params[ name ] === 'number' )
546
+ params[ name ] = tsl.float( params[ name ]);
547
+ else
548
+ if ( params[ name ] instanceof three.Color )
549
+ params[ name ] = tsl.vec3( params[ name ].r, params[ name ].g, params[ name ].b );
550
+ else
551
+ if ( params[ name ] instanceof three.Vector3 )
552
+ params[ name ] = tsl.vec3( params[ name ].x, params[ name ].y, params[ name ].z );
553
+
554
+ }
555
+
556
+ return params;
557
+
558
+ }
559
+
560
+
561
+
562
+ // generate scaled noise
563
+ function noised( pos, scale=1, octave=1, seed=0 ) {
564
+
565
+ return tsl.mx_noise_float( pos.mul( scale, octave ).add( seed ) );
566
+
567
+ }
568
+
569
+ var camouflage = tsl.Fn( ( params )=>{
570
+
571
+ params = prepare( { ...camouflage.defaults, ...params } );
572
+
573
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale ) ).add( params.seed ).toVar( );
574
+
575
+ var color = tsl.vec3( 0, 0, 0 ).toVar( );
576
+
577
+ tsl.If( tsl.round( tsl.mx_noise_float( pos, 1, 0.2 ) ).greaterThanEqual( 1 ), () => {
578
+
579
+ color.assign( params.colorA );
580
+
581
+ }
582
+ )
583
+ .ElseIf( tsl.round( tsl.mx_noise_float( pos.yzx, 1, 0.3 ) ).greaterThanEqual( 1 ), () => {
584
+
585
+ color.assign( params.colorB );
586
+
587
+ }
588
+ )
589
+ .ElseIf( tsl.round( tsl.mx_noise_float( pos.zxy, 1, 0.4 ) ).greaterThanEqual( 1 ), () => {
590
+
591
+ color.assign( params.colorC );
592
+
593
+ }
594
+ )
595
+ .Else( () => {
596
+
597
+ color.assign( params.colorD );
598
+
599
+ }
600
+ );
601
+
602
+ return color;
603
+
604
+ } );
605
+
606
+
607
+
608
+ camouflage.defaults = {
609
+ $name: 'Camouflage',
610
+
611
+ scale: 2,
612
+
613
+ colorA: new three.Color( 0xc2bea8 ),
614
+ colorB: new three.Color( 0x9c895e ),
615
+ colorC: new three.Color( 0x92a375 ),
616
+ colorD: new three.Color( 0x717561 ),
617
+
618
+ seed: 0,
619
+ };
620
+
621
+ var caveArt = tsl.Fn( ( params ) => {
622
+
623
+ params = prepare( { ...caveArt.defaults, ...params } );
624
+
625
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale ) ).add( params.seed ).toVar( );
626
+
627
+ var k1 = tsl.mx_noise_float( pos, 4 ).sin().toVar();
628
+ var k2 = tsl.mx_noise_float( pos.mul( 1.5 ), 4 ).cos().toVar();
629
+
630
+ var thinness = tsl.exp( tsl.sub( tsl.float( 3 ), params.thinness ) );
631
+ var k = tsl.sub( thinness, tsl.pow2( tsl.abs( tsl.add( k1, k2 ) ) ).mul( 20 ) ).toVar();
632
+
633
+ tsl.If( tsl.or( k1.greaterThan( k2 ), k.lessThan( 0 ) ), ()=>{
634
+
635
+ k.assign( 0 );
636
+
637
+ } );
638
+
639
+ tsl.If( k.lessThanEqual( 0 ), ()=>{
640
+
641
+ k.assign( params.noise.mul( tsl.pow2( tsl.mx_noise_float( pos.mul( 30 ) ) ) ) );
642
+
643
+ } );
644
+
645
+ return tsl.mix( params.background, params.color, k );
646
+
647
+ } );
648
+
649
+
650
+
651
+ caveArt.defaults = {
652
+ $name: 'Cave art',
653
+
654
+ scale: 2,
655
+ thinness: 2,
656
+ noise: 0.3,
657
+
658
+ color: new three.Color( 0xD34545 ),
659
+ background: new three.Color( 0xFFF8F0 ),
660
+
661
+ seed: 0,
662
+ };
663
+
664
+ var circles = tsl.Fn( ( params ) => {
665
+
666
+ params = prepare( { ...circles.defaults, ...params } );
667
+
668
+ var pos = tsl.select( params.flat, tsl.positionGeometry, tsl.positionGeometry.normalize() );
669
+
670
+ var angle = tsl.acos( tsl.clamp( pos.y, -1, 1 ) ).mul( 20 );
671
+
672
+ var scale = tsl.exp( params.scale.sub( 1 ) );
673
+
674
+ var x = angle.div( 3000 ).mul( scale );
675
+
676
+ var k = tsl.float( params.seed.sin().mul( 100 ) ).toVar();
677
+
678
+ for ( var n=0; n<=10; n++ ) {
679
+
680
+ k.addAssign( tsl.sin( x.mul( 2**n ).sub( Math.PI*n/2 ) ).mul( -n*( n+1 )/2 ) );
681
+
682
+ }
683
+
684
+ k.assign( k.div( 200 ).clamp( -2, 2 ) );
685
+
686
+ var HSL = toHsl( params.color );
687
+
688
+ var hue = HSL.x.add( k.mul( params.variety ) ).mod( 1 ).mul( 10 );
689
+
690
+ var huei = hue.floor();
691
+ var huef = hue.sub( huei );
692
+ huef = tsl.select( huef.lessThan( 0.5 ), huef.pow( 1.5 ), huef.pow( 1/1.5 ) );
693
+
694
+ return hsl( huei.add( huef ).div( 10 ), HSL.y, HSL.z );
695
+
696
+ } );
697
+
698
+
699
+
700
+ circles.defaults = {
701
+ $name: 'Circles',
702
+
703
+ scale: 2,
704
+ variety: 1,
705
+
706
+ color: new three.Color( 0xF0E0D0 ),
707
+
708
+ flat: 0,
709
+
710
+ seed: 0,
711
+ };
712
+
713
+ var _clouds = tsl.Fn( ( params ) => {
714
+
715
+ // prepare parameters
716
+ params = prepare( { ...clouds.defaults, ...params } );
717
+
718
+ const pos = tsl.positionGeometry;
719
+ const scale = tsl.exp( params.scale.div( 1.5 ).sub( 0.5 ) );
720
+
721
+ // color blending
722
+ const k = tsl.add(
723
+ noised( pos, scale, 1, params.seed ),
724
+ noised( pos, scale, 2, params.seed ).mul( 0.80 ),
725
+ noised( pos, scale, 6, params.seed ).mul( 0.10 ),
726
+ noised( pos, scale, 8, params.seed ).mul( 0.07, params.opacity ),
727
+ params.density.remap( 0, 1, -0.5, 1.5 )
728
+ );
729
+
730
+ // opacity
731
+ const a = tsl.clamp( 0, 1, tsl.mul( k, 2 ).pow( 1.5 ).sub( 1 ).mul( params.opacity ) );
732
+
733
+ // final color+opacity
734
+ return tsl.vec4( tsl.mix( params.subcolor, params.color, k.clamp( 0, 1 ) ), a );
735
+
736
+ } );
737
+
738
+
739
+
740
+ var clouds = tsl.Fn( ( params ) => {
741
+
742
+ return _clouds( params ).rgb;
743
+
744
+ } );
745
+
746
+
747
+
748
+ clouds.opacity = tsl.Fn( ( params ) => {
749
+
750
+ return _clouds( params ).a;
751
+
752
+ } );
753
+
754
+
755
+
756
+ clouds.defaults = {
757
+ $name: 'Clouds',
758
+
759
+ scale: 2,
760
+ density: 0.5,
761
+ opacity: 1,
762
+
763
+ color: new three.Color( 0xFFFFFF ),
764
+ subcolor: new three.Color( 0xA0A0B0 ),
765
+
766
+ seed: 0,
767
+ };
768
+
769
+ var surfacePos$7 = tsl.Fn( ([ pos, normal, bump, density, seed ]) => {
770
+
771
+ var k = tsl.mx_noise_float( pos.add( seed ) ).mul( 0.5 ).add( 0.5 );
772
+ k = bump.mul( tsl.pow( tsl.abs( k ), density ) );
773
+
774
+ return pos.add( k.mul( normal ) );
775
+
776
+ } );
777
+
778
+
779
+ var concrete = tsl.Fn( ( params ) => {
780
+
781
+ params = prepare( { ...concrete.defaults, ...params } );
782
+
783
+ var eps = 0.001;
784
+
785
+ var position = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 2 ).add( 2 ) ) ).toVar( ),
786
+ normal = tsl.normalLocal.normalize().toVar(),
787
+ tangent = tsl.tangentLocal.normalize().mul( eps ).toVar(),
788
+ bitangent = tsl.cross( normal, tangent ).normalize().mul( eps ).toVar();
789
+
790
+ var density = tsl.remap( params.density, 0, 1, 10, 0.5 ).toVar();
791
+ var seed = tsl.vec3( tsl.sin( params.seed ).mul( 100 ), tsl.cos( params.seed.div( 2 ) ).mul( 100 ), tsl.sin( params.seed.div( 3 ) ).mul( 100 ) ).toVar();
792
+
793
+ var pos = surfacePos$7( position, normal, params.bump, density, seed );
794
+ var posU = surfacePos$7( position.add( tangent ), normal, params.bump, density, seed );
795
+ var posV = surfacePos$7( position.add( bitangent ), normal, params.bump, density, seed );
796
+
797
+ var dU = tsl.sub( posU, pos ),
798
+ dV = tsl.sub( posV, pos );
799
+
800
+ return tsl.transformNormalToView( tsl.cross( dU, dV ).normalize() );
801
+
802
+ } );
803
+
804
+
805
+
806
+ concrete.defaults = {
807
+ $name: 'Concrete',
808
+ $normalNode: true,
809
+
810
+ scale: 2,
811
+ density: 0.5,
812
+ bump: 0.5,
813
+
814
+ seed: 0,
815
+ };
816
+
817
+ var cellCenter$1 = tsl.Fn( ([ cell ])=>{
818
+
819
+ return cell.add( vnoise( cell ) );
820
+
821
+ } );
822
+
823
+
824
+ var cork = tsl.Fn( ( params )=>{
825
+
826
+ params = prepare( { ...cork.defaults, ...params } );
827
+
828
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 1.5 ).add( 1 ) ) ).add( params.seed ).toVar( );
829
+
830
+ var midCell = pos.round().toVar();
831
+
832
+ var minCell = midCell.toVar();
833
+ var minDist = tsl.float( 1 ).toVar();
834
+
835
+ var cell = tsl.vec3().toVar();
836
+ var dist = tsl.float().toVar();
837
+
838
+ var i = tsl.float( 0 ).toVar();
839
+
840
+
841
+ tsl.Loop( 27, () => {
842
+
843
+ var ix = i.mod( 3 ).sub( 1 );
844
+ var iy = i.div( 3 ).floor().mod( 3 ).sub( 1 );
845
+ var iz = i.div( 9 ).floor().sub( 1 );
846
+ cell.assign( midCell.add( tsl.vec3( ix, iy, iz ) ) );
847
+ dist.assign( pos.distance( cellCenter$1( cell ) ) );
848
+
849
+ dist.addAssign( tsl.mx_noise_float( pos.add( cell ) ).div( params.straight.exp() ) );
850
+
851
+ tsl.If( dist.lessThan( minDist ), ()=>{
852
+
853
+ minDist.assign( dist );
854
+ minCell.assign( cell );
855
+
856
+ } );
857
+ i.addAssign( 1 );
858
+
859
+ } );
860
+
861
+ var n = tsl.mx_noise_float( minCell.mul( Math.PI ) ).toVar();
862
+ var r = tsl.mx_noise_float( pos.mul( 12 ) ).toVar();
863
+ r.assign( r.sign().mul( r.abs().pow3() ) );
864
+ r.addAssign( tsl.mx_noise_float( pos.mul( 40 ) ).div( 3 ) );
865
+ var k = n.add( 1 ).div( 2 );
866
+
867
+ var color = tsl.mix( params.color, params.background, k.add( r.mul( params.noise ) ) ).toVar();
868
+
869
+ return color;
870
+
871
+ } );
872
+
873
+
874
+
875
+ cork.defaults = {
876
+ $name: 'Cork',
877
+
878
+ scale: 1,
879
+ straight: 1,
880
+ noise: 0.3,
881
+
882
+ color: new three.Color( 0xfff0c0 ),
883
+ background: new three.Color( 0xd08060 ),
884
+
885
+ seed: 0,
886
+ };
887
+
888
+ var dalmatianSpots = tsl.Fn( ( params )=>{
889
+
890
+ params = prepare( { ...dalmatianSpots.defaults, ...params } );
891
+
892
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale ) ).add( params.seed ).sub( 1000 ).toVar( );
893
+
894
+ var k = tsl.float( 1 ).toVar();
895
+
896
+ var d = tsl.float( 1.5 ).sub( params.density ).mul( 2 ).toVar();
897
+ var count = params.density.mul( 5 ).add( 5 ).toVar();
898
+
899
+ tsl.Loop( count, ()=> {
900
+
901
+ k.mulAssign( tsl.mx_noise_float( pos ).abs().pow( d ).mul( 100 ).sub( 50 ).clamp( 0, 1 ).oneMinus() );
902
+ pos.assign( pos.mul( 1.01 ) );
903
+ k.mulAssign( tsl.mx_noise_float( pos.yzx ).abs().pow( d ).mul( 100 ).sub( 50 ).clamp( 0, 1 ).oneMinus() );
904
+ pos.assign( pos.mul( 1.01 ) );
905
+ k.mulAssign( tsl.mx_noise_float( pos.zxy ).abs().pow( d ).mul( 100 ).sub( 50 ).clamp( 0, 1 ).oneMinus() );
906
+ pos.assign( pos.mul( 1.01 ) );
907
+
908
+ } );
909
+
910
+ return tsl.mix( params.background, params.color, k.clamp( 0, 1 ) );
911
+
912
+ } );
913
+
914
+
915
+ dalmatianSpots.defaults = {
916
+ $name: 'Dalmatian spots',
917
+ $width: 260,
918
+
919
+ scale: 2,
920
+ density: 0.6,
921
+
922
+ color: new three.Color( 0xFFFFFF ),
923
+ background: new three.Color( 0x000000 ),
924
+
925
+ seed: 0,
926
+ };
927
+
928
+ var noisea = tsl.Fn( ([ pos ])=>{
929
+
930
+ var p = pos.mul( 5**0.5 ).fract().toVar();
931
+ p.addAssign( p.dot( p.add( tsl.vec3( 31.4159, 27.1828, 14.142 ) ) ) );
932
+ return p.z.mul( p.x.add( p.y ) ).fract().mul( 2 ).sub( 1 );
933
+
934
+ } );
935
+
936
+
937
+ var smooth = tsl.Fn( ([ x ])=>{
938
+
939
+ var t = x.oneMinus().clamp( 0, 1 ).toVar();
940
+ return t.mul( t ).mul( tsl.float( 3 ).sub( t.mul( 2 ) ) );
941
+
942
+ } );
943
+
944
+
945
+ var noiseg = tsl.Fn( ([ pos ])=>{
946
+
947
+ var minx = pos.x.floor().toVar();
948
+ var maxx = minx.add( 1 ).toVar();
949
+
950
+ var miny = pos.y.floor().toVar();
951
+ var maxy = miny.add( 1 ).toVar();
952
+
953
+ var minz = pos.z.floor().toVar();
954
+ var maxz = minz.add( 1 ).toVar();
955
+
956
+ var dx = smooth( pos.x.fract() ).toVar();
957
+ var dy = smooth( pos.y.fract() ).toVar();
958
+ var dz = smooth( pos.z.fract() ).toVar();
959
+
960
+ var mx = smooth( dx.oneMinus() ).toVar();
961
+ var my = smooth( dy.oneMinus() ).toVar();
962
+ var mz = smooth( dz.oneMinus() ).toVar();
963
+
964
+ var n000 = noisea( tsl.vec3( minx, miny, minz ) ).mul( mx ).mul( my ).mul( mz ).toVar();
965
+ var n001 = noisea( tsl.vec3( minx, miny, maxz ) ).mul( mx ).mul( my ).mul( dz ).toVar();
966
+ var n010 = noisea( tsl.vec3( minx, maxy, minz ) ).mul( mx ).mul( dy ).mul( mz ).toVar();
967
+ var n011 = noisea( tsl.vec3( minx, maxy, maxz ) ).mul( mx ).mul( dy ).mul( dz ).toVar();
968
+ var n100 = noisea( tsl.vec3( maxx, miny, minz ) ).mul( dx ).mul( my ).mul( mz ).toVar();
969
+ var n101 = noisea( tsl.vec3( maxx, miny, maxz ) ).mul( dx ).mul( my ).mul( dz ).toVar();
970
+ var n110 = noisea( tsl.vec3( maxx, maxy, minz ) ).mul( dx ).mul( dy ).mul( mz ).toVar();
971
+ var n111 = noisea( tsl.vec3( maxx, maxy, maxz ) ).mul( dx ).mul( dy ).mul( dz ).toVar();
972
+
973
+ return n000.add( n001 ).add( n010 ).add( n011 ).add( n100 ).add( n101 ).add( n110 ).add( n111 );
974
+
975
+ } );
976
+
977
+
978
+
979
+ var dysonSphere = tsl.Fn( ( params )=>{
980
+
981
+ params = prepare( { ...dysonSphere.defaults, ...params } );
982
+
983
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 2 ).add( 0.5 ) ) ).add( params.seed ).toVar( );
984
+
985
+ var res = tsl.vec3().toVar();
986
+ var factor = tsl.float( 1 ).toVar();
987
+
988
+ tsl.Loop( params.complexity.add( 4 ), ()=>{
989
+
990
+ res.addAssign( noiseg( pos.mul( factor ) ) );
991
+ factor.addAssign( factor );
992
+
993
+ } );
994
+
995
+ return tsl.mix( params.background, params.color, res.x.add( 1 ).div( 5 ) );
996
+
997
+ } );
998
+
999
+
1000
+
1001
+ dysonSphere.defaults = {
1002
+ $name: 'Dyson sphere',
1003
+
1004
+ scale: 2,
1005
+ complexity: 2,
1006
+
1007
+ variation: 0,
1008
+
1009
+ color: new three.Color( 0xc0d0ff ),
1010
+ background: new three.Color( 0 ),
1011
+
1012
+ seed: 0,
1013
+ };
1014
+
1015
+ var entangled = tsl.Fn( ( params ) => {
1016
+
1017
+ params = prepare( { ...entangled.defaults, ...params } );
1018
+
1019
+ var scale = tsl.exp( params.scale.div( 2 ) ).toVar( );
1020
+ var pos = tsl.positionGeometry.add( params.seed ).toVar( );
1021
+ var k = tsl.float( -1e4 ).toVar( );
1022
+ var k1 = tsl.float( 0 ).toVar( );
1023
+
1024
+ tsl.Loop( tsl.floor( tsl.float( params.density ) ), ()=> {
1025
+
1026
+ k1.assign( tsl.sin( tsl.mx_noise_float( tsl.mul( pos, scale ) ).mul( 3*Math.PI ) ) );
1027
+ k.assign( tsl.max( k, k1 ) );
1028
+ scale.mulAssign( 1.2 );
1029
+
1030
+ } );
1031
+
1032
+ k.assign( tsl.oneMinus( tsl.pow( tsl.abs( k ), 5 ) ).mul( 6 ) );
1033
+
1034
+ return tsl.mix( params.color, params.background, k );
1035
+
1036
+ } );
1037
+
1038
+
1039
+
1040
+ entangled.defaults = {
1041
+ $name: 'Entangled',
1042
+
1043
+ scale: 2,
1044
+ density: 10,
1045
+
1046
+ color: new three.Color( 0x002040 ),
1047
+ background: new three.Color( 0xFFFFFF ),
1048
+
1049
+ seed: 0,
1050
+ };
1051
+
1052
+ var fordite = tsl.Fn( ( params ) => {
1053
+
1054
+ params = prepare( { ...fordite.defaults, ...params } );
1055
+
1056
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale ) ).add( params.seed ).toVar( );
1057
+
1058
+ var k = tsl.mx_noise_float(
1059
+ tsl.vec3(
1060
+ tsl.mx_noise_float( pos ),
1061
+ tsl.mx_noise_float( pos ).mul( 2 ),
1062
+ tsl.mx_noise_float( pos ).mul( 3 ),
1063
+ )
1064
+ ).toVar( );
1065
+
1066
+ return hsl(
1067
+ k,
1068
+ 1,
1069
+ tsl.sin( tsl.mul( k, Math.PI, 4 ) ).mul( 0.5 ).add( 0.5 )
1070
+ ).add( params.color );
1071
+
1072
+ } );
1073
+
1074
+
1075
+
1076
+ fordite.defaults = {
1077
+ $name: 'Fordite',
1078
+ scale: 2,
1079
+ color: new three.Color( 0, 0, 0 ),
1080
+ seed: 0,
1081
+ };
1082
+
1083
+ var gasGiant = tsl.Fn( ( params )=>{
1084
+
1085
+ params = prepare( { ...gasGiant.defaults, ...params } );
1086
+
1087
+ var scale = params.scale.div( 2 ).add( 1 ).toVar();
1088
+ var pos = tsl.positionGeometry.mul( tsl.exp( scale ) ).add( params.seed ).toVar( );
1089
+
1090
+ // turbulence strength
1091
+ var turbulence = params.turbulence.mul(
1092
+ tsl.mx_noise_float( tsl.vec3( 0, pos.y.mul( 0.5 ), 0 ).add( 1 ) ).add(
1093
+ tsl.mx_noise_float( tsl.vec3( 0, pos.y.mul( 1 ), 0 ).add( 1 ) ).mul( 0.5 ),
1094
+ tsl.mx_noise_float( tsl.vec3( 1, pos.y.mul( 2 ), 1 ).add( 1 ) ).mul( 0.25 )
1095
+ )
1096
+ ).mul( 5 ).abs().toVar();
1097
+
1098
+ var spot = tsl.mx_noise_float( pos.div( 4 ) ).add( 1 ).div( 2 ).pow( 10 ).mul( 10 ).smoothstep( 0, 1 );
1099
+
1100
+ // apply turbulence
1101
+ pos.addAssign( tsl.vec3( tsl.mx_noise_float( pos ), tsl.mx_noise_float( pos.yxz ), tsl.mx_noise_float( pos.yzx ) ).mul( turbulence.mul( spot.mul( 2 ).exp() ) ) );
1102
+
1103
+
1104
+ var blur = params.blur.pow( 0.2 ).oneMinus().mul( turbulence.add( 1 ) ).toVar();
1105
+
1106
+ var k = tsl.mx_noise_float( pos.mul( tsl.vec3( 0, scale, 0 ) ) );
1107
+ k = k.add( tsl.mx_noise_float( pos.mul( tsl.vec3( 1, 15, 1 ) ) ).mul( blur ) );
1108
+ k = k.add( -0.5 ).smoothstep( -1, 1 ).oneMinus();
1109
+
1110
+ var n = tsl.mx_noise_float( tsl.vec3( 0, pos.y.mul( 0.75 ), 0 ) ).add( 1 );
1111
+
1112
+ var HSL = toHsl( tsl.mix( params.colorB, params.colorA, n ) );
1113
+ var color = hsl( HSL.x.add( tsl.mx_noise_float( pos.mul( tsl.vec3( 0, scale, 0 ) ) ).div( 4 ) ), HSL.y, HSL.z ).toVar();
1114
+
1115
+ color.assign( tsl.mix( color, params.colorC, turbulence.mul( 0.3 ) ) );
1116
+
1117
+ return color.mul( k );
1118
+
1119
+ } );
1120
+
1121
+
1122
+ gasGiant.defaults = {
1123
+ $name: 'Gas giant',
1124
+
1125
+ scale: 2,
1126
+ turbulence: 0.3,
1127
+ blur: 0.6,
1128
+
1129
+ colorA: new three.Color( 0xFFF8F0 ),
1130
+ colorB: new three.Color( 0xF0E8B0 ),
1131
+ colorC: new three.Color( 0xAFA0D0 ),
1132
+
1133
+ seed: 0,
1134
+ };
1135
+
1136
+ var grid = tsl.Fn( ( params ) => {
1137
+
1138
+ params = prepare( { ...grid.defaults, ...params } );
1139
+
1140
+ var aspect = tsl.select( params.flat, tsl.screenSize.x.div( tsl.screenSize.y ), 2 );
1141
+
1142
+ var uv = tsl.select( params.flat, tsl.screenUV, tsl.equirectUV( tsl.positionGeometry.normalize() ) ).toVar(),
1143
+ a = tsl.mul( uv.x, aspect, Math.PI ),
1144
+ b = tsl.mul( uv.y, Math.PI ).toVar();
1145
+
1146
+ var uTo = tsl.div( tsl.round( tsl.mul( uv.x, params.countU ) ), params.countU ),
1147
+ vTo = tsl.div( tsl.round( tsl.mul( uv.y, params.countV ) ), params.countV ),
1148
+ aTo = tsl.mul( uTo, aspect, Math.PI ),
1149
+ bTo = tsl.mul( vTo, Math.PI );
1150
+
1151
+ var angleU = tsl.abs( tsl.sub( a, aTo ) ).mul( tsl.select( params.flat, 1, tsl.sin( b ) ) ),
1152
+ angleV = tsl.abs( tsl.sub( b, bTo ) ),
1153
+ angle = tsl.min( angleU, angleV );
1154
+
1155
+ var treshold = tsl.mul( tsl.min( tsl.div( aspect.mul( Math.PI ), params.countU ), tsl.div( Math.PI, params.countV ) ), tsl.remapClamp( tsl.pow( params.thinness, 0.5 ), 0, 1, 0.9, 0.04 ), 0.5 );
1156
+ var k = tsl.oneMinus( tsl.smoothstep( tsl.sub( treshold, 0.002 ), tsl.add( treshold, 0.002 ), angle ) );
1157
+
1158
+ return tsl.mix( params.background, params.color, k );
1159
+
1160
+ } );
1161
+
1162
+
1163
+
1164
+ grid.defaults = {
1165
+ $name: 'Grid',
1166
+
1167
+ countU: 32,
1168
+ countV: 16,
1169
+
1170
+ thinness: 0.8,
1171
+
1172
+ color: new three.Color( 0x000000 ),
1173
+ background: new three.Color( 0xFFFFFF ),
1174
+
1175
+ flat: 0,
1176
+ };
1177
+
1178
+ var isolines = tsl.Fn( ( params )=>{
1179
+
1180
+ params = prepare( { ...isolines.defaults, ...params } );
1181
+
1182
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale ) ).add( params.seed ).toVar( );
1183
+
1184
+ var k = tsl.mx_noise_float( pos ).mul( params.density );
1185
+
1186
+ k = tsl.oneMinus( tsl.sin( k ) ).div( 2 );
1187
+
1188
+ k = tsl.smoothstep( tsl.sub( params.thinness, params.blur ), tsl.add( params.thinness, params.blur ), k );
1189
+
1190
+ return tsl.mix( params.color, params.background, k );
1191
+
1192
+ } );
1193
+
1194
+
1195
+ isolines.defaults = {
1196
+ $name: 'Isolines',
1197
+
1198
+ scale: 2,
1199
+ density: 40,
1200
+ blur: 0.3,
1201
+ thinness: 0.6,
1202
+
1203
+ color: new three.Color( 0xFFFFFF ),
1204
+ background: new three.Color( 0x000000 ),
1205
+
1206
+ seed: 0,
1207
+ };
1208
+
1209
+ var karstRock = tsl.Fn( ( params )=>{
1210
+
1211
+ params = prepare( { ...karstRock.defaults, ...params } );
1212
+
1213
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale ) ).add( params.seed.sin().mul( 5 ) ).toVar( );
1214
+
1215
+ var pos2 = pos.add( tsl.mx_noise_float( pos.mul( 2 ) ) ).toVar();
1216
+
1217
+ var k = tsl.mx_noise_float( pos2 ).div( tsl.mx_noise_float( pos2.mul( 1.01 ) ) ).clamp( 0, 2 ).toVar();
1218
+
1219
+ k.addAssign( tsl.mx_noise_float( pos.mul( 100 ) ).div( 3 ) );
1220
+ k.addAssign( tsl.mx_noise_float( pos.mul( 2 ) ).div( 2 ) );
1221
+
1222
+ return tsl.mix( params.background, params.color, k ).mul( k.pow( 0.1 ) );
1223
+
1224
+ } );
1225
+
1226
+
1227
+
1228
+ karstRock.defaults = {
1229
+ $name: 'Karst rock',
1230
+
1231
+ scale: 2,
1232
+
1233
+ color: new three.Color( 0xFFF4F0 ),
1234
+ background: new three.Color( 0xD0D0D0 ),
1235
+
1236
+ seed: 0,
1237
+ };
1238
+
1239
+ var marble = tsl.Fn( ( params ) => {
1240
+
1241
+ params = prepare( { ...marble.defaults, ...params } );
1242
+
1243
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale ) ).add( params.seed ).toVar( );
1244
+
1245
+ var k = tsl.add(
1246
+ tsl.mx_noise_float( pos ),
1247
+ tsl.mx_noise_float( pos.mul( 2 ) ).mul( 0.5 ),
1248
+ tsl.mx_noise_float( pos.mul( 6 ) ).mul( 0.1 )
1249
+ );
1250
+
1251
+ var k = tsl.oneMinus( k.abs().pow( 2.5 ) ).toVar();
1252
+
1253
+ var maxSmooth = tsl.oneMinus( tsl.pow( 0.5, params.thinness.add( 7 ) ) ).toVar(),
1254
+ minSmooth = tsl.oneMinus( tsl.pow( 0.5, params.thinness.add( 7 ).mul( 0.5 ) ) ).toVar();
1255
+
1256
+ tsl.If( k.greaterThan( maxSmooth ), ()=>{
1257
+
1258
+ k.assign( 1 );
1259
+
1260
+ } )
1261
+ .ElseIf( k.lessThan( minSmooth ), ()=>{
1262
+
1263
+ k.assign( 0 );
1264
+
1265
+ } )
1266
+ .Else( ()=> {
1267
+
1268
+ var a = k.sub( minSmooth );
1269
+ var b = maxSmooth.sub( minSmooth );
1270
+ k.assign( tsl.pow( tsl.div( a, b ), 5 ).mul( 0.75 ) );
1271
+ k.assign( k.mul( tsl.add( 0.5, tsl.mx_noise_float( pos.mul( 2 ) ).mul( 1.5 ) ) ) );
1272
+
1273
+ } );
1274
+
1275
+ k.assign( k.add( tsl.mul( params.noise, tsl.mx_noise_float( pos.mul( 150 ) ).abs().pow3() ) ) );
1276
+
1277
+ return tsl.mix( params.background, params.color, k );
1278
+
1279
+ } );
1280
+
1281
+
1282
+
1283
+ marble.defaults = {
1284
+ $name: 'Marble',
1285
+
1286
+ scale: 1.2,
1287
+ thinness: 5,
1288
+ noise: 0.3,
1289
+
1290
+ color: new three.Color( 0x4545D3 ),
1291
+ background: new three.Color( 0xF0F8FF ),
1292
+
1293
+ seed: 0,
1294
+ };
1295
+
1296
+ var neonLights = tsl.Fn( ( params ) => {
1297
+
1298
+ params = prepare( { ...neonLights.defaults, ...params } );
1299
+
1300
+ var pos = tsl.positionGeometry;//.mul( exp( params.scale ) ).add( params.seed ).toVar( );
1301
+
1302
+ var scale = tsl.exp( params.scale.remap( 0, 4, 2, -2 ) ).toVar();
1303
+ var thinness = tsl.exp( params.thinness.remap( 0, 1, 1.5, 0 ) ).toVar();
1304
+
1305
+ var color = params.background.toVar();
1306
+ var neon = tsl.vec3( 0 ).toVar();
1307
+
1308
+ var x = tsl.mx_noise_float( pos.xyz ).toVar();
1309
+ var y = tsl.mx_noise_float( pos.yzx ).toVar();
1310
+ var z = tsl.mx_noise_float( pos.zxy ).toVar();
1311
+
1312
+ var k = tsl.mx_noise_float( tsl.vec3( x, y, z ).mul( scale ).add( params.seed ) ).toVar();
1313
+ k.assign( tsl.oneMinus( tsl.sqrt( tsl.abs( k ) ) ).pow( 3 ) );
1314
+
1315
+ neon.assign( params.colorA );
1316
+ var HSL = toHsl( neon );
1317
+ neon.assign( hsl( HSL.x, HSL.y, HSL.z.mul( k ) ) );
1318
+
1319
+ color.addAssign( tsl.select( params.mode.equal( 0 ), neon, neon.negate() ).mul( thinness ) );
1320
+
1321
+ k.assign( tsl.mx_noise_float( tsl.vec3( y, z, x ).mul( scale ).sub( params.seed ) ) );
1322
+ k.assign( tsl.oneMinus( tsl.sqrt( tsl.abs( k ) ) ).pow( 3 ) );
1323
+
1324
+ neon.assign( params.colorB );
1325
+ var HSL = toHsl( neon );
1326
+ neon.assign( hsl( HSL.x, HSL.y, HSL.z.mul( k ) ) );
1327
+
1328
+ color.addAssign( tsl.select( params.mode.equal( 0 ), neon, neon.negate() ).mul( thinness ) );
1329
+
1330
+
1331
+ k.assign( tsl.mx_noise_float( tsl.vec3( z, x, y.negate() ).mul( scale ).add( params.seed ) ) );
1332
+ k.assign( tsl.oneMinus( tsl.sqrt( tsl.abs( k ) ) ).pow( 3 ) );
1333
+
1334
+ neon.assign( params.colorC );
1335
+ var HSL = toHsl( neon );
1336
+ neon.assign( hsl( HSL.x, HSL.y, HSL.z.mul( k ) ) );
1337
+
1338
+ color.addAssign( tsl.select( params.mode.equal( 0 ), neon, neon.negate() ).mul( thinness ) );
1339
+
1340
+ return color;
1341
+
1342
+ } );
1343
+
1344
+
1345
+
1346
+ neonLights.defaults = {
1347
+ $name: 'Neon Lights',
1348
+
1349
+ scale: 1.5,
1350
+ thinness: 0.8,
1351
+ mode: 0, // 0=additive, 1=subtractive
1352
+
1353
+ colorA: new three.Color( 0xFF0000 ),
1354
+ colorB: new three.Color( 0x00FF00 ),
1355
+ colorC: new three.Color( 0x0000FF ),
1356
+ background: new three.Color( 0x000000 ),
1357
+
1358
+ seed: 0,
1359
+ };
1360
+
1361
+ var photosphere = tsl.Fn( ( params ) => {
1362
+
1363
+ params = prepare( { ...photosphere.defaults, ...params } );
1364
+
1365
+ var scale = tsl.exp( params.scale.add( 1 ) ).toVar( );
1366
+ var pos = tsl.positionGeometry.toVar( );
1367
+
1368
+ var vec = tsl.vec3( pos ).toVar();
1369
+
1370
+ tsl.Loop( 6, () => {
1371
+
1372
+ vec.assign( applyEuler( vec, pos.mul( scale ) ) );
1373
+ scale.mulAssign( params.seed.mul( scale ).sin().mul( 0.05 ).add( 1.1 ) );
1374
+
1375
+ } );
1376
+
1377
+
1378
+ var k = tsl.mx_noise_float( vec ).add( 1 ).div( 2 );
1379
+
1380
+ return tsl.mix( params.background, params.color, k );
1381
+
1382
+ } );
1383
+
1384
+
1385
+
1386
+ photosphere.defaults = {
1387
+ $name: 'Photosphere',
1388
+
1389
+ scale: 2,
1390
+
1391
+ color: new three.Color( 0xFFFF00 ),
1392
+ background: new three.Color( 0xFF0000 ),
1393
+
1394
+ seed: 0,
1395
+ };
1396
+
1397
+ var planet = tsl.Fn( ( params )=>{
1398
+
1399
+ params = prepare( { ...planet.defaults, ...params } );
1400
+
1401
+ var k = tsl.float( 0 ).toVar(),
1402
+ sum = tsl.float( 0 ).toVar(),
1403
+ scale = tsl.exp( params.scale.sub( 2 ) ).toVar(),
1404
+ power = tsl.float( 2 ).toVar();
1405
+
1406
+ tsl.Loop( params.iterations.add( 10 ), ()=>{
1407
+
1408
+ k.addAssign( tsl.mul( power, tsl.mx_noise_float( tsl.positionGeometry.mul( scale ).add( params.seed ) ) ) );
1409
+ sum.addAssign( power );
1410
+ scale.mulAssign( 1.5 );
1411
+ power.mulAssign( 0.8 );
1412
+
1413
+ } );
1414
+
1415
+ k.assign( tsl.mul( k, k, 0.5 ).div( sum ) );
1416
+
1417
+ var levelSea = params.levelSea.pow( 2 ).toVar();
1418
+ var levelMountain = params.levelMountain.pow( 2 ).toVar();
1419
+ var levelSand = tsl.mix( levelSea, levelMountain, params.balanceSand ).toVar();
1420
+ var levelCoast = tsl.mix( levelSea, levelSand, 0.4 ).toVar();
1421
+ var levelGrass = tsl.mix( levelSea, levelSand, 0.6 ).toVar();
1422
+
1423
+ var color = tsl.vec3().toVar();
1424
+
1425
+ // process water
1426
+ tsl.If( k.lessThan( levelSea ), ()=>{
1427
+
1428
+ // deep-shallow
1429
+ color.assign( tsl.mix(
1430
+ params.colorDeep,
1431
+ params.colorShallow,
1432
+ tsl.remap( k, 0, levelSea, 0, 1 ).pow( tsl.exp( params.balanceWater.mul( -8 ).add( 4 ) ) )
1433
+ ) );
1434
+
1435
+ } )
1436
+ .ElseIf( k.lessThan( levelCoast ), ()=>{
1437
+
1438
+ // shallow-sand
1439
+ color.assign( tsl.mix(
1440
+ params.colorShallow,
1441
+ params.colorBeach,
1442
+ tsl.remap( k, levelSea, levelCoast )
1443
+ ) );
1444
+
1445
+ } )
1446
+ .ElseIf( k.lessThan( levelGrass ), ()=>{
1447
+
1448
+ // sand
1449
+ color.assign( params.colorBeach );
1450
+
1451
+ } )
1452
+ .ElseIf( k.lessThan( levelSand ), ()=>{
1453
+
1454
+ // shallow-sand-grass
1455
+ color.assign( tsl.mix(
1456
+ params.colorBeach,
1457
+ params.colorGrass,
1458
+ tsl.remap( k, levelGrass, levelSand )
1459
+ ) );
1460
+
1461
+ } )
1462
+ .ElseIf( k.lessThan( levelMountain ), ()=>{
1463
+
1464
+ // grass-forest
1465
+ color.assign( tsl.mix(
1466
+ params.colorGrass,
1467
+ params.colorForest,
1468
+ tsl.remap( k, levelSand, levelMountain ).pow( 0.75 )
1469
+ ) );
1470
+
1471
+ } )
1472
+ .Else( ()=>{
1473
+
1474
+ // forest-snow
1475
+ var levelSnow = tsl.mix( 1, levelMountain, params.balanceSnow );
1476
+ color.assign( tsl.mix(
1477
+ params.colorForest,
1478
+ params.colorSnow,
1479
+ tsl.smoothstep( tsl.mix( levelSnow, levelMountain, params.balanceSnow.pow( 0.5 ) ), levelSnow, k )
1480
+ ) );
1481
+
1482
+ } );
1483
+
1484
+ return color;
1485
+
1486
+ } );
1487
+
1488
+
1489
+
1490
+ planet.defaults = {
1491
+ $name: 'Planet',
1492
+
1493
+ scale: 2,
1494
+
1495
+ iterations: 5,
1496
+
1497
+ levelSea: 0.3,
1498
+ levelMountain: 0.7,
1499
+
1500
+ balanceWater: 0.3,
1501
+ balanceSand: 0.2,
1502
+ balanceSnow: 0.8,
1503
+
1504
+ colorDeep: new three.Color( 0x123a59 ).convertLinearToSRGB(), // SteelBlue
1505
+ colorShallow: new three.Color( 0x87CEEB ).convertLinearToSRGB(), // SkyBlue
1506
+ colorBeach: new three.Color( 0xFFFACD ).convertLinearToSRGB(), // LemonChiffon
1507
+ colorGrass: new three.Color( 0x3CB371 ).convertLinearToSRGB(), // MediumSeaGreen
1508
+ colorForest: new three.Color( 0x003000 ).convertLinearToSRGB(), // Dark green
1509
+ colorSnow: new three.Color( 0xF0FFFF ).convertLinearToSRGB(), // Azure
1510
+
1511
+ seed: 0,
1512
+ };
1513
+
1514
+ var goldenRatio = ( 1+5**0.5 )/2;
1515
+
1516
+
1517
+
1518
+ var polkaDots = tsl.Fn( ( params ) => {
1519
+
1520
+ params = prepare( { ...polkaDots.defaults, ...params } );
1521
+
1522
+ var dist = tsl.float( 1 ).toVar();
1523
+
1524
+ tsl.If( params.flat.equal( 1 ), ()=>{
1525
+
1526
+ var cnt = params.count.pow( 2 ).sub( 0.5 ).toVar();
1527
+ var pos = tsl.positionGeometry.xy.mul( cnt ).mul( tsl.mat2( 1, 1, -1, 1 ) );
1528
+ var posTo = pos.round().toVar();
1529
+
1530
+ dist.assign( pos.distance( posTo ).div( cnt ) );
1531
+
1532
+ } ).Else( ()=>{
1533
+
1534
+ var cnt = tsl.pow( 10, params.count ).toVar();
1535
+ var vec = tsl.positionGeometry.normalize().toVar();
1536
+
1537
+ var besti = tsl.oneMinus( vec.y ).mul( cnt ).sub( 1 ).div( 2 );
1538
+
1539
+ var span = tsl.max( 10, cnt.pow( 0.5 ) );
1540
+
1541
+ var mini = besti.sub( span ).floor().clamp( 0, cnt );
1542
+ var maxi = besti.add( span ).floor().clamp( 0, cnt );
1543
+
1544
+ dist.assign( 1 ).toVar();
1545
+
1546
+ tsl.Loop( maxi.sub( mini ), ( { i } )=> {
1547
+
1548
+ var j = tsl.add( i, mini );
1549
+ var theta = tsl.mod( tsl.mul( 2*Math.PI/goldenRatio, j ), 2*Math.PI );
1550
+ var phi = tsl.acos( tsl.oneMinus( tsl.float( j ).mul( 2 ).add( 1 ).div( cnt ) ) );
1551
+ var pnt = spherical( phi, theta );//.normalize();
1552
+ dist.assign( tsl.min( dist, tsl.distance( vec, pnt ) ) );
1553
+
1554
+ } ); // Loop
1555
+
1556
+ } ); // Else
1557
+
1558
+ var size = tsl.exp( params.size.mul( 5 ).sub( 5 ) ).toVar();
1559
+ var blur = params.blur.pow( 4 ).toVar();
1560
+ var k = tsl.smoothstep( size.sub( blur ), size.add( blur ), dist );
1561
+
1562
+ return tsl.mix( params.color, params.background, k );
1563
+
1564
+ } );
1565
+
1566
+
1567
+
1568
+ polkaDots.defaults = {
1569
+ $name: 'Polka dots',
1570
+
1571
+ count: 2,
1572
+ size: 0.5,
1573
+ blur: 0.25,
1574
+
1575
+ color: new three.Color( 0x000000 ),
1576
+ background: new three.Color( 0xFFFFFF ),
1577
+
1578
+ flat: 0,
1579
+ };
1580
+
1581
+ var processedWood = tsl.Fn( ( params )=>{
1582
+
1583
+ params = prepare( { ...processedWood.defaults, ...params } );
1584
+
1585
+ var angle = tsl.radians( params.angle ).toVar();
1586
+ var posLocal = tsl.vec3(
1587
+ tsl.sub( tsl.positionGeometry.x.mul( tsl.cos( angle ) ), tsl.positionGeometry.y.mul( tsl.sin( angle ) ) ),
1588
+ tsl.add( tsl.positionGeometry.x.mul( tsl.sin( angle ) ), tsl.positionGeometry.y.mul( tsl.cos( angle ) ) ),
1589
+ tsl.positionGeometry.z,
1590
+ ).toVar();
1591
+
1592
+ var scale = params.scale.div( 2 ).add( 1 ).toVar();
1593
+ var pos = posLocal.mul( tsl.exp( scale ) ).add( params.seed ).toVar( );
1594
+
1595
+ var len = params.length.add( 5 ).reciprocal().toVar();
1596
+ var k = tsl.mx_noise_float( pos.mul( scale, tsl.vec3( 1, len, len ) ) );
1597
+ k = k.mul( tsl.mx_noise_float( pos.mul( tsl.vec3( 25, 1, 1 ) ) ).add( -1 ).mul( 0.2 ) );
1598
+ k = k.add( params.strength.sub( 0.5 ) ).smoothstep( -0.3, 0.3 ).oneMinus();
1599
+
1600
+ return tsl.mix( params.color, params.background, k );
1601
+
1602
+ } );
1603
+
1604
+
1605
+ processedWood.defaults = {
1606
+ $name: 'Processed wood',
1607
+ $width: 260,
1608
+
1609
+ scale: 2,
1610
+ length: 4,
1611
+ strength: 0.3,
1612
+ angle: 0,
1613
+
1614
+ color: new three.Color( 0x702020 ),
1615
+ background: new three.Color( 0xF0D0A0 ),
1616
+
1617
+ seed: 0,
1618
+ };
1619
+
1620
+ var pnoise = tsl.Fn( ([ pos, fat ])=>{
1621
+
1622
+ return tsl.mx_noise_float( pos ).mul( fat ).clamp( -3.14, 3.14 ).cos().add( 1 ).div( 2 );
1623
+
1624
+ } );
1625
+
1626
+
1627
+
1628
+ var protozoa = tsl.Fn( ( params )=>{
1629
+
1630
+ params = prepare( { ...protozoa.defaults, ...params } );
1631
+
1632
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale.sub( 1 ) ) ).add( params.seed ).toVar( );
1633
+
1634
+ var matcap = tsl.vec3( tsl.matcapUV, tsl.matcapUV.length() ).toVar();
1635
+
1636
+ var rings1 = tsl.float( 0 ).toVar();
1637
+ var rings2 = tsl.float( 0 ).toVar();
1638
+
1639
+ var n1 = tsl.float( 0 ).toVar();
1640
+ var n2 = tsl.float( 0 ).toVar();
1641
+
1642
+ var fat = params.fat.add( 0.2 ).oneMinus().mul( 60 ).add( 30 ).toVar();
1643
+ var scale = tsl.float( 2 ).toVar();
1644
+
1645
+ var dPos = params.amount.div( 2 ).add( 0.5 ).exp().toVar();
1646
+
1647
+ tsl.Loop( 10, ()=>{
1648
+
1649
+ rings1.assign( pnoise( pos.xyz.add( matcap ), fat ) );
1650
+ rings2.assign( pnoise( pos.yzx.add( matcap ), fat ) );
1651
+
1652
+ n1.addAssign( rings1.mul( rings2 ).mul( scale ) );
1653
+ n2.addAssign( rings1.max( rings2 ).mul( scale ) );
1654
+
1655
+ pos.assign( tsl.mix( pos.mul( dPos ), 0, 0.4 ) );
1656
+
1657
+ scale.mulAssign( 0.9 );
1658
+
1659
+ } );
1660
+
1661
+ return tsl.mix( params.background, tsl.mix( params.color, params.subcolor, n2.mul( 0.1 ) ), n1 );
1662
+
1663
+ } );
1664
+
1665
+
1666
+ protozoa.defaults = {
1667
+ $name: 'Protozoa',
1668
+
1669
+ scale: 1.5,
1670
+ fat: 0.7,
1671
+ amount: 0.4,
1672
+
1673
+ color: new three.Color( 0xA0A0A0 ),
1674
+ subcolor: new three.Color( 0xE0E8FF ),
1675
+ background: new three.Color( 0xF0F8FF ),
1676
+
1677
+ seed: 0,
1678
+ };
1679
+
1680
+ var surfacePos$6 = tsl.Fn( ([ pos, params ])=>{
1681
+
1682
+ var zone = selectPlanar( pos, params.selectorAngles, params.selectorCenter, params.selectorWidth );
1683
+
1684
+ var R = matRotYXZ( params.angles.mul( zone ) ),
1685
+ T = matTrans( params.center ),
1686
+ TN = matTrans( params.center.negate() );
1687
+
1688
+ return T.mul( R ).mul( TN ).mul( tsl.vec4( pos, 1 ) ).xyz;
1689
+
1690
+ } );
1691
+
1692
+
1693
+
1694
+ var rotator = tsl.Fn( ( params )=>{
1695
+
1696
+ params = prepare( { ...rotator.defaults, ...params } );
1697
+
1698
+ return surfacePos$6( tsl.positionGeometry, params );
1699
+
1700
+ } );
1701
+
1702
+
1703
+
1704
+ rotator.normal = tsl.Fn( ( params ) => {
1705
+
1706
+ params = prepare( { ...rotator.defaults, ...params } );
1707
+
1708
+ var eps = 0.01;
1709
+
1710
+ var position = tsl.positionGeometry,
1711
+ normal = tsl.normalLocal.normalize().toVar(),
1712
+ tangent = tsl.tangentLocal.normalize().mul( eps ).toVar(),
1713
+ bitangent = tsl.cross( normal, tangent ).normalize().mul( eps ).toVar();
1714
+
1715
+ var pos = surfacePos$6( position, params );
1716
+ var posU = surfacePos$6( position.add( tangent ), params );
1717
+ var posV = surfacePos$6( position.add( bitangent ), params );
1718
+
1719
+ var dU = tsl.sub( posU, pos ),
1720
+ dV = tsl.sub( posV, pos );
1721
+
1722
+ return tsl.transformNormalToView( tsl.cross( dU, dV ).normalize() );
1723
+
1724
+ } );
1725
+
1726
+
1727
+
1728
+ rotator.defaults = {
1729
+ $name: 'Rotator',
1730
+ $positionNode: true,
1731
+ $selectorPlanar: true,
1732
+
1733
+ angles: new three.Vector3( 0.4, -0.6, 0 ),
1734
+ center: new three.Vector3( 0, 0, 0 ),
1735
+
1736
+ selectorCenter: new three.Vector3( 0, 0, 0 ),
1737
+ selectorAngles: new three.Vector2( 0, 0 ),
1738
+ selectorWidth: 2,
1739
+
1740
+ };
1741
+
1742
+ var surfacePos$5 = tsl.Fn( ([ pos, normal, bump, curvature ]) => {
1743
+
1744
+ var k1 = tsl.mx_worley_noise_float( pos.add( tsl.mx_noise_float( pos ).mul( curvature ) ) ).add( 0.8 ).pow( 5 ).toVar();
1745
+ k1.addAssign( k1.pow( 0.5 ) );
1746
+ //k1.addAssign( noise(pos.mul(noiseScale.add(8))).add(1).pow(2).mul(noiseBump) );
1747
+ return pos.add( normal.mul( k1 ).mul( bump ) );
1748
+
1749
+ } );
1750
+
1751
+ var roughClay = tsl.Fn( ( params ) => {
1752
+
1753
+ params = prepare( { ...roughClay.defaults, ...params } );
1754
+
1755
+ var eps = 0.001;
1756
+
1757
+ var bump = params.bump.div( 50 ).toVar();
1758
+
1759
+ var position = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 2 ) ) ).add( params.seed.sin().mul( 10 ) ).toVar( ),
1760
+ normal = tsl.normalLocal.normalize().toVar(),
1761
+ tangent = tsl.tangentLocal.normalize().mul( eps ).toVar(),
1762
+ bitangent = tsl.cross( normal, tangent ).normalize().mul( eps ).toVar();
1763
+
1764
+ var pos = surfacePos$5( position, normal, bump, params.curvature );
1765
+ var posU = surfacePos$5( position.add( tangent ), normal, bump, params.curvature );
1766
+ var posV = surfacePos$5( position.add( bitangent ), normal, bump, params.curvature );
1767
+
1768
+ var dU = tsl.sub( posU, pos ),
1769
+ dV = tsl.sub( posV, pos );
1770
+
1771
+ return tsl.transformNormalToView( tsl.cross( dU, dV ).normalize() );
1772
+
1773
+
1774
+ } );
1775
+
1776
+
1777
+
1778
+ roughClay.defaults = {
1779
+ $name: 'Rough clay',
1780
+ $normalNode: true,
1781
+
1782
+ scale: 2,
1783
+ bump: 0.5,
1784
+ curvature: 0.2,
1785
+
1786
+ seed: 0,
1787
+ };
1788
+
1789
+ var runnyEggs = tsl.Fn( ( params ) => {
1790
+
1791
+ params = prepare( { ...runnyEggs.defaults, ...params } );
1792
+
1793
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 1 ) ) ).add( params.seed.sin().mul( 10 ) ).toVar( );
1794
+
1795
+ var sizeYolk = params.sizeYolk.oneMinus();
1796
+ var sizeWhite = params.sizeWhite.oneMinus();
1797
+
1798
+ var n = tsl.mx_worley_noise_float( pos ).toVar();
1799
+ var whites = n.add( sizeWhite ).pow( 8 ).oneMinus().clamp( -0.5, 1 );
1800
+ var yolks = n.add( sizeYolk ).pow( 18 ).oneMinus().clamp( 0, 1 ).pow( 0.4 ).clamp( 0, 1 );
1801
+
1802
+ return tsl.mix( params.colorBackground, tsl.mix( params.colorWhite, params.colorYolk, yolks ), whites );
1803
+
1804
+ } );
1805
+
1806
+
1807
+ var surfacePos$4 = tsl.Fn( ([ pos, normal, bump, sizeYolk, sizeWhite ]) => {
1808
+
1809
+ var n = tsl.mx_worley_noise_float( pos ).toVar();
1810
+ var whites = n.add( sizeWhite ).pow( 8 ).oneMinus();
1811
+ var yolks = n.add( sizeYolk ).pow( 18 ).oneMinus().clamp( 0, 1 );
1812
+
1813
+ var k = tsl.mix( 0, tsl.mix( 0, 1, yolks ), whites );
1814
+
1815
+ return pos.add( normal.mul( k ).mul( bump ) );
1816
+
1817
+ } );
1818
+
1819
+
1820
+ runnyEggs.normal = tsl.Fn( ( params ) => {
1821
+
1822
+ params = prepare( { ...runnyEggs.defaults, ...params } );
1823
+
1824
+ var eps = 0.001;
1825
+ var bump = 0.05;
1826
+
1827
+ var position = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 1 ) ) ).add( params.seed.sin().mul( 10 ) ).toVar( ),
1828
+ normal = tsl.normalLocal.normalize().toVar(),
1829
+ tangent = tsl.tangentLocal.normalize().mul( eps ).toVar(),
1830
+ bitangent = tsl.cross( normal, tangent ).normalize().mul( eps ).toVar();
1831
+
1832
+ var sizeYolk = params.sizeYolk.oneMinus();
1833
+ var sizeWhite = params.sizeWhite.oneMinus();
1834
+
1835
+ var pos = surfacePos$4( position, normal, bump, sizeYolk, sizeWhite );
1836
+ var posU = surfacePos$4( position.add( tangent ), normal, bump, sizeYolk, sizeWhite );
1837
+ var posV = surfacePos$4( position.add( bitangent ), normal, bump, sizeYolk, sizeWhite );
1838
+
1839
+ var dU = tsl.sub( posU, pos ),
1840
+ dV = tsl.sub( posV, pos );
1841
+
1842
+ return tsl.transformNormalToView( tsl.cross( dU, dV ).normalize() );
1843
+
1844
+ } );
1845
+
1846
+
1847
+ runnyEggs.roughness = tsl.Fn( ( params ) => {
1848
+
1849
+ params = prepare( { ...runnyEggs.defaults, ...params } );
1850
+
1851
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 1 ) ) ).add( params.seed.sin().mul( 10 ) ).toVar( );
1852
+
1853
+ var sizeYolk = params.sizeYolk.oneMinus();
1854
+
1855
+ var n = tsl.mx_worley_noise_float( pos ).toVar();
1856
+ var yolks = n.add( sizeYolk ).pow( 18 ).clamp( 0, 1 );
1857
+
1858
+ return yolks;
1859
+
1860
+ } );
1861
+
1862
+
1863
+ runnyEggs.defaults = {
1864
+ $name: 'Runny eggs',
1865
+
1866
+ scale: 1,
1867
+
1868
+ sizeYolk: 0.2,
1869
+ sizeWhite: 0.7,
1870
+
1871
+ colorYolk: new three.Color( 'orange' ),
1872
+ colorWhite: new three.Color( 'white' ),
1873
+ colorBackground: new three.Color( 'lightgray' ),
1874
+
1875
+ seed: 0,
1876
+ };
1877
+
1878
+ var _rust = tsl.Fn( ( params )=>{
1879
+
1880
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 4 ).add( -1 ) ) ).add( params.seed ).toVar( );
1881
+
1882
+ var amount = params.amount.mul( tsl.mx_noise_float( pos.mul( params.amount.div( 2 ).add( 4 ) ) ).add( 4 ) ).toVar();
1883
+
1884
+ var k = tsl.mx_noise_float( pos ).toVar();
1885
+
1886
+ tsl.Loop( params.iterations, ()=>{
1887
+
1888
+ pos.mulAssign( 2 );
1889
+ k.addAssign( tsl.mx_noise_float( pos ) );
1890
+
1891
+ } );
1892
+
1893
+ k.subAssign( tsl.mx_noise_float( pos.mul( 2 ) ).abs() );
1894
+
1895
+ k.assign( k.sub( amount ).clamp( 0, 15 ) );
1896
+
1897
+ return k;
1898
+
1899
+ } );
1900
+
1901
+
1902
+ var rust = tsl.Fn( ( params )=>{
1903
+
1904
+ params = prepare( { ...rust.defaults, ...params } );
1905
+
1906
+ var k = _rust( params ).mul( 1.25 ).pow( 0.5 );
1907
+
1908
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale.add( params.noiseScale.mul( 3 ), 2 ) ) );
1909
+
1910
+ k.addAssign( params.noise.mul( tsl.mx_noise_float( pos ).abs().add( 0.1 ).pow( 2 ) ) );
1911
+
1912
+ return tsl.mix( params.color, params.background, k );
1913
+
1914
+ } );
1915
+
1916
+
1917
+
1918
+ rust.opacity = tsl.Fn( ( params )=>{
1919
+
1920
+ params = prepare( { ...rust.defaults, ...params } );
1921
+
1922
+ var k = _rust( params ).mul( params.opacity.add( 0.2 ) );
1923
+
1924
+ return k.oneMinus();
1925
+
1926
+ } );
1927
+
1928
+
1929
+ rust.defaults = {
1930
+ $name: 'rust',
1931
+
1932
+ scale: 2,
1933
+ iterations: 8,
1934
+ amount: -0.3,
1935
+ opacity: 0.5,
1936
+ noise: 0.5,
1937
+ noiseScale: 0.5,
1938
+
1939
+ color: new three.Color( 0xC08000 ),
1940
+ background: new three.Color( 0x000020 ),
1941
+
1942
+ seed: 0,
1943
+ };
1944
+
1945
+ var satin = tsl.Fn( ( params ) => {
1946
+
1947
+ params = prepare( { ...satin.defaults, ...params } );
1948
+
1949
+ var pos = tsl.positionGeometry.toVar( );
1950
+
1951
+ var scale = tsl.exp( params.scale.div( 3 ) ).toVar();
1952
+
1953
+ var k = tsl.mx_noise_float(
1954
+ tsl.vec3(
1955
+ tsl.mx_noise_float( tsl.vec3( pos.x.mul( 2 ), pos.y, pos.z ).mul( scale ) ),
1956
+ tsl.mx_noise_float( tsl.vec3( pos.x, pos.y.mul( 2 ), pos.z ).mul( scale ) ),
1957
+ tsl.mx_noise_float( tsl.vec3( pos.x, pos.y, pos.z.mul( 2 ) ).mul( scale ) ),
1958
+ ).mul( scale ).add( params.seed )
1959
+ );
1960
+
1961
+ k = tsl.pow( tsl.abs( k ), 3 ).mul( 20 );
1962
+
1963
+ return tsl.mix( params.background, params.color, k );
1964
+
1965
+ } );
1966
+
1967
+
1968
+
1969
+ satin.defaults = {
1970
+ $name: 'Satin',
1971
+
1972
+ scale: 2,
1973
+
1974
+ color: new three.Color( 0x7080FF ),
1975
+ background: new three.Color( 0x000050 ),
1976
+
1977
+ seed: 0,
1978
+ };
1979
+
1980
+ var surfacePos$3 = tsl.Fn( ([ pos, params ])=>{
1981
+
1982
+ var zone = selectPlanar( pos, params.selectorAngles, params.selectorCenter, params.selectorWidth );
1983
+
1984
+ var S = matScale( tsl.mix( tsl.vec3( 1, 1, 1 ), params.scales, zone ) ),
1985
+ T = matTrans( params.center ),
1986
+ TN = matTrans( params.center.negate() );
1987
+
1988
+ return T.mul( S ).mul( TN ).mul( tsl.vec4( pos, 1 ) ).xyz;
1989
+
1990
+ } );
1991
+
1992
+
1993
+
1994
+ var scaler = tsl.Fn( ( params )=>{
1995
+
1996
+ params = prepare( { ...scaler.defaults, ...params } );
1997
+
1998
+ return surfacePos$3( tsl.positionGeometry, params );
1999
+
2000
+ } );
2001
+
2002
+
2003
+
2004
+ scaler.normal = tsl.Fn( ( params ) => {
2005
+
2006
+ params = prepare( { ...scaler.defaults, ...params } );
2007
+
2008
+ var eps = 0.01;
2009
+
2010
+ var position = tsl.positionGeometry,
2011
+ normal = tsl.normalLocal.normalize().toVar(),
2012
+ tangent = tsl.tangentLocal.normalize().mul( eps ).toVar(),
2013
+ bitangent = tsl.cross( normal, tangent ).normalize().mul( eps ).toVar();
2014
+
2015
+ var pos = surfacePos$3( position, params );
2016
+ var posU = surfacePos$3( position.add( tangent ), params );
2017
+ var posV = surfacePos$3( position.add( bitangent ), params );
2018
+
2019
+ var dU = tsl.sub( posU, pos ),
2020
+ dV = tsl.sub( posV, pos );
2021
+
2022
+ return tsl.transformNormalToView( tsl.cross( dU, dV ).normalize() );
2023
+
2024
+ } );
2025
+
2026
+
2027
+
2028
+ scaler.defaults = {
2029
+ $name: 'Scaler',
2030
+ $positionNode: true,
2031
+ $selectorPlanar: true,
2032
+
2033
+ scales: new three.Vector3( 0.01, 0.9, 1.7 ),
2034
+ center: new three.Vector3( 0, 0, 0 ),
2035
+
2036
+ selectorCenter: new three.Vector3( 0, 0, 0 ),
2037
+ selectorAngles: new three.Vector2( 0, 0 ),
2038
+ selectorWidth: 2,
2039
+
2040
+ };
2041
+
2042
+ var scepterHead = tsl.Fn( ( params ) => {
2043
+
2044
+ params = prepare( { ...scepterHead.defaults, ...params } );
2045
+
2046
+ var pos = tsl.positionGeometry;
2047
+
2048
+ var fx = pos.x.mul( remapExp( params.xFactor, 0, 100, 1.35, 30 ) ).toVar( ),
2049
+ fy = pos.y.mul( remapExp( params.yFactor, 0, 100, 1.35, 30 ) ).toVar( ),
2050
+ fz = pos.z.mul( remapExp( params.zFactor, 0, 100, 1.35, 30 ) ).toVar( );
2051
+
2052
+ var cosX = tsl.cos( fx ).toVar(),
2053
+ cosY = tsl.cos( fy ).toVar(),
2054
+ cosZ = tsl.cos( fz ).toVar();
2055
+
2056
+ var k = tsl.mx_noise_float( tsl.vec3( pos.x.div( cosX ), pos.y.div( cosY ), pos.z.div( cosZ ) ) );
2057
+
2058
+ k = tsl.sign( k ).mul( tsl.abs( k ).pow( 0.75 ) );
2059
+
2060
+ var dx = tsl.abs( tsl.mul( fx, tsl.tan( fx ) ).add( 1 ).div( tsl.cos( fx ) ) ),
2061
+ dy = tsl.abs( tsl.mul( fy, tsl.tan( fy ) ).add( 1 ).div( tsl.cos( fy ) ) ),
2062
+ dz = tsl.abs( tsl.mul( fz, tsl.tan( fz ) ).add( 1 ).div( tsl.cos( fz ) ) );
2063
+
2064
+ var HSL = tsl.vec3().toVar();
2065
+
2066
+ var indexX = ( tsl.abs( tsl.floor( ( fx.mul( 2/Math.PI ).add( 1 ) ).div( 2 ) ) ) ),
2067
+ indexY = ( tsl.abs( tsl.floor( ( fy.mul( 2/Math.PI ).add( 1 ) ).div( 2 ) ) ) ),
2068
+ indexZ = ( tsl.abs( tsl.floor( ( fz.mul( 2/Math.PI ).add( 1 ) ).div( 2 ) ) ) );
2069
+
2070
+ var index = tsl.mod( ( tsl.add( indexX, indexY, indexZ ) ), 2 );
2071
+
2072
+ HSL.assign( toHsl( tsl.mix( params.colorA, params.colorB, index ) ) );
2073
+ var color1 = hsl( HSL.x, HSL.y, HSL.z.mul( k ) ).toVar();
2074
+
2075
+ HSL.assign( toHsl( params.colorRim ) );
2076
+ var color2 = hsl( HSL.x, HSL.y, tsl.mul( 2, k, HSL.z ) ).toVar();
2077
+
2078
+ return tsl.mix( color1, color2, tsl.remapClamp( tsl.max( dx, tsl.max( dy, dz ) ), 55-10, 55+10 ) );
2079
+
2080
+ } );
2081
+
2082
+
2083
+
2084
+ scepterHead.defaults = {
2085
+ $name: 'Scepter head',
2086
+
2087
+ xFactor: 10,
2088
+ yFactor: 22,
2089
+ zFactor: 10,
2090
+
2091
+ colorRim: new three.Color( 0xFFFFFF ),
2092
+ colorA: new three.Color( 0x70E0FF ),
2093
+ colorB: new three.Color( 0x3000FF ),
2094
+ };
2095
+
2096
+ var scream = tsl.Fn( ( params ) => {
2097
+
2098
+ params = prepare( { ...scream.defaults, ...params } );
2099
+
2100
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale ) ).add( params.seed ).toVar( );
2101
+
2102
+ var k = tsl.mx_noise_float( tsl.add( tsl.sin( pos.xyz ), tsl.cos( pos.yzx ) ) );
2103
+
2104
+ pos.assign( tsl.positionGeometry.mul( tsl.exp( params.scale ).mul( k ) ).add( params.seed ) );
2105
+
2106
+ var k = tsl.mx_noise_float( tsl.add( tsl.sin( pos.xyz ), tsl.cos( pos.yzx ) ).mul( 2 ) );
2107
+
2108
+ var col = tsl.mix( params.background, params.color, k ).toVar();
2109
+
2110
+ var HSL = toHsl( col ).toVar();
2111
+
2112
+ return hsl( tsl.add( HSL.x, params.variety.mul( tsl.sin( k.mul( Math.PI ) ) ).mul( 0.5 ) ), HSL.y, HSL.z );
2113
+
2114
+ } );
2115
+
2116
+
2117
+
2118
+ scream.defaults = {
2119
+ $name: 'Scream',
2120
+
2121
+ scale: 2,
2122
+ variety: 1,
2123
+
2124
+ color: new three.Color( 0xF0F060 ),
2125
+ background: new three.Color( 0xD09090 ),
2126
+
2127
+ seed: 0,
2128
+ };
2129
+
2130
+ var simplexNoise = tsl.Fn( ( params ) => {
2131
+
2132
+ params = prepare( { ...simplexNoise.defaults, ...params } );
2133
+
2134
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale ) ).add( params.seed );
2135
+
2136
+ var k = tsl.clamp( 0, 1, tsl.mx_noise_float( pos ).mul( 0.5, tsl.exp( params.contrast ) ).add( 0.5, params.balance ) );
2137
+
2138
+ return tsl.mix( params.background, params.color, k );
2139
+
2140
+ } );
2141
+
2142
+
2143
+
2144
+ simplexNoise.defaults = {
2145
+ $name: 'Simplex noise',
2146
+
2147
+ scale: 2,
2148
+ balance: 0,
2149
+ contrast: 0,
2150
+
2151
+ color: new three.Color( 0xFFFFFF ),
2152
+ background: new three.Color( 0x000000 ),
2153
+
2154
+ seed: 0,
2155
+ };
2156
+
2157
+ var stars = tsl.Fn( ( params ) => {
2158
+
2159
+ params = prepare( { ...stars.defaults, ...params } );
2160
+
2161
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 2 ).add( 3 ) ) ).add( params.seed ).toVar( );
2162
+
2163
+ var k = tsl.abs( tsl.mx_noise_float( pos ) ).pow( 10 ).mul( 10 );
2164
+
2165
+ k = k.mul( tsl.exp( params.density.sub( 2 ) ) );
2166
+
2167
+ var dS = tsl.select( k.greaterThan( 0.1 ), params.variation.mul( tsl.mx_noise_float( pos ) ), 0 );
2168
+
2169
+ var col = toHsl( tsl.mix( params.background, params.color, k ) );
2170
+
2171
+ return hsl( tsl.add( col.x, dS ), col.y, col.z );
2172
+
2173
+ } );
2174
+
2175
+
2176
+
2177
+ stars.defaults = {
2178
+ $name: 'Stars',
2179
+
2180
+ scale: 2,
2181
+ density: 2,
2182
+ variation: 0,
2183
+
2184
+ color: new three.Color( 0xfff5f0 ),
2185
+ background: new three.Color( 0x000060 ),
2186
+
2187
+ seed: 0,
2188
+ };
2189
+
2190
+ var surfacePos$2 = tsl.Fn( ([ pos, params ])=>{
2191
+
2192
+ var exponent = tsl.float( 2 ).pow( params.exponent );
2193
+ var equPos = pos.div( pos.length() ).toVar();
2194
+
2195
+ var p = equPos.x.abs().pow( exponent )
2196
+ .add( equPos.y.abs().pow( exponent ) )
2197
+ .add( equPos.z.abs().pow( exponent ) )
2198
+ .pow( tsl.float( 1 ).div( exponent ) );
2199
+
2200
+ return equPos.div( p );
2201
+
2202
+ } );
2203
+
2204
+
2205
+
2206
+ var supersphere = tsl.Fn( ( params )=>{
2207
+
2208
+ params = prepare( { ...supersphere.defaults, ...params } );
2209
+
2210
+ return surfacePos$2( tsl.positionGeometry, params );
2211
+
2212
+ } );
2213
+
2214
+
2215
+
2216
+ supersphere.normal = tsl.Fn( ( params ) => {
2217
+
2218
+ params = prepare( { ...supersphere.defaults, ...params } );
2219
+
2220
+ var eps = 0.01;
2221
+
2222
+ var position = tsl.positionGeometry,
2223
+ normal = tsl.normalLocal.normalize().toVar(),
2224
+ tangent = tsl.tangentLocal.normalize().mul( eps ).toVar(),
2225
+ bitangent = tsl.cross( normal, tangent ).normalize().mul( eps ).toVar();
2226
+
2227
+ var pos = surfacePos$2( position, params );
2228
+ var posU = surfacePos$2( position.add( tangent ), params );
2229
+ var posV = surfacePos$2( position.add( bitangent ), params );
2230
+
2231
+ var dU = tsl.sub( posU, pos ),
2232
+ dV = tsl.sub( posV, pos );
2233
+
2234
+ return tsl.transformNormalToView( tsl.cross( dU, dV ).normalize() );
2235
+
2236
+ } );
2237
+
2238
+
2239
+
2240
+ supersphere.defaults = {
2241
+ $name: 'Supersphere',
2242
+ $positionNode: true,
2243
+
2244
+ exponent: 3,
2245
+
2246
+ };
2247
+
2248
+ var tigerFur = tsl.Fn( ( params )=>{
2249
+
2250
+ params = prepare( { ...tigerFur.defaults, ...params } );
2251
+
2252
+ var scale = params.scale.div( 2 ).add( 1 ).toVar();
2253
+ var pos = tsl.positionGeometry.mul( tsl.exp( scale ) ).add( params.seed ).toVar( );
2254
+
2255
+ var len = params.length.add( 5 ).reciprocal().toVar();
2256
+ var hairs = params.hairs.mul( 0.3 ).toVar();
2257
+ var k = tsl.mx_noise_float( pos.mul( scale, tsl.vec3( 1, len, len ) ) );
2258
+ k = k.add( tsl.mx_noise_float( pos.mul( tsl.vec3( 25, 1, 1 ) ) ).add( 1 ).mul( hairs ) );
2259
+ k = k.add( params.strength.sub( 0.5 ) ).smoothstep( params.blur.negate(), params.blur ).oneMinus();
2260
+
2261
+ var n = tsl.positionGeometry.y.add( hairs.sub( 0.5 ) ).smoothstep( -1, 0.5 );
2262
+
2263
+ return tsl.mix( params.bottomColor, params.color, n ).mul( k );
2264
+
2265
+ } );
2266
+
2267
+
2268
+ tigerFur.defaults = {
2269
+ $name: 'Tiger fur',
2270
+
2271
+ scale: 2,
2272
+ length: 4,
2273
+ blur: 0.3,
2274
+ strength: 0.3,
2275
+ hairs: 0.5,
2276
+
2277
+ color: new three.Color( 0xFFAA00 ),
2278
+ bottomColor: new three.Color( 0xFFFFEE ),
2279
+
2280
+ seed: 0,
2281
+ };
2282
+
2283
+ var surfacePos$1 = tsl.Fn( ([ pos, params ])=>{
2284
+
2285
+ var zone = selectPlanar( pos, params.selectorAngles, params.selectorCenter, params.selectorWidth );
2286
+
2287
+ var T = matTrans( params.distance.mul( zone ) );
2288
+
2289
+ return T.mul( tsl.vec4( pos, 1 ) ).xyz;
2290
+
2291
+ } );
2292
+
2293
+
2294
+
2295
+ var translator = tsl.Fn( ( params )=>{
2296
+
2297
+ params = prepare( { ...translator.defaults, ...params } );
2298
+
2299
+ return surfacePos$1( tsl.positionGeometry, params );
2300
+
2301
+ } );
2302
+
2303
+
2304
+
2305
+ translator.normal = tsl.Fn( ( params ) => {
2306
+
2307
+ params = prepare( { ...translator.defaults, ...params } );
2308
+
2309
+ var eps = 0.01;
2310
+
2311
+ var position = tsl.positionGeometry,
2312
+ normal = tsl.normalLocal.normalize().toVar(),
2313
+ tangent = tsl.tangentLocal.normalize().mul( eps ).toVar(),
2314
+ bitangent = tsl.cross( normal, tangent ).normalize().mul( eps ).toVar();
2315
+
2316
+ var pos = surfacePos$1( position, params );
2317
+ var posU = surfacePos$1( position.add( tangent ), params );
2318
+ var posV = surfacePos$1( position.add( bitangent ), params );
2319
+
2320
+ var dU = tsl.sub( posU, pos ),
2321
+ dV = tsl.sub( posV, pos );
2322
+
2323
+ return tsl.transformNormalToView( tsl.cross( dU, dV ).normalize() );
2324
+
2325
+ } );
2326
+
2327
+
2328
+
2329
+ translator.defaults = {
2330
+ $name: 'Translator',
2331
+ $positionNode: true,
2332
+ $selectorPlanar: true,
2333
+
2334
+ distance: new three.Vector3( -0.5, 0, 0.2 ),
2335
+
2336
+ selectorCenter: new three.Vector3( 0, 0, 0 ),
2337
+ selectorAngles: new three.Vector2( 0, 0 ),
2338
+ selectorWidth: 0.7,
2339
+
2340
+ };
2341
+
2342
+ var cellCenter = tsl.Fn( ([ cell ])=>{
2343
+
2344
+ return cell.add( tsl.mx_noise_float( cell.mul( Math.PI ) ) );
2345
+
2346
+ } );
2347
+
2348
+
2349
+ var voronoiCells = tsl.Fn( ( params )=>{
2350
+
2351
+ params = prepare( { ...voronoiCells.defaults, ...params } );
2352
+
2353
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 2 ).add( 0.5 ) ) ).add( params.seed ).toVar( );
2354
+
2355
+ var midCell = pos.round().toVar();
2356
+
2357
+ var minCell = midCell.toVar();
2358
+ var minDist = tsl.float( 1 ).toVar();
2359
+
2360
+ var cell = tsl.vec3().toVar();
2361
+ var dist = tsl.float().toVar();
2362
+
2363
+ var i = tsl.float( 0 ).toVar();
2364
+
2365
+ tsl.Loop( 27, () => {
2366
+
2367
+ var ix = i.mod( 3 ).sub( 1 );
2368
+ var iy = i.div( 3 ).floor().mod( 3 ).sub( 1 );
2369
+ var iz = i.div( 9 ).floor().sub( 1 );
2370
+ cell.assign( midCell.add( tsl.vec3( ix, iy, iz ) ) );
2371
+ dist.assign( pos.distance( cellCenter( cell ) ).add( tsl.mx_noise_float( pos ).div( 5 ) ) );
2372
+
2373
+ tsl.If( dist.lessThan( minDist ), ()=>{
2374
+
2375
+ minDist.assign( dist );
2376
+ minCell.assign( cell );
2377
+
2378
+ } );
2379
+ i.addAssign( 1 );
2380
+
2381
+ } );
2382
+
2383
+
2384
+ var n = tsl.mx_noise_float( minCell.mul( Math.PI ) ).toVar();
2385
+ var k = tsl.mix( minDist, n.add( 1 ).div( 2 ), params.facet );
2386
+
2387
+ var color = tsl.mix( params.color, params.background, k ).toVar();
2388
+ var randomColor = tsl.vec3( n.mul( 16.8 ), n.mul( 31.4159 ), n.mul( 27.1828 ) ).sin().add( 1 ).div( 2 );
2389
+
2390
+ return tsl.mix( color, tsl.mix( color, randomColor, params.variation ), params.variation );
2391
+
2392
+ } );
2393
+
2394
+
2395
+
2396
+ voronoiCells.defaults = {
2397
+ $name: 'Voronoi cells',
2398
+
2399
+ scale: 2,
2400
+ variation: 0,
2401
+ facet: 0,
2402
+
2403
+ color: new three.Color( 0 ),
2404
+ background: new three.Color( 0xc0d0ff ),
2405
+
2406
+ seed: 0,
2407
+ };
2408
+
2409
+ var surfacePos = tsl.Fn( ([ pos, normal, bump, density, seed ]) => {
2410
+
2411
+ var k = tsl.mx_noise_float( pos.add( seed ) ).add( density ).clamp( 0, 1 );
2412
+ k = tsl.cos( k.mul( Math.PI ) ).add( 1 ).pow( 0.5 ).toVar();
2413
+
2414
+ return pos.add( k.mul( normal, bump ) );
2415
+
2416
+ } );
2417
+
2418
+
2419
+ var waterDrops = tsl.Fn( ( params ) => {
2420
+
2421
+ params = prepare( { ...waterDrops.defaults, ...params } );
2422
+
2423
+ var eps = 0.001;
2424
+
2425
+ var position = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 1 ).add( 1 ) ) ).toVar( ),
2426
+ normal = tsl.normalLocal.normalize().toVar(),
2427
+ tangent = tsl.tangentLocal.normalize().mul( eps ).toVar(),
2428
+ bitangent = tsl.cross( normal, tangent ).normalize().mul( eps ).toVar();
2429
+
2430
+ var density = tsl.remap( params.density, 0, 1, 1.5, 0.7 ).toVar();
2431
+ var seed = tsl.vec3( tsl.sin( params.seed ).mul( 100 ), tsl.cos( params.seed.div( 2 ) ).mul( 100 ), tsl.sin( params.seed.div( 3 ) ).mul( 100 ) ).toVar();
2432
+
2433
+ var pos = surfacePos( position, normal, params.bump, density, seed );
2434
+
2435
+ var posU = surfacePos( position.add( tangent ), normal, params.bump, density, seed );
2436
+ var posV = surfacePos( position.add( bitangent ), normal, params.bump, density, seed );
2437
+
2438
+ var dU = tsl.sub( posU, pos ),
2439
+ dV = tsl.sub( posV, pos );
2440
+
2441
+ return tsl.transformNormalToView( tsl.cross( dU, dV ).normalize() );
2442
+
2443
+ } );
2444
+
2445
+
2446
+
2447
+ waterDrops.defaults = {
2448
+ $name: 'Water Drops',
2449
+ $normalNode: true,
2450
+
2451
+ scale: 1.4,
2452
+ density: 0.5,
2453
+ bump: 0.6,
2454
+
2455
+ seed: 0,
2456
+ };
2457
+
2458
+ var watermelon = tsl.Fn( ( params )=>{
2459
+
2460
+ params = prepare( { ...watermelon.defaults, ...params } );
2461
+
2462
+ var variation = tsl.select( params.flat, params.variation.mul( 0.85 ).add( 0.15 ), params.variation );
2463
+
2464
+ var pos = tsl.positionGeometry.mul( tsl.exp( params.scale.div( 4 ).add( 2 ) ) ).add( params.seed ).toVar( );
2465
+
2466
+ var uv = tsl.select( params.flat, tsl.screenUV, tsl.equirectUV( tsl.positionGeometry.normalize() ) ).toVar(),
2467
+ a = uv.x.mul( params.stripes.round(), tsl.select( params.flat, Math.PI, 2*Math.PI ) ).add( tsl.mx_noise_float( pos.mul( tsl.vec3( 1, 0.3, 1 ) ) ).mul( 2 ) );
2468
+
2469
+ var k = a.sin().add( 0.5 ).div( 2 ).mul( uv.y.remap( 0, 1, -Math.PI, Math.PI ).cos().add( 1.2 ).clamp( 0, 1 ) )
2470
+ .add( variation.mul( 2, tsl.mx_noise_float( pos.mul( 1.5 ) ).div( 2 ) ) )
2471
+ .add( variation.mul( 2, tsl.mx_noise_float( pos.mul( 4 ) ).div( 6 ) ) )
2472
+ .toVar();
2473
+
2474
+ k.assign(
2475
+ k.mix( k.round(), 0.75 )
2476
+ .add( tsl.mx_noise_float( pos.mul( 2 ) ).mul( params.noise, 0.5 ) )
2477
+ .add( tsl.mx_noise_float( pos.mul( 3 ) ).mul( params.noise, 1 ) )
2478
+ .add( tsl.mx_noise_float( pos.mul( 15 ) ).mul( params.noise, 0.2 ) )
2479
+ .clamp( 0, 1 )
2480
+ );
2481
+
2482
+ var color = tsl.mix( params.background, params.color, k ).toVar();
2483
+
2484
+ return color;
2485
+
2486
+ } );
2487
+
2488
+
2489
+
2490
+ watermelon.defaults = {
2491
+ $name: 'Watermelon',
2492
+
2493
+ scale: 2,
2494
+ stripes: 12,
2495
+ variation: 0.5,
2496
+ noise: 0.25,
2497
+
2498
+ color: new three.Color( 'yellowgreen' ),
2499
+ background: new three.Color( 'darkgreen' ),
2500
+
2501
+ flat: 0,
2502
+
2503
+ seed: 0,
2504
+ };
2505
+
2506
+ var wood = tsl.Fn( ( params ) => {
2507
+
2508
+ params = prepare( { ...wood.defaults, ...params } );
2509
+
2510
+ var angle = tsl.radians( params.angle ).toVar();
2511
+ var posLocal = tsl.vec3(
2512
+ tsl.sub( tsl.positionGeometry.x.mul( tsl.cos( angle ) ), tsl.positionGeometry.y.mul( tsl.sin( angle ) ) ),
2513
+ tsl.add( tsl.positionGeometry.x.mul( tsl.sin( angle ) ), tsl.positionGeometry.y.mul( tsl.cos( angle ) ) ),
2514
+ tsl.positionGeometry.z,
2515
+ ).toVar();
2516
+
2517
+
2518
+ // main pattern with rings
2519
+ var pos = posLocal.mul( tsl.exp( params.scale.sub( 3 ) ).mul( tsl.vec3( tsl.reciprocal( params.length ), 4, tsl.reciprocal( params.length ) ) ) ).add( params.seed ).toVar( );
2520
+ var k = tsl.mx_noise_float( pos ).add( 1 ).mul( 10 ).mul( params.rings );
2521
+ k = k.add( k.cos() ).cos().add( 1 ).div( 2 );
2522
+
2523
+ var kk = tsl.float( 0 ).toVar(),
2524
+ sum = tsl.float( 0 ).toVar(),
2525
+ scale = tsl.exp( params.scale.sub( 2 ) ).mul( tsl.vec3( 1, params.fibersDensity, 1 ) ).toVar(),
2526
+ power = tsl.float( 2 ).toVar();
2527
+
2528
+ tsl.Loop( 10, ()=>{
2529
+
2530
+ kk.addAssign( tsl.mul( power, tsl.mx_noise_float( posLocal.mul( scale ).add( params.seed ) ) ) );
2531
+ sum.addAssign( power );
2532
+ scale.mulAssign( 1.8 );
2533
+ power.mulAssign( 0.6 );
2534
+
2535
+ } );
2536
+
2537
+ kk.assign( tsl.mul( kk, 5 ).div( sum ).mul( 10 ).sin().add( 1 ).div( 2 ) );
2538
+
2539
+ return tsl.mix( params.color, params.background, tsl.mix( k, kk, params.fibers ) );
2540
+
2541
+ } );
2542
+
2543
+
2544
+
2545
+ wood.defaults = {
2546
+ $name: 'Wood',
2547
+ scale: 2.5,
2548
+ rings: 4.5,
2549
+ length: 1,
2550
+ angle: 0,
2551
+ fibers: 0.3,
2552
+ fibersDensity: 10,
2553
+ color: new three.Color( 0.8, 0.4, 0 ),
2554
+ background: new three.Color( 0.4, 0.1, 0 ),
2555
+ seed: 0,
2556
+ };
2557
+
2558
+ var zebraLines = tsl.Fn( ( params ) => {
2559
+
2560
+ params = prepare( { ...zebraLines.defaults, ...params } );
2561
+
2562
+ var pos = tsl.select( params.flat, tsl.positionGeometry, tsl.positionGeometry.normalize() ).toVar( );
2563
+
2564
+ var dir = tsl.select( params.flat, tsl.vec2( tsl.cos( params.phi ), tsl.sin( params.phi ) ), spherical( params.phi, params.theta ) ).toVar();
2565
+
2566
+ var angle = tsl.select( params.flat, tsl.clamp( dir.dot( pos ), -2, 2 ), tsl.acos( tsl.clamp( dir.dot( pos ), -1, 1 ) ) ).toVar();
2567
+
2568
+ var scale = tsl.exp( params.scale.add( 1 ) ).toVar();
2569
+
2570
+ var k = tsl.sin( angle.mul( scale ) ).sub( params.thinness.sub( 0.5 ).mul( 2 ) );
2571
+
2572
+ k = tsl.clamp( k.mul( 1000 ).div( scale ), -1, 1 ).mul( 0.5 ).add( 0.5 );
2573
+
2574
+ return tsl.mix( params.background, params.color, k );
2575
+
2576
+ } );
2577
+
2578
+
2579
+
2580
+ zebraLines.defaults = {
2581
+ $name: 'Zebra lines',
2582
+
2583
+ scale: 2,
2584
+ thinness: 0.5,
2585
+ phi: 0,
2586
+ theta: 0,
2587
+
2588
+ color: new three.Color( 0x0 ),
2589
+ background: new three.Color( 0xFFFFFF ),
2590
+
2591
+ flat: 0,
2592
+ // no seed for zebra lines
2593
+ };
2594
+
2595
+ Object.defineProperty(exports, "noise", {
2596
+ enumerable: true,
2597
+ get: function () { return tsl.mx_noise_float; }
2598
+ });
2599
+ exports.applyEuler = applyEuler;
2600
+ exports.camouflage = camouflage;
2601
+ exports.caveArt = caveArt;
2602
+ exports.circles = circles;
2603
+ exports.clouds = clouds;
2604
+ exports.concrete = concrete;
2605
+ exports.cork = cork;
2606
+ exports.dalmatianSpots = dalmatianSpots;
2607
+ exports.dynamic = dynamic;
2608
+ exports.dysonSphere = dysonSphere;
2609
+ exports.entangled = entangled;
2610
+ exports.fordite = fordite;
2611
+ exports.gasGiant = gasGiant;
2612
+ exports.grid = grid;
2613
+ exports.hideFallbackWarning = hideFallbackWarning;
2614
+ exports.hsl = hsl;
2615
+ exports.isolines = isolines;
2616
+ exports.karstRock = karstRock;
2617
+ exports.marble = marble;
2618
+ exports.matRotX = matRotX;
2619
+ exports.matRotY = matRotY;
2620
+ exports.matRotYXZ = matRotYXZ;
2621
+ exports.matRotZ = matRotZ;
2622
+ exports.matScale = matScale;
2623
+ exports.matTrans = matTrans;
2624
+ exports.neonLights = neonLights;
2625
+ exports.noised = noised;
2626
+ exports.normalVector = normalVector;
2627
+ exports.overlayPlanar = overlayPlanar;
2628
+ exports.photosphere = photosphere;
2629
+ exports.planet = planet;
2630
+ exports.polkaDots = polkaDots;
2631
+ exports.prepare = prepare;
2632
+ exports.processedWood = processedWood;
2633
+ exports.protozoa = protozoa;
2634
+ exports.remapExp = remapExp;
2635
+ exports.rotator = rotator;
2636
+ exports.roughClay = roughClay;
2637
+ exports.runnyEggs = runnyEggs;
2638
+ exports.rust = rust;
2639
+ exports.satin = satin;
2640
+ exports.scaler = scaler;
2641
+ exports.scepterHead = scepterHead;
2642
+ exports.scream = scream;
2643
+ exports.selectPlanar = selectPlanar;
2644
+ exports.showFallbackWarning = showFallbackWarning;
2645
+ exports.simplexNoise = simplexNoise;
2646
+ exports.spherical = spherical;
2647
+ exports.stars = stars;
2648
+ exports.supersphere = supersphere;
2649
+ exports.tigerFur = tigerFur;
2650
+ exports.toHsl = toHsl;
2651
+ exports.translator = translator;
2652
+ exports.vnoise = vnoise;
2653
+ exports.voronoiCells = voronoiCells;
2654
+ exports.waterDrops = waterDrops;
2655
+ exports.watermelon = watermelon;
2656
+ exports.wood = wood;
2657
+ exports.zebraLines = zebraLines;