tsl-textures
Version:
A collection of Three.js Shading Language (TSL) textures
2,088 lines (1,343 loc) • 115 kB
JavaScript
// TSL Textures v3.0.4
import { Fn, vec3, sub, transformNormalToView, cross, remap, pow, mul, log2, min, max, float, add, If, select, sin, cos, rotate, smoothstep, mx_fractal_noise_float, mix, mx_noise_float, time, positionGeometry, or, acos, clamp, exp, normalLocal, tangentLocal, int, Loop, oneMinus, abs, equirectUV, screenSize, exp2, div, round, remapClamp, screenUV, sqrt, mat2, mod, distance, radians, matcapUV, mx_worley_noise_float, sign, tan, floor, screenCoordinate, reciprocal, vec2, mx_worley_noise_vec2, mx_fractal_noise_vec3, mx_worley_noise_vec3, vertexColor, Discard, Switch, positionView } from 'three/tsl';
export { mx_fractal_noise_float as fractal, mx_fractal_noise_vec3 as fractal3, mx_noise_float as noise, mx_noise_vec3 as noise3, mx_worley_noise_float as voronoi, mx_worley_noise_vec2 as voronoi2, mx_worley_noise_vec3 as voronoi3 } from 'three/tsl';
import { Color, Vector3, Vector2 } from 'three';
// simple vector noise, vec3->float[-1,1]
const vnoise = Fn( ([ v ])=>{
return v.dot( vec3( 12.9898, 78.233, -97.5123 ) ).sin().mul( 43758.5453 ).fract().mul( 2 ).sub( 1 );
} ).setLayout( {
name: 'vnoise',
type: 'float',
inputs: [
{ name: 'v', type: 'vec3' },
]
} );
// approximate normal vector given point and two neighbout points
const approximateNormal = Fn( ([ pos, posU, posV ])=>{
var dU = sub( posU, pos ),
dV = sub( posV, pos );
return transformNormalToView( cross( dU, dV ).normalize() );
} ).setLayout( {
name: 'approximateNormal',
type: 'vec3',
inputs: [
{ name: 'pos', type: 'vec3' },
{ name: 'posU', type: 'vec3' },
{ name: 'posV', type: 'vec3' },
]
} );
// exponential version of remap
const remapExp = Fn( ([ x, fromMin, fromMax, toMin, toMax ]) => {
x = remap( x, fromMin, fromMax, 0, 1 );
x = pow( 2, mul( x, log2( toMax.div( toMin ) ) ).add( log2( toMin ) ) );
return x;
} ).setLayout( {
name: 'remapExp',
type: 'float',
inputs: [
{ name: 'x', type: 'float' },
{ name: 'fromMin', type: 'float' },
{ name: 'fromMax', type: 'float' },
{ name: 'toMin', type: 'float' },
{ name: 'toMax', type: 'float' },
]
} );
// show notification that
var banner = null;
var bannerCounter = 10;
async function showFallbackWarning( ) {
if ( navigator.gpu != undefined ) {
var adapter = await navigator.gpu.requestAdapter();
if ( adapter ) return;
}
var html = `
<div style="font-size:1.25em; font-weight:bold;">PLEASE, WAIT</div>
<div style="font-size:0.85em; font-weight:100;" >NO WEBGPU — TRYING WEBGL2</div>
<div id="counter"></div>
`;
banner = document.createElement( 'div' );
banner.innerHTML = html;
banner.style.left = 'calc(50% - 8em)';
banner.style.width = '16em';
banner.style.fontFamily = 'Bahnschrifts, Arial';
banner.style.position = 'absolute';
banner.style.bottom = '20px';
banner.style.padding = '12px 6px';
banner.style.border = '1px solid white';
banner.style.borderRadius = '4px';
banner.style.background = 'rgba(0,0,0,0.5)';
banner.style.color = 'white';
banner.style.textAlign = 'center';
banner.style.opacity = '0.8';
banner.style.outline = 'none';
banner.style.zIndex = '999';
document.body.appendChild( banner );
}
function hideFallbackWarning( ) {
if ( banner ) {
if ( bannerCounter>0 )
bannerCounter--;
else {
banner.style.display = 'none';
banner = null;
}
}
}
// helper function - convert hsl to rgb, ported to TSL from:
// https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative
const hslHelper = Fn( ([ h, s, l, n ])=>{
var k = n.add( h.mul( 12 ) ).mod( 12 );
var a = s.mul( min( l, sub( 1, l ) ) );
return l.sub( a.mul( max( -1, min( min( k.sub( 3 ), sub( 9, k ) ), 1 ) ) ) );
} ).setLayout( {
name: 'hslHelper',
type: 'float',
inputs: [
{ name: 'h', type: 'float' },
{ name: 's', type: 'float' },
{ name: 'l', type: 'float' },
{ name: 'n', type: 'float' },
]
} );
// convert from hsl to rgb
const hsl = Fn( ([ col ]) => {
var h = col.x.fract().add( 1 ).fract();
var s = col.y.clamp( 0, 1 );
var l = col.z.clamp( 0, 1 );
var r = hslHelper( h, s, l, 0 );
var g = hslHelper( h, s, l, 8 );
var b = hslHelper( h, s, l, 4 );
return vec3( r, g, b );
} ).setLayout( {
name: 'hsl',
type: 'vec3',
inputs: [
{ name: 'col', type: 'vec3' },
]
} );
// convert from rgb to hsl
const toHsl = Fn( ([ rgb ]) => {
var R = float( rgb.x ).toVar(),
G = float( rgb.y ).toVar(),
B = float( rgb.z ).toVar();
var mx = max( R, max( G, B ) ).toVar();
var mn = min( R, min( G, B ) ).toVar();
var H = float( 0 ).toVar(),
S = float( 0 ).toVar(),
L = add( mx, mn ).div( 2 );
If( mn.notEqual( mx ), ()=>{
const delta = sub( mx, mn ).toVar();
S.assign( select( L.lessThanEqual( 0.5 ), delta.div( add( mn, mx ) ), delta.div( sub( 2, add( mn, mx ) ) ) ) );
If( mx.equal( R ), ()=>{
H.assign( sub( G, B ).div( delta ).add( select( G.lessThanEqual( B ), 6, 0 ) ) );
} )
.ElseIf( mx.equal( G ), ()=>{
H.assign( sub( B, R ).div( delta ).add( 2 ) );
} )
.Else( ()=>{
H.assign( sub( R, G ).div( delta ).add( 4 ) );
} );
H.divAssign( 6 );
} );
return vec3( H, S, L );
} );
toHsl.setLayout( {
name: 'toHsl',
type: 'vec3',
inputs: [
{ name: 'rgb', type: 'vec3' },
]
} );
const spherical = Fn( ([ phi, theta ]) => {
return vec3(
sin( theta ).mul( sin( phi ) ),
cos( phi ),
cos( theta ).mul( sin( phi ) )
);
} ).setLayout( {
name: 'spherical',
type: 'vec3',
inputs: [
{ name: 'phi', type: 'float' },
{ name: 'theta', type: 'float' },
]
} );
const rotatePivot = Fn( ([ vector, pivot, angle ])=>{
return rotate( vector.sub( pivot ), angle ).add( pivot );
} ).setLayout( {
name: 'rotatePivot',
type: 'vec3',
inputs: [
{ name: 'vector', type: 'vec3' },
{ name: 'pivot', type: 'vec3' },
{ name: 'angle', type: 'vec3' },
]
} );
const selectPlanar = Fn( ([ pos, selAngles, selCenter, selWidth ])=>{
// select zone in a plane through point selCenter,
// rotated according to selAngles and selWidth thick
// result is [0,1] inside plane, 0 below plane, 1 above plane
// C is projected on segment AB
// result is [0,1] inside AB, 0 before A, 1 after B
/* non-optimized version
var s = spherical(selAngles.x,selAngles.y).mul(selWidth).toVar(),
c = pos,
a = selCenter.sub(s.div(2)),
b = selCenter.add(s.div(2));
var ca = a.sub(c),
ab = b.sub(a).toVar();
var caab = ca.dot(s),
abab = ab.dot(ab);
var k = caab.div(abab).negate();
*/
var s = spherical( selAngles.x, selAngles.y ).mul( selWidth ).toVar();
var k = selCenter.sub( s.div( 2 ) ).sub( pos ).dot( s ).div( s.dot( s ) ).negate();
return smoothstep( 0, 1, k );
} ).setLayout( {
name: 'selectPlanar',
type: 'float',
inputs: [
{ name: 'pos', type: 'vec3' },
{ name: 'selAngles', type: 'vec2' },
{ name: 'selCenter', type: 'vec3' },
{ name: 'selWidth', type: 'float' },
]
} );
var defaults$P = {
$name: 'Brain',
position: positionGeometry,
scale: 2,
smooth: 0.5,
wave: 0.5,
speed: 2.5,
time: time,
color: new Color( 0xFFD0D0 ),
background: new Color( 0x500000 ),
seed: 0,
};
var brainRaw = Fn( ([ position, scale, xsmooth, /*wave, speed, time,*/ color, background, seed ])=>{
var pos = position.mul( scale.div( 3 ).exp( ) ).add( seed ).toVar( 'pos' );
var octaves = xsmooth.oneMinus().mul( 2 ).exp( ).toVar( 'octaves' );
var n = mx_fractal_noise_float( pos.mul( 5 ), octaves ).add( 1 ).div( 2 ).clamp( 0, 1 ).pow( 2 );
return mix( color, background, n );
} ).setLayout( {
name: 'brainRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'xsmooth', type: 'float' },
/*{ name: 'wave', type: 'float' },*/
/*{ name: 'speed', type: 'float' },*/
/*{ name: 'time', type: 'float' },*/
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
var brainNormalRaw = Fn( ([ position, scale, xsmooth, wave, speed, time, /*color, background,*/ seed ])=>{
var pos = position.mul( scale.div( 3 ).exp( ) ).add( seed ).toVar( 'pos' );
var octaves = xsmooth.oneMinus().mul( 2 ).exp( ).toVar( 'octaves' );
const EPS = 0.01;
var n = mx_fractal_noise_float( pos.mul( 5 ), octaves ).toVar( 'n' ),
dx = mx_fractal_noise_float( pos.add( vec3( EPS, 0, 0 ) ).mul( 5 ), octaves ).sub( n ).div( EPS ).toVar( 'dx' ),
dy = mx_fractal_noise_float( pos.add( vec3( 0, EPS, 0 ) ).mul( 5 ), octaves ).sub( n ).div( EPS ).toVar( 'dy' );
var dTime = mx_noise_float( pos.mul( wave, 5 ) ).add( 1 ).div( 2 ).mul( 6.28 ).toVar( 'dTime' );
return vec3( dx, dy, time.mul( speed ).add( dTime ).sin().add( n, 1 ) ).normalize();
} ).setLayout( {
name: 'brainNormalRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'xsmooth', type: 'float' },
{ name: 'wave', type: 'float' },
{ name: 'speed', type: 'float' },
{ name: 'time', type: 'float' },
/*{ name: 'color', type: 'vec3' },*/
/*{ name: 'background', type: 'vec3' },*/
{ name: 'seed', type: 'float' },
] }
);
function brain( params={} ) {
var { position, scale, smooth, /*wave, speed, time,*/ color, background, seed } = { ...defaults$P, ...params };
return brainRaw( position, scale, smooth, /*wave, speed, time,*/ color, background, seed );
}
brain.normal = function ( params={} ) {
var { position, scale, smooth, wave, speed, time, /*color, background,*/ seed } = { ...defaults$P, ...params };
return brainNormalRaw( position, scale, smooth, wave, speed, time, /*color, background,*/ seed );
};
brain.defaults = defaults$P;
var defaults$O = {
$name: 'Camouflage',
position: positionGeometry,
scale: 2,
colorA: new Color( 0xc2bea8 ),
colorB: new Color( 0x9c895e ),
colorC: new Color( 0x92a375 ),
colorD: new Color( 0x717561 ),
seed: 0,
};
var camouflageRaw = Fn( ([ position, scale, colorA, colorB, colorC, colorD, seed ])=>{
var pos = position.mul( scale.exp( ) ).add( seed ).toVar( 'pos' );
var color = colorD.toVar( 'color' );
If( mx_noise_float( pos ).greaterThanEqual( 0.3 ), () => {
color.assign( colorA );
}
)
.ElseIf( mx_noise_float( pos.yzx ).greaterThanEqual( 0.2 ), () => {
color.assign( colorB );
}
)
.ElseIf( mx_noise_float( pos.zxy ).greaterThanEqual( 0.1 ), () => {
color.assign( colorC );
}
);
return color;
} ).setLayout( {
name: 'camouflageRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'colorA', type: 'vec3' },
{ name: 'colorB', type: 'vec3' },
{ name: 'colorC', type: 'vec3' },
{ name: 'colorD', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function camouflage( params={} ) {
var { position, scale, colorA, colorB, colorC, colorD, seed } = { ...defaults$O, ...params };
return camouflageRaw( position, scale, colorA, colorB, colorC, colorD, seed );
}
camouflage.defaults = defaults$O;
var defaults$N = {
$name: 'Cave art',
position: positionGeometry,
scale: 2,
thinness: 2,
noise: 0.3,
color: new Color( 0xD34545 ),
background: new Color( 0xFFF8F0 ),
seed: 0,
};
var caveArtRaw = Fn( ([ position, scale, thinness, xnoise, color, background, seed ]) => {
var pos = position.mul( scale.exp( ) ).add( seed ).toVar( 'pos' );
thinness = float( 3 ).sub( thinness ).exp( );
var k1 = mx_noise_float( pos, 4 ).sin().toVar( 'k1' ),
k2 = mx_noise_float( pos.mul( 1.5 ), 4 ).cos().toVar( 'k2' ),
k = thinness.sub( k1.add( k2 ).abs( ).pow2( ).mul( 20 ) ).toVar( 'k' );
If( or( k1.greaterThan( k2 ), k.lessThan( 0 ) ), ()=>{
k.assign( 0 );
} );
If( k.lessThanEqual( 0 ), ()=>{
k.assign( xnoise.mul( mx_noise_float( pos.mul( 30 ) ).pow2( ) ) );
} );
return mix( background, color, k );
} ).setLayout( {
name: 'caveArtRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'thinness', type: 'float' },
{ name: 'xnoise', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function caveArt( params={} ) {
var { position, scale, thinness, noise, color, background, seed } = { ...defaults$N, ...params };
return caveArtRaw( position, scale, thinness, noise, color, background, seed );
}
caveArt.defaults = defaults$N;
var defaults$M = {
$name: 'Circles',
position: positionGeometry,
scale: 2,
variety: 1,
color: new Color( 0xF0E0D0 ),
seed: 0,
};
var circlesRaw = Fn( ([ position, scale, variety, color, seed ]) => {
var pos = position.toVar();
var angle = acos( clamp( pos.y, -1, 1 ) ).mul( 20 );
var x = angle.div( 3000 ).mul( exp( scale.sub( 1 ) ) );
var k = seed.sin().mul( 100 ).toVar();
for ( var n=0; n<=10; n++ ) {
k.addAssign( sin( x.mul( 2**n ).sub( Math.PI*n/2 ) ).mul( -n*( n+1 )/2 ) );
}
k.assign( k.div( 200 ).clamp( -2, 2 ) );
var HSL = toHsl( color );
var hue = HSL.x.add( k.mul( variety ) ).mod( 1 ).mul( 10 );
var huei = hue.floor();
var huef = hue.sub( huei );
huef = select( huef.lessThan( 0.5 ), huef.pow( 1.5 ), huef.pow( 1/1.5 ) );
return hsl( vec3( huei.add( huef ).div( 10 ), HSL.yz ) );
} ).setLayout( {
name: 'circlesRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'variety', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function circles( params={} ) {
var { position, scale, variety, color, seed } = { ...defaults$M, ...params };
return circlesRaw( position, scale, variety, color, seed );
}
circles.defaults = defaults$M;
var defaults$L = {
$name: 'Clouds',
position: positionGeometry,
scale: 2,
density: 0.5,
opacity: 1,
color: new Color( 0xFFFFFF ),
subcolor: new Color( 0xA0A0B0 ),
seed: 0,
};
var cloud_core = Fn( ([ position, scale, density, seed ]) => {
const pos = position.mul( exp( scale.div( 1.5 ).sub( 0.5 ) ) ).add( seed ).toVar( 'pos' );
return mx_fractal_noise_float( pos, 4 ).add( density.remap( 0, 1, -0.5, 1.5 ) );
} ).setLayout( {
name: 'cloud_core',
type: 'float',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'density', type: 'float' },
{ name: 'seed', type: 'float' },
] }
);
var cloudsRaw = Fn( ([ position, scale, density, /*opacity,*/color, subcolor, seed ]) => {
var k = cloud_core( position, scale, density, seed );
return mix( subcolor, color, k.clamp( 0, 1 ) );
} ).setLayout( {
name: 'cloudsRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'density', type: 'float' },
/*{ name: 'opacity', type: 'float' },*/
{ name: 'color', type: 'vec3' },
{ name: 'subcolor', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
var cloudsOpacityRaw = Fn( ([ position, scale, density, opacity, /*color,subcolor,*/seed ]) => {
var k = cloud_core( position, scale, density, seed );
return clamp( 0, 1, mul( k, 2 ).pow( 1.5 ).sub( 1 ).mul( opacity ) );
} ).setLayout( {
name: 'cloudsOpacityRaw',
type: 'float',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'density', type: 'float' },
{ name: 'opacity', type: 'float' },
/*{ name: 'color', type: 'vec3' },*/
/*{ name: 'subcolor', type: 'vec3' },*/
{ name: 'seed', type: 'float' },
] }
);
function clouds( params={} ) {
var { position, scale, density, /*opacity,*/color, subcolor, seed } = { ...defaults$L, ...params };
return cloudsRaw( position, scale, density, /*opacity,*/color, subcolor, seed );
}
clouds.opacity = function ( params={} ) {
var { position, scale, density, opacity, /*color,subcolor,*/seed } = { ...defaults$L, ...params };
return cloudsOpacityRaw( position, scale, density, opacity, /*color,subcolor,*/seed );
};
clouds.defaults = defaults$L;
var defaults$K = {
$name: 'Concrete',
$normalNode: true,
position: positionGeometry,
scale: 2,
density: 0.5,
bump: 0.5,
seed: 0,
};
var surfacePos$7 = Fn( ([ position, normal, density ]) => {
var k = mx_noise_float( position, 0.5, 0.5 ).abs().pow( density );
return position.add( normal.mul( k ) );
} ).setLayout( {
name: 'surfacePos',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'normal', type: 'vec3' },
{ name: 'density', type: 'float' },
] }
);
var concreteRaw = Fn( ([ position, normal, tangent, scale, density, bump, seed ]) => {
const EPS = 0.001;
var seed3d = vec3( 1, 2, 3 ).mul( seed ).sin().mul( 100 ).toVar( 'seed3d' );
var xposition = position.mul( exp( scale.div( 2 ).add( 2 ) ) ).add( seed3d ).toVar( 'xposition' ),
xnormal = normal.normalize().toVar( 'xnormal' ),
xtangent = tangent.normalize().mul( EPS ).toVar( 'xtangent' ),
xbitangent = cross( xnormal, xtangent ).normalize().mul( EPS ).toVar( 'xbitangent' );
var xdensity = remap( density, 0, 1, 10, 0.5 ).toVar( 'xdensity' );
xnormal.mulAssign( bump );
var pos = surfacePos$7( xposition, xnormal, xdensity ).toVar( 'pos' ),
posU = surfacePos$7( xposition.add( xtangent ), xnormal, xdensity ).toVar( 'posU' ),
posV = surfacePos$7( xposition.add( xbitangent ), xnormal, xdensity ).toVar( 'posV' );
return approximateNormal( pos, posU, posV );
} ).setLayout( {
name: 'concreteRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'normal', type: 'vec3' },
{ name: 'tangent', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'density', type: 'float' },
{ name: 'bump', type: 'float' },
{ name: 'seed', type: 'float' },
] }
);
function concrete( params={} ) {
var { position, scale, density, bump, seed } = { ...defaults$K, ...params };
return concreteRaw( position, normalLocal, tangentLocal, scale, density, bump, seed );
}
concrete.defaults = defaults$K;
var defaults$J = {
$name: 'Cork',
position: positionGeometry,
scale: 1,
straight: 1,
noise: 0.3,
color: new Color( 0xfff0c0 ),
background: new Color( 0xd08060 ),
seed: 0,
};
var corkRaw = Fn( ([ position, scale, straight, xnoise, color, background, seed ])=>{
var pos = position.mul( exp( scale.div( 1.5 ).add( 1 ) ) ).add( seed ).toVar( 'pos' );
var midCell = pos.round().toConst( 'midCell' );
var minCell = midCell.toVar( 'minCell' ),
minDist = float( 1 ).toVar( 'minDist' );
var cell = vec3().toVar( 'cell' ),
dist = float().toVar( 'dist' );
var strtaightness = straight.exp().reciprocal().toVar( 'strtaightness' );
var i=int( 0 ).toVar( 'i' ),
j=int( 0 ).toVar( 'j' ),
k=int( 0 ).toVar( 'k' );
// Loop uses hard-coded i, j, k as indices
Loop( 3, 3, 3, () => {
cell.assign( midCell.add( vec3( i, j, k ).sub( 1 ) ) );
var cellCenter = cell.add( vnoise( cell ) );
dist.assign( pos.distance( cellCenter ) );
dist.addAssign( mx_noise_float( pos.add( cell ), strtaightness ) );
If( dist.lessThan( minDist ), ()=>{
minDist.assign( dist );
minCell.assign( cell );
} );
} );
var n = mx_noise_float( minCell.mul( Math.PI ), 0.5, 0.5 ).toVar( 'n' );
var r = mx_noise_float( pos.mul( 12 ) ).toVar( 'r' );
r.mulAssign( r, r );
r.addAssign( mx_noise_float( pos.mul( 40 ), 1/3 ) );
var result = mix( color, background, n.add( r.mul( xnoise ) ) );
return result;
} ).setLayout( {
name: 'camouflageRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'straight', type: 'float' },
{ name: 'xnoise', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function cork( params={} ) {
var { position, scale, straight, noise, color, background, seed } = { ...defaults$J, ...params };
return corkRaw( position, scale, straight, noise, color, background, seed );
}
cork.defaults = defaults$J;
var defaults$I = {
$name: 'Dalmatian spots',
$width: 260,
position: positionGeometry,
scale: 2,
density: 0.6,
color: new Color( 0xFFFFFF ),
background: new Color( 0x000000 ),
seed: 0,
};
var dalmatianSpotsRaw = Fn( ([ position, scale, density, color, background, seed ])=>{
var pos = position.mul( scale.exp( ) ).add( seed ).sub( 1000 ).toVar( 'pos' );
var k = float( 1 ).toVar( 'k' );
var d = float( 1.5 ).sub( density ).mul( 2 ).toVar( 'd' );
var count = density.mul( 5 ).add( 5 ).toVar( 'count' );
Loop( count, ()=> {
k.mulAssign( mx_noise_float( pos ).abs().pow( d ).mul( 100 ).sub( 50 ).clamp( 0, 1 ).oneMinus() );
pos.assign( pos.mul( 1.01 ) );
k.mulAssign( mx_noise_float( pos.yzx ).abs().pow( d ).mul( 100 ).sub( 50 ).clamp( 0, 1 ).oneMinus() );
pos.assign( pos.mul( 1.01 ) );
k.mulAssign( mx_noise_float( pos.zxy ).abs().pow( d ).mul( 100 ).sub( 50 ).clamp( 0, 1 ).oneMinus() );
pos.assign( pos.mul( 1.01 ) );
} );
return mix( background, color, k.clamp( 0, 1 ) );
} ).setLayout( {
name: 'dalmatianSpotsRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'density', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function dalmatianSpots( params={} ) {
var { position, scale, density, color, background, seed } = { ...defaults$I, ...params };
return dalmatianSpotsRaw( position, scale, density, color, background, seed );
}
dalmatianSpots.defaults = defaults$I;
var defaults$H = {
$name: 'Darth Maul',
position: positionGeometry,
scale: 2,
shift: new Vector3( 0, 0, 0 ),
complexity: 0,
angle: 60,
distance: 1.9,
color: new Color( 0xF04040 ),
background: new Color( 0x000000 ),
balance: 0,
seed: 0,
};
var darthMaulRaw = Fn( ([ position, scale, shift, complexity, angle, distance, color, background, balance, seed ]) => {
var xposition = position.add( shift ).mul( exp( scale.div( 1.5 ).sub( 1 ) ) ).sub( shift ).mul( vec3( 1, 1/2, 1/2 ) ).toVar( );
var s = select( position.y.mul( angle.radians().cos() ).add( position.z.mul( angle.radians().sin() ) ).greaterThan( distance ), 1, 0 );
// implement symmetry
xposition.x.assign( xposition.x.add( shift.x ).abs() );
xposition.y.addAssign( seed );
xposition.z.mulAssign( shift.z );
var n = mx_noise_float( xposition ).toVar();
var k = n.sin().mul( n.mul( complexity.mul( 2 ).add( 1 ).exp() ).sin() ).remap( 0, 0.2, 1, -1 ).greaterThan( balance ).select( 0, 1 );
var c = select( xposition.x.greaterThan( mx_noise_float( xposition.mul( 2.3 ) ).abs().mul( 0.5 ).add( 0.02 ) ), 1, 0 );
return mix( background, color, k.mul( s ).mul( c ).clamp( 0, 1 ) );
} ).setLayout( {
name: 'darthMaulRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'shift', type: 'vec3' },
{ name: 'complexity', type: 'float' },
{ name: 'angle', type: 'float' },
{ name: 'distance', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'balance', type: 'float' },
{ name: 'seed', type: 'float' },
] }
);
function darthMaul( params={} ) {
var { position, scale, shift, complexity, angle, distance, color, background, balance, seed } = { ...defaults$H, ...params };
return darthMaulRaw( position, scale, shift, complexity, angle, distance, color, background, balance, seed );
}
darthMaul.defaults = defaults$H;
var defaults$G = {
$name: 'Dyson sphere',
position: positionGeometry,
scale: 2,
complexity: 2,
variation: 0,
color: new Color( 0xc0d0ff ),
background: new Color( 0 ),
seed: 0,
};
var noisea = Fn( ([ pos ])=>{
var p = pos.mul( 5**0.5 ).fract().toVar();
p.addAssign( p.dot( p.add( vec3( 31.4159, 27.1828, 14.142 ) ) ) );
return p.z.mul( p.x.add( p.y ) ).fract().mul( 2 ).sub( 1 );
} ).setLayout( {
name: 'noisea',
type: 'float',
inputs: [
{ name: 'pos', type: 'vec3' },
] }
);
var smoother = Fn( ([ x ])=>{
var t = x.oneMinus().clamp( 0, 1 ).toVar();
return t.mul( t ).mul( float( 3 ).sub( t.mul( 2 ) ) );
} ).setLayout( {
name: 'smoother',
type: 'float',
inputs: [
{ name: 'x', type: 'float' },
] }
);
var noiseg = Fn( ([ pos ])=>{
var minx = pos.x.floor().toVar();
var maxx = minx.add( 1 ).toVar();
var miny = pos.y.floor().toVar();
var maxy = miny.add( 1 ).toVar();
var minz = pos.z.floor().toVar();
var maxz = minz.add( 1 ).toVar();
var dx = smoother( pos.x.fract() ).toVar();
var dy = smoother( pos.y.fract() ).toVar();
var dz = smoother( pos.z.fract() ).toVar();
var mx = smoother( dx.oneMinus() ).toVar();
var my = smoother( dy.oneMinus() ).toVar();
var mz = smoother( dz.oneMinus() ).toVar();
var n000 = noisea( vec3( minx, miny, minz ) ).mul( mx ).mul( my ).mul( mz ).toVar();
var n001 = noisea( vec3( minx, miny, maxz ) ).mul( mx ).mul( my ).mul( dz ).toVar();
var n010 = noisea( vec3( minx, maxy, minz ) ).mul( mx ).mul( dy ).mul( mz ).toVar();
var n011 = noisea( vec3( minx, maxy, maxz ) ).mul( mx ).mul( dy ).mul( dz ).toVar();
var n100 = noisea( vec3( maxx, miny, minz ) ).mul( dx ).mul( my ).mul( mz ).toVar();
var n101 = noisea( vec3( maxx, miny, maxz ) ).mul( dx ).mul( my ).mul( dz ).toVar();
var n110 = noisea( vec3( maxx, maxy, minz ) ).mul( dx ).mul( dy ).mul( mz ).toVar();
var n111 = noisea( vec3( maxx, maxy, maxz ) ).mul( dx ).mul( dy ).mul( dz ).toVar();
return n000.add( n001 ).add( n010 ).add( n011 ).add( n100 ).add( n101 ).add( n110 ).add( n111 );
} ).setLayout( {
name: 'noiseg',
type: 'float',
inputs: [
{ name: 'pos', type: 'vec3' },
] }
);
var dysonSphereRaw = Fn( ([ position, scale, complexity, color, background, seed ])=>{
var pos = position.mul( exp( scale.div( 2 ).add( 0.5 ) ) ).add( seed ).toVar( );
var res = vec3().toVar();
var factor = float( 1 ).toVar();
Loop( complexity.add( 4 ), ()=>{
res.addAssign( noiseg( pos.mul( factor ) ) );
factor.addAssign( factor );
} );
return mix( background, color, res.x.add( 1 ).div( 5 ) );
} ).setLayout( {
name: 'dysonSphereRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'complexity', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function dysonSphere( params={} ) {
var { position, scale, complexity, color, background, seed } = { ...defaults$G, ...params };
return dysonSphereRaw( position, scale, complexity, color, background, seed );
}
dysonSphere.defaults = defaults$G;
var defaults$F = {
$name: 'Entangled',
position: positionGeometry,
scale: 2,
density: 10,
color: new Color( 0x002040 ),
background: new Color( 0xFFFFFF ),
seed: 0,
};
var entangledRaw = Fn( ([ position, scale, density, color, background, seed ]) => {
var xscale = exp( scale.div( 2 ) ).toVar( );
var pos = position.add( seed ).toVar( );
var k = float( -1e4 ).toVar( );
var k1 = float( 0 ).toVar( );
Loop( density, ()=> {
k1.assign( sin( mx_noise_float( mul( pos, xscale ) ).mul( 3*Math.PI ) ) );
k.assign( max( k, k1 ) );
xscale.mulAssign( 1.2 );
} );
k.assign( oneMinus( pow( abs( k ), 5 ) ).mul( 6 ) );
return mix( color, background, k );
} ).setLayout( {
name: 'entangled',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'density', type: 'int' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function entangled( params={} ) {
var { position, scale, density, color, background, seed } = { ...defaults$F, ...params };
return entangledRaw( position, scale, density, color, background, seed );
}
entangled.defaults = defaults$F;
var defaults$E = {
$name: 'Fordite',
position: positionGeometry,
scale: 2,
color: new Color( 0, 0, 0 ),
seed: 0,
};
var forditeRaw = Fn( ([ position, scale, color, seed ]) => {
var pos = position.mul( exp( scale ) ).add( seed ).toVar( );
var k = mx_noise_float(
vec3(
mx_noise_float( pos, 1 ),
mx_noise_float( pos, 2 ),
mx_noise_float( pos, 3 ),
)
).toVar( );
return hsl( vec3(
k,
1,
sin( mul( k, Math.PI, 4 ) ).mul( 0.5 ).add( 0.5 )
) ).add( color );
} ).setLayout( {
name: 'forditeRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function fordite( params={} ) {
var { position, scale, color, seed } = { ...defaults$E, ...params };
return forditeRaw( position, scale, color, seed );
}
fordite.defaults = defaults$E;
var defaults$D = {
$name: 'Gas giant',
position: positionGeometry,
scale: 2,
turbulence: 0.3,
blur: 0.6,
colorA: new Color( 0xFFF8F0 ),
colorB: new Color( 0xF0E8B0 ),
colorC: new Color( 0xAFA0D0 ),
seed: 0,
};
var gasGiantRaw = Fn( ([ position, scale, turbulence, blur, colorA, colorB, colorC, seed ])=>{
var xscale = scale.div( 2 ).add( 1 ).toVar();
var pos = position.mul( exp( xscale ) ).add( seed ).toVar( );
// turbulence strength
var xturbulence = turbulence.mul(
mx_noise_float( vec3( 0, pos.y.mul( 0.5 ), 0 ).add( 1 ) ).add(
mx_noise_float( vec3( 0, pos.y.mul( 1 ), 0 ).add( 1 ) ).mul( 0.5 ),
mx_noise_float( vec3( 1, pos.y.mul( 2 ), 1 ).add( 1 ) ).mul( 0.25 )
)
).mul( 5 ).abs().toVar();
var spot = mx_noise_float( pos.div( 4 ) ).add( 1 ).div( 2 ).pow( 10 ).mul( 10 ).smoothstep( 0, 1 );
// apply turbulence
pos.addAssign( vec3( mx_noise_float( pos ), mx_noise_float( pos.yxz ), mx_noise_float( pos.yzx ) ).mul( xturbulence.mul( spot.mul( 2 ).exp() ) ) );
var xblur = blur.pow( 0.2 ).oneMinus().mul( xturbulence.add( 1 ) ).toVar();
var k = mx_noise_float( pos.mul( vec3( 0, xscale, 0 ) ) );
k = k.add( mx_noise_float( pos.mul( vec3( 1, 15, 1 ) ) ).mul( xblur ) );
k = k.add( -0.5 ).smoothstep( -1, 1 ).oneMinus();
var n = mx_noise_float( vec3( 0, pos.y.mul( 0.75 ), 0 ) ).add( 1 );
var HSL = toHsl( mix( colorB, colorA, n ) );
var color = hsl( vec3( HSL.x.add( mx_noise_float( pos.mul( vec3( 0, xscale, 0 ) ) ).div( 4 ) ), HSL.yz ) ).toVar();
color.assign( mix( color, colorC, xturbulence.mul( 0.3 ) ) );
return color.mul( k );
} ).setLayout( {
name: 'gasGiantRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'turbulence', type: 'float' },
{ name: 'blur', type: 'float' },
{ name: 'colorA', type: 'vec3' },
{ name: 'colorB', type: 'vec3' },
{ name: 'colorC', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function gasGiant( params={} ) {
var { position, scale, turbulence, blur, colorA, colorB, colorC, seed } = { ...defaults$D, ...params };
return gasGiantRaw( position, scale, turbulence, blur, colorA, colorB, colorC, seed );
}
gasGiant.defaults = defaults$D;
var defaults$C = {
$name: 'Grid',
$replaceExportUVS: screenUV,
$replaceExportASP: screenSize.x.div( screenSize.y ).log2(),
uvs: equirectUV( positionGeometry.normalize() ),
countU: 32,
countV: 16,
aspect: 1,
thinness: 0.8,
equirectangular: true,
color: new Color( 0x000000 ),
background: new Color( 0xFFFFFF ),
};
var gridRaw = Fn( ([ uvs, countU, countV, aspect, thinness, equirectangular, color, background ]) => {
var xaspect = max( exp2( aspect ), 1 );
var a = mul( uvs.x, xaspect, Math.PI ).toVar(),
b = mul( uvs.y, Math.PI ).toVar();
var uTo = div( round( mul( uvs.x, countU ) ), countU ),
vTo = div( round( mul( uvs.y, countV ) ), countV ),
aTo = mul( uTo, xaspect, Math.PI ),
bTo = mul( vTo, Math.PI );
var angleU = abs( sub( a, aTo ) ).mul( mix( 1, sin( b ), equirectangular ) ),
angleV = abs( sub( b, bTo ) ),
angle = min( angleU, angleV );
var treshold = mul( min( div( xaspect.mul( Math.PI ), countU ), div( Math.PI, countV ) ), remapClamp( pow( thinness, 0.5 ), 0, 1, 0.9, 0.04 ), 0.5 );
var k = oneMinus( smoothstep( sub( treshold, 0.002 ), add( treshold, 0.002 ), angle ) );
return mix( background, color, k );
} ).setLayout( {
name: 'gridRaw',
type: 'vec3',
inputs: [
{ name: 'uvs', type: 'vec2' },
{ name: 'countU', type: 'float' },
{ name: 'countV', type: 'float' },
{ name: 'aspect', type: 'float' },
{ name: 'thinness', type: 'float' },
{ name: 'equirectangular', type: 'int' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
] }
);
function grid( params={} ) {
var { uvs, countU, countV, aspect, thinness, equirectangular, color, background } = { ...defaults$C, ...params };
return gridRaw( uvs, countU, countV, aspect, thinness, equirectangular, color, background );
}
grid.defaults = defaults$C;
var defaults$B = {
$name: 'Isolines',
position: positionGeometry,
scale: 2,
density: 40,
blur: 0.3,
thinness: 0.6,
color: new Color( 0xFFFFFF ),
background: new Color( 0x000000 ),
seed: 0,
};
var isolinesRaw = Fn( ([ position, scale, density, blur, thinness, color, background, seed ])=>{
var pos = position.mul( exp( scale ) ).add( seed ).toVar( );
var k = mx_noise_float( pos, density );
k = oneMinus( sin( k ) ).div( 2 );
k = smoothstep( sub( thinness, blur ), add( thinness, blur ), k );
return mix( color, background, k );
} ).setLayout( {
name: 'isolinesRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'density', type: 'float' },
{ name: 'blur', type: 'float' },
{ name: 'thinness', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function isolines( params={} ) {
var { position, scale, density, blur, thinness, color, background, seed } = { ...defaults$B, ...params };
return isolinesRaw( position, scale, density, blur, thinness, color, background, seed );
}
isolines.defaults = defaults$B;
var defaults$A = {
$name: 'Karst rock',
position: positionGeometry,
scale: 2,
color: new Color( 0xFFF4F0 ),
background: new Color( 0xD0D0D0 ),
seed: 0,
};
var karstRockRaw = Fn( ([ position, scale, color, background, seed ])=>{
var pos = position.mul( exp( scale ) ).add( seed.sin().mul( 5 ) ).toVar( );
var pos2 = pos.add( mx_noise_float( pos.mul( 2 ) ) ).toVar();
var k = mx_noise_float( pos2 ).div( mx_noise_float( pos2.mul( 1.01 ) ) ).clamp( 0, 2 ).toVar();
k.addAssign( mx_noise_float( pos.mul( 100 ) ).div( 3 ) );
k.addAssign( mx_noise_float( pos.mul( 2 ) ).div( 2 ) );
return mix( background, color, k ).mul( k.pow( 0.1 ) );
} ).setLayout( {
name: 'karstRockRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function karstRock( params={} ) {
var { position, scale, color, background, seed } = { ...defaults$A, ...params };
return karstRockRaw( position, scale, color, background, seed );
}
karstRock.defaults = defaults$A;
var defaults$z = {
$name: 'Marble',
position: positionGeometry,
scale: 1.2,
thinness: 5,
noise: 0.3,
color: new Color( 0x4545D3 ),
background: new Color( 0xF0F8FF ),
seed: 0,
};
var marbleRaw = Fn( ([ position, scale, thinness, xnoise, color, background, seed ]) => {
var pos = position.mul( exp( scale ) ).add( seed ).toVar( );
var k = add(
mx_noise_float( pos ),
mx_noise_float( pos.mul( 2 ) ).mul( 0.5 ),
mx_noise_float( pos.mul( 6 ) ).mul( 0.1 )
);
var k = oneMinus( k.abs().pow( 2.5 ) ).toVar();
var maxSmooth = oneMinus( pow( 0.5, thinness.add( 7 ) ) ).toVar(),
minSmooth = oneMinus( pow( 0.5, thinness.add( 7 ).mul( 0.5 ) ) ).toVar();
If( k.greaterThan( maxSmooth ), ()=>{
k.assign( 1 );
} )
.ElseIf( k.lessThan( minSmooth ), ()=>{
k.assign( 0 );
} )
.Else( ()=> {
var a = k.sub( minSmooth );
var b = maxSmooth.sub( minSmooth );
k.assign( pow( div( a, b ), 5 ).mul( 0.75 ) );
k.assign( k.mul( add( 0.5, mx_noise_float( pos.mul( 2 ) ).mul( 1.5 ) ) ) );
} );
k.assign( k.add( mul( xnoise, mx_noise_float( pos.mul( 150 ) ).abs().pow3() ) ) );
return mix( background, color, k );
} ).setLayout( {
name: 'marbleRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'thinness', type: 'float' },
{ name: 'xnoise', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function marble( params={} ) {
var { position, scale, thinness, noise, color, background, seed } = { ...defaults$z, ...params };
return marbleRaw( position, scale, thinness, noise, color, background, seed );
}
marble.defaults = defaults$z;
var defaults$y = {
$name: 'Neon Lights',
position: positionGeometry,
scale: 2,
thinness: 0.8,
mode: 0, // 0=additive, 1=subtractive
colorA: new Color( 0xFF0000 ),
colorB: new Color( 0x00FF00 ),
colorC: new Color( 0x0000FF ),
background: new Color( 0x000000 ),
seed: 0,
};
var neonLightsRaw = Fn( ([ position, scale, thinness, mode, colorA, colorB, colorC, background, seed ]) => {
var pos = position;
var xscale = exp( scale.remap( 0, 4, -2, 2 ) ).toVar();
var xthinness = exp( thinness.remap( 0, 1, 1.5, 0 ) ).toVar();
var color = background.toVar();
var neon = vec3( 0 ).toVar();
var x = mx_noise_float( pos.xyz ).toVar();
var y = mx_noise_float( pos.yzx ).toVar();
var z = mx_noise_float( pos.zxy ).toVar();
var k = mx_noise_float( vec3( x, y, z ).mul( xscale ).add( seed ) ).toVar();
k.assign( oneMinus( sqrt( abs( k ) ) ).pow( 3 ) );
neon.assign( colorA );
var HSL = toHsl( neon );
neon.assign( hsl( vec3( HSL.xy, HSL.z.mul( k ) ) ) );
color.addAssign( select( mode.equal( 0 ), neon, neon.negate() ).mul( xthinness ) );
k.assign( mx_noise_float( vec3( y, z, x ).mul( xscale ).sub( seed ) ) );
k.assign( oneMinus( sqrt( abs( k ) ) ).pow( 3 ) );
neon.assign( colorB );
var HSL = toHsl( neon );
neon.assign( hsl( vec3( HSL.xy, HSL.z.mul( k ) ) ) );
color.addAssign( select( mode.equal( 0 ), neon, neon.negate() ).mul( xthinness ) );
k.assign( mx_noise_float( vec3( z, x, y.negate() ).mul( xscale ).add( seed ) ) );
k.assign( oneMinus( sqrt( abs( k ) ) ).pow( 3 ) );
neon.assign( colorC );
var HSL = toHsl( neon );
neon.assign( hsl( vec3( HSL.xy, HSL.z.mul( k ) ) ) );
color.addAssign( select( mode.equal( 0 ), neon, neon.negate() ).mul( xthinness ) );
return color;
} ).setLayout( {
name: 'neonLightsRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'thinness', type: 'float' },
{ name: 'node', type: 'float' },
{ name: 'colorA', type: 'vec3' },
{ name: 'colorB', type: 'vec3' },
{ name: 'colorC', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function neonLights( params={} ) {
var { position, scale, thinness, mode, colorA, colorB, colorC, background, seed } = { ...defaults$y, ...params };
return neonLightsRaw( position, scale, thinness, mode, colorA, colorB, colorC, background, seed );
}
neonLights.defaults = defaults$y;
var defaults$x = {
$name: 'Perlin noise',
position: positionGeometry,
scale: 2,
balance: 0,
contrast: 0,
color: new Color( 0xFFFFFF ),
background: new Color( 0x000000 ),
seed: 0,
};
var perlinNoiseRaw = Fn( ([ position, scale, balance, contrast, color, background, seed ]) => {
var pos = position.mul( exp( scale ) ).add( seed );
var k = clamp( 0, 1, mx_noise_float( pos ).mul( 0.5, exp( contrast ) ).add( 0.5, balance ) );
return mix( background, color, k );
} ).setLayout( {
name: 'perlinNoiseRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'balance', type: 'float' },
{ name: 'contrast', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function perlinNoise( params={} ) {
var { position, scale, balance, contrast, color, background, seed } = { ...defaults$x, ...params };
return perlinNoiseRaw( position, scale, balance, contrast, color, background, seed );
}
perlinNoise.defaults = defaults$x;
var defaults$w = {
$name: 'Photosphere',
position: positionGeometry,
scale: 2,
color: new Color( 0xFFFF00 ),
background: new Color( 0xFF0000 ),
seed: 0,
};
var photosphereRaw = Fn( ([ position, scale, color, background, seed ]) => {
var xscale = exp( scale.add( 1 ) ).toVar( );
var pos = position.toVar( );
var vec = vec3( pos ).toVar();
Loop( 6, () => {
vec.assign( rotate( vec, pos.mul( xscale ) ) );
xscale.mulAssign( seed.mul( xscale ).sin().mul( 0.05 ).add( 1.1 ) );
} );
var k = mx_noise_float( vec ).add( 1 ).div( 2 );
return mix( background, color, k );
} ).setLayout( {
name: 'photosphereRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function photosphere( params={} ) {
var { position, scale, color, background, seed } = { ...defaults$w, ...params };
return photosphereRaw( position, scale, color, background, seed );
}
photosphere.defaults = defaults$w;
var defaults$v = {
$name: 'Planet',
position: positionGeometry,
scale: 2,
iterations: 5,
levelSea: 0.3,
levelMountain: 0.7,
balanceWater: 0.3,
balanceSand: 0.2,
balanceSnow: 0.8,
colorDeep: new Color( 0x123a59 ).convertLinearToSRGB(), // SteelBlue
colorShallow: new Color( 0x87CEEB ).convertLinearToSRGB(), // SkyBlue
colorBeach: new Color( 0xFFFACD ).convertLinearToSRGB(), // LemonChiffon
colorGrass: new Color( 0x3CB371 ).convertLinearToSRGB(), // MediumSeaGreen
colorForest: new Color( 0x003000 ).convertLinearToSRGB(), // Dark green
colorSnow: new Color( 0xF0FFFF ).convertLinearToSRGB(), // Azure
seed: 0,
};
var planetRaw = Fn( ([ position, scale, iterations, levelSea, levelMountain, balanceWater, balanceSand, balanceSnow, colorDeep, colorShallow, colorBeach, colorGrass, colorForest, colorSnow, seed ])=>{
var k = float( 0 ).toVar(),
sum = float( 0 ).toVar(),
xscale = exp( scale.sub( 2 ) ).toVar(),
xpower = float( 2 ).toVar();
Loop( iterations.add( 10 ), ()=>{
k.addAssign( mul( xpower, mx_noise_float( position.mul( xscale ).add( seed ) ) ) );
sum.addAssign( xpower );
xscale.mulAssign( 1.5 );
xpower.mulAssign( 0.8 );
} );
k.assign( mul( k, k, 0.5 ).div( sum ) );
var levelSea = levelSea.pow( 2 ).toVar();
var levelMountain = levelMountain.pow( 2 ).toVar();
var levelSand = mix( levelSea, levelMountain, balanceSand ).toVar();
var levelCoast = mix( levelSea, levelSand, 0.4 ).toVar();
var levelGrass = mix( levelSea, levelSand, 0.6 ).toVar();
var color = vec3().toVar();
// process water
If( k.lessThan( levelSea ), ()=>{
// deep-shallow
color.assign( mix(
colorDeep,
colorShallow,
remap( k, 0, levelSea, 0, 1 ).pow( exp( balanceWater.mul( -8 ).add( 4 ) ) )
) );
} )
.ElseIf( k.lessThan( levelCoast ), ()=>{
// shallow-sand
color.assign( mix(
colorShallow,
colorBeach,
remap( k, levelSea, levelCoast )
) );
} )
.ElseIf( k.lessThan( levelGrass ), ()=>{
// sand
color.assign( colorBeach );
} )
.ElseIf( k.lessThan( levelSand ), ()=>{
// shallow-sand-grass
color.assign( mix(
colorBeach,
colorGrass,
remap( k, levelGrass, levelSand )
) );
} )
.ElseIf( k.lessThan( levelMountain ), ()=>{
// grass-forest
color.assign( mix(
colorGrass,
colorForest,
remap( k, levelSand, levelMountain ).pow( 0.75 )
) );
} )
.Else( ()=>{
// forest-snow
var levelSnow = mix( 1, levelMountain, balanceSnow );
color.assign( mix(
colorForest,
colorSnow,
smoothstep( mix( levelSnow, levelMountain, balanceSnow.pow( 0.5 ) ), levelSnow, k )
) );
} );
return color;
} ).setLayout( {
name: 'planetRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'scale', type: 'float' },
{ name: 'iterations', type: 'int' },
{ name: 'levelSea', type: 'float' },
{ name: 'levelMountain', type: 'float' },
{ name: 'balanceWater', type: 'float' },
{ name: 'balanceSand', type: 'float' },
{ name: 'balanceSnow', type: 'float' },
{ name: 'colorDeep', type: 'vec3' },
{ name: 'colorShallow', type: 'vec3' },
{ name: 'colorBeach', type: 'vec3' },
{ name: 'colorGrass', type: 'vec3' },
{ name: 'colorForest', type: 'vec3' },
{ name: 'colorSnow', type: 'vec3' },
{ name: 'seed', type: 'float' },
] }
);
function planet( params={} ) {
var { position, scale, iterations, levelSea, levelMountain, balanceWater, balanceSand, balanceSnow, colorDeep, colorShallow, colorBeach, colorGrass, colorForest, colorSnow, seed } = { ...defaults$v, ...params };
return planetRaw( position, scale, iterations, levelSea, levelMountain, balanceWater, balanceSand, balanceSnow, colorDeep, colorShallow, colorBeach, colorGrass, colorForest, colorSnow, seed );
}
planet.defaults = defaults$v;
var defaults$u = {
$name: 'Polka dots',
position: positionGeometry,
count: 2,
size: 0.5,
blur: 0.25,
color: new Color( 0x000000 ),
background: new Color( 0xFFFFFF ),
flat: 0,
};
var goldenRatio = ( 1+5**0.5 )/2;
var polkaDotsRaw = Fn( ([ position, count, size, blur, color, background, xflat ]) => {
var dist = float( 1 ).toVar();
If( xflat.equal( 1 ), ()=>{
var cnt = count.pow( 2 ).sub( 0.5 ).toVar();
var pos = position.xy.mul( cnt ).mul( mat2( 1, 1, -1, 1 ) );
var posTo = pos.round().toVar();
dist.assign( pos.distance( posTo ).div( cnt ) );
} ).Else( ()=>{
var cnt = pow( 10, count ).toVar();
var vec = position.normalize().toVar();
var besti = oneMinus( vec.y ).mul( cnt ).sub( 1 ).div( 2 );
var span = max( 10, cnt.pow( 0.5 ) );
var mini = besti.sub( span ).floor().clamp( 0, cnt );
var maxi = besti.add( span ).floor().clamp( 0, cnt );
dist.assign( 1 ).toVar();
Loop( maxi.sub( mini ), ( { i } )=> {
var j = add( i, mini );
var theta = mod( mul( 2*Math.PI/goldenRatio, j ), 2*Math.PI );
var phi = acos( oneMinus( float( j ).mul( 2 ).add( 1 ).div( cnt ) ) );
var pnt = spherical( phi, theta );//.normalize();
dist.assign( min( dist, distance( vec, pnt ) ) );
} ); // Loop
} ); // Else
var xsize = exp( size.mul( 5 ).sub( 5 ) ).toVar();
var xblur = blur.pow( 4 ).toVar();
var k = smoothstep( xsize.sub( xblur ), xsize.add( xblur ), dist );
return mix( color, background, k );
} ).setLayout( {
name: 'polkaDotsRaw',
type: 'vec3',
inputs: [
{ name: 'position', type: 'vec3' },
{ name: 'count', type: 'float' },
{ name: 'size', type: 'float' },
{ name: 'blur', type: 'float' },
{ name: 'color', type: 'vec3' },
{ name: 'background', type: 'vec3' },
{ name: 'xflat', type: 'int' },
] }
);
function polkaDots( params={} ) {
var { position, count, size, blur, color, background, flat } = { ...defaults$u, ...params };
return polkaDotsRaw( position, count, size, blur, color, background, flat );
}
polkaDots.defaults = defaults$u;
var defaults$t = {
$name: 'Processed wood',
$width: 260,
position: positionGeometry,
scale: 2,
lengths: 4,
strength: 0.3,
angle: 0,
color: new Color( 0x702020 ),
background: new Color( 0xF0D0A0 ),
seed: 0,
};
var processedWoodRaw = Fn( ([ position, scale, lengths, strength, angle, color, background, seed ])=>{
var angle = radians( angle ).toVar();
var posLocal = vec3(
sub( position.x.mul( cos( angle ) ), position.y.mul( sin( angle ) ) ),
add( position.x.mul( sin( angle ) ), position.y.mul( cos( angle ) ) ),
position.z,
).toVar();
var xscale = scale.div( 2 ).add( 1 ).toVar();
var pos = posLocal.mul( exp( scale ) ).add( seed ).toVar( );
var len = lengths.add( 5 ).reciprocal().toVar();
var k = mx_noise_float( pos.mul( xscale, vec3( 1, l