Growing from a seed

Two nodes write the expression for you. Evolve assembles one from a number and a set of weights; Mutate takes what exists and drifts it.

Everything on The Expression language assumes you are typing. These two nodes do not change the language, they author in it. Evolve builds a small tree out of the same ingredients an Expression can call, and Mutate rewrites a tree it is handed. What comes out is an ordinary field or an ordinary analytic shape, so the rest of the graph cannot tell it was generated.

Generate random procedural expressions or shape compositions from a seed and palette.

Seed, palette, depth

A seed is a number. The same seed with the same weights always assembles the same thing, so a seed is a coordinate rather than a dice roll: change it to browse, keyframe it to walk, and come back to it to get the result again.

depth is a growth budget rather than a literal count. The tree picks an ingredient at each level, so raising it tends towards more layered results without promising a fixed structure.

Every palette entry is a weight, not a tick. 0 rules an ingredient out; anything above that is a share of the draw. Two entries at 1 come up about equally, 2 against 1 about twice as often, and raising one does not demote the rest. What that means in practice is that a low weight is a frequency and not a guarantee: at noise = 0.2 some seeds draw a noise leaf and some do not, so raise the weight until it appears rather than expecting one per seed.

The categories overlap on purpose, and where they overlap the shares add. tiling_ops weights the repeat move on its own while sharp already carries a share of it, so sharp = 1 with tiling_ops = 1 gives the repeat operator more of the pool than either number reads like alone. Raise tiling_ops to get repeating motifs without dragging the rest of the graphic vocabulary along.

With every weight at 0 there is nothing to draw from, and the result falls back to a single sine wave.

What grows follows the mode

mode is Expression or Shape, and the palette on the node changes with it.

Expression grows a field. outputs picks its valence: Scalar for a mask or a displacement, RGB or RGBA for a colour field, each channel grown as its own independent sub-tree from the same seed. frequency sets the feature size, and at its default of 0.02 the pattern reads at about the same scale as a Noise node beside it, features around 50 units across. periodic, smooth, sharp, tiling_ops and noise weight the ingredient families; arithmetic weights combining two branches against wrapping one, so it decides how bushy the tree gets rather than what it looks like.

Shape grows a solid instead, at a usable size, comparable to a Sphere or a Cube. sphere, cube, torus, cylinder, cone and superquadric weight the primitives, boolean_ops is Shape's version of arithmetic, and displaced, offset_ops and repeat_ops weight the three ways one shape is modified: noise on the surface, a uniform shell, and infinite repetition.

distance_input is a plain switch rather than a weight, because there is no honest amount of it to dial. On, distance from the centre joins the ingredients and results read as more radially symmetric. Off, nothing biases the result towards a centre.

A Shape composition can hang the GPU. At least one seed at depth 6 does it on most runs and the cause is not yet known, and a hang of this kind is not recoverable by quitting the app. Save before sweeping Seed in Shape mode, and leave Expression mode selected while you work on the rest of the graph.

Your own building blocks

Raise palette_count and each new socket appears with a palette_weight beside it, in the same currency as the built-in categories: a wired field at 2 against periodic at 1 is drawn about twice as often. Set a weight to 0 to mute a slot without unwiring it. The weight belongs to the socket, so leaving a gap in the middle of the list does not renumber the others.

Wire fields there, not shapes. The sockets accept any value, and a pin that accepts anything turns off automatic conversion, so a shape wired into one is a cook error naming the mismatch rather than a conversion. In Shape mode the custom palette is not consulted at all: the weights disappear from the node while the sockets stay, and anything wired to them is dropped without a message.

ParameterTypeDefaultWhat it does
modeString"Expression"Expression: procedural field output. Shape: analytical 3D geometry. One of: Expression, Shape.
seedNumber42Random seed — same seed + same palette = same output
depthNumber4Composition depth — higher = more complex structures
periodicNumber1How often periodic operators are drawn: sin, cos, triangle wave, sawtooth. 0 = never
smoothNumber1How often smooth operators are drawn: tanh, sigmoid, gaussian. 0 = never
sharpNumber0How often sharp operators are drawn: abs, sign, floor, fract. 0 = never
arithmeticNumber1How often two branches are COMBINED (add, multiply) instead of one being wrapped — the tree's bushiness. 0 = never
tiling_opsNumber0How often the tiling operator (fract — repeating patterns) is drawn. Adds to `sharp`'s share of it. 0 = never
noiseNumber0How often a procedural noise or Voronoi generator is drawn as a new leaf. 0 = never
outputsString"Scalar"Output valence: Scalar (grayscale field), RGB, or RGBA colour field. Each channel evolves as an independent sub-tree from a seed offset. One of: Scalar, RGB, RGBA.
distance_inputBooleantrueAdd distance-to-center (D) as an implicit input — produces more symmetric patterns
frequencyNumber0.020Pattern frequency — higher = smaller features. 0.02 ≈ 50-unit features.
sphereNumber1How often spheres are drawn from the shape palette. 0 = never
torusNumber1How often tori are drawn from the shape palette. 0 = never
cubeNumber1How often boxes are drawn from the shape palette. 0 = never
cylinderNumber0How often cylinders are drawn from the shape palette. 0 = never
coneNumber0How often cones are drawn from the shape palette. 0 = never
superquadricNumber1How often superquadrics are drawn from the shape palette. 0 = never
boolean_opsNumber1How often two shapes are combined (union/intersect/subtract) rather than one being wrapped. 0 = never
displacedNumber1How often noise-based surface displacement is applied. 0 = never
offset_opsNumber0How often a uniform shell offset is applied. 0 = never
repeat_opsNumber0How often infinite tiling repetition is applied. 0 = never
palette_countNumber0Number of custom palette inputs — wire in Fields or Shapes as building blocks
opacityNumber1Layer opacity (0 = transparent, 1 = opaque). Editable, wirable, keyframable.

Drifting what already exists

Mutate takes an expression field or an analytic shape on input and rewrites it. It is the same vocabulary and the same weight currency, applied to a tree that already exists rather than an empty one.

mutations is how many rewriting steps each variant takes and severity is how far a numeric constant is allowed to jump, so a low severity over many steps drifts and a high severity over one jumps. Six weights choose what each step does: grow_weight adds an operator above what is there, replace_weight swaps one operator for another, tweak_weight moves constants, prune_weight removes an operator, regrow_weight throws a subtree away and grows a fresh one, and graft_weight transplants a subtree from a donor.

Donors come from graft_count, which grows a set of sockets the same way Evolve's palette does. A donor has to be self-contained to be transplantable: an image, a volume, or an Evolve field that has its own wired palette cannot be lifted out of its context, and grafting from one is a silent no-op however high graft_weight goes. An ordinary generated field or shape grafts.

count above 1 returns several variants at once as a list. A list of fields has no viewport handler, so the viewport goes blank rather than showing the first one: pick a variant out of the list before looking at it, and put an index between Mutate and Mutate if you want to keep drifting one of them.

ParameterTypeDefaultWhat it does
inputField or CollectionExpression field or CRC shape to mutate
seedNumber42Random seed for mutation
countNumber1Number of variant outputs (1 = single, N = list of variants)
mutationsNumber3Number of mutation steps per variant
severityNumber0.300Parameter jitter magnitude (higher = larger changes to constants)
grow_weightNumber1Weight for growing the tree (adding operators above existing nodes)
replace_weightNumber1Weight for replacing operators with different ones
tweak_weightNumber1.500Weight for tweaking numeric parameters (constants, slopes, radii)
graft_weightNumber0.500Weight for grafting subtrees from graft sources
prune_weightNumber0.300Weight for pruning (removing operators, simplifying)
regrow_weightNumber0.300Weight for regrowing (replacing subtrees with fresh random ones)
periodicNumber1How often periodic operators are introduced: sin, cos, triangle wave, sawtooth. 0 = never
smoothNumber1How often smooth operators are introduced: tanh, sigmoid, gaussian. 0 = never
sharpNumber0How often sharp operators are introduced: abs, sign, floor, fract. 0 = never
arithmeticNumber1How often two branches are COMBINED (add, multiply) instead of one being wrapped — the tree's bushiness. 0 = never
tiling_opsNumber0How often the tiling operator (fract — repeating patterns) is introduced. Adds to `sharp`'s share of it. 0 = never
sphereNumber1How often a mutation introduces a sphere. 0 = never
cubeNumber1How often a mutation introduces a box. 0 = never
torusNumber1How often a mutation introduces a torus. 0 = never
cylinderNumber0How often a mutation introduces a cylinder. 0 = never
coneNumber0How often a mutation introduces a cone. 0 = never
superquadricNumber1How often a mutation introduces a superquadric. 0 = never
boolean_opsNumber1How often a mutation combines two shapes (union/intersect/subtract) rather than wrapping one. 0 = never
displacedNumber1How often a mutation introduces noise-based surface displacement. 0 = never
offset_opsNumber0How often a mutation introduces a uniform shell offset. 0 = never
repeat_opsNumber0How often a mutation introduces infinite tiling repetition. 0 = never
graft_countNumber0Number of graft source inputs — wire in Fields or Shapes as cross-pollination donors
opacityNumber1Layer opacity (0 = transparent, 1 = opaque). Editable, wirable, keyframable.

See also