voxolith

Trees

@voxolith/gen-tree: procedural broadleaf and conifer trees, from one pipeline, with bark, twigs and seasonal foliage.

The five tree presets: oak, maple, birch, spruce and pine

@voxolith/gen-tree grows broadleaf and conifer trees from one pipeline, tuned for tall, detailed models (about 192 voxels) where bark texture and single twigs are visible.

import { seededRandom } from "@voxolith/renderer/core";
import { generateTree, PRESETS } from "@voxolith/gen-tree";

const { entity, stats } = generateTree(PRESETS.oak, seededRandom(42));
// entity.model: a dense, Y-up grid of role indices, anchored at the trunk base

How it works

Skeleton. Branch polylines with radii are grown before any voxel exists. Children start on the parent's axis, so the tree is one connected piece; child radius follows a pipe model, so forks conserve visual mass; direction wobble is coherent noise sampled in space.

Wood. Limbs of at least one voxel radius are rasterised as tapered capsules. Thinner twigs walk their axis with a 3D DDA, which crosses voxel faces and so stays 6-connected.

Bark, surface only. Furrow frequency scales with the local radius, so the wavelength stays constant in voxels as the trunk tapers.

Foliage. Clusters hang off real twigs, not a global envelope, so the crown inherits the irregularity of the branching. A shell hollow throws away buried leaves and a macro carve punches sky holes.

Colour, scored from how far out, how high and how exposed each leaf is, with accents chosen per cluster; then a prune keeps the result a single 6-connected component.

Parameters split into shape and foliage (which voxels exist) and look (which role each voxel gets), so a UI can re-run the cheap colour pass while caching the geometry. Everything measured in voxels is tuned for a 192-tall tree and scales with shape.height.

One tree through the four seasons

Voxel values are role indices (bark.dark, leaf.edge, snow, ...), so one tree is restyled for a season or a biome by palette, without regenerating it. Presets: oak, maple and birch for the broadleaf generator, spruce and pine for the conifer.

Finer scales

At 20, 50 and 100 voxels per metre the leaves, snow and cones refine from the coarse voxels (each leaf voxel becomes a few single leaves, or needles on a conifer, in its own shade), and the wood is redrawn from the skeleton: every segment and root as a thin shell of an exact tapered capsule, flared at the base and thinner above the trunk than the coarse tree could draw it, taking the role of the coarse voxel it falls in (so moss and crevices keep their places) and then fine furrows running up the stem. Leaves, blossom, snow and cones are loose roles. See scales and refinement.

Development

bun run --cwd generators/tree verify             # connectivity, budget, determinism
bun run --cwd generators/tree preview species    # also: skeleton, foliage, bark, shell, resolution, seasons
bun run --cwd generators/tree gen                # bake .vox files into out/
bun generators/tree/tools/debug.ts oak 100       # per-level skeleton report for tuning

Broadleaf

Id
voxolith/tree.broadleaf
Version
0.1.0
Scales
10, 20, 50, 100 voxels per metre

Parameters

Shape

ParameterPathRangeDefault
Height
overall height in voxels (10 per metre); the whole tree scales with it
shape.height32 to 240192
Trunk radius
trunk base radius as a fraction of height; higher is a stouter bole
shape.trunk.radiusRatio0.012 to 0.05, step 0.0010.034
Taper
how the trunk narrows: 1 is a straight cone, lower keeps it thick higher up
shape.trunk.taperExp0.3 to 1.4, step 0.050.55
Lean
most the trunk may lean from vertical, in degrees; the actual lean is random up to this
shape.trunk.leanDeg0 to 12, step 0.53
Sweep
total sideways bend of the trunk from base to top, in degrees
shape.trunk.sweepDeg0 to 20, step 0.57
Root flare
extra radius at the foot as a fraction of the base radius; 0 is a straight stem
shape.trunk.flareGain0 to 1.6, step 0.050.85
Crown start
where the lowest branches leave the trunk, as a fraction of its length; higher is a longer bare bole
shape.crownStartRatio0.05 to 0.8, step 0.010.38
Fork mass
pipe-model exponent; higher keeps child branches thicker where they fork
shape.pipeExp1.8 to 3, step 0.052.2

Foliage

ParameterPathRangeDefault
Foliage
grow leaves or needles; off gives the bare wood skeleton
foliage.enabledyes / noyes
Cluster radius
broadleaf leaf clump radius in voxels at height 192; larger clumps give a fuller, lumpier crown
foliage.clusterRadius2 to 9, step 0.16
Cluster spacing
broadleaf gap between clumps along a twig in voxels at height 192; lower packs them closer
foliage.spacing1 to 8, step 0.12.5
Shell depth
leaves deeper than this below the canopy surface are dropped, in voxels at height 192; 0 keeps a solid crown
foliage.shellDepth0 to 40, step 114
Sky holes
size of the sky holes carved through the canopy; 0 carves none
foliage.macroThreshold0 to 0.6, step 0.010.25

Look

ParameterPathRangeDefault
Season
leaf colours and density; a winter broadleaf is bare with snow on its upper faces
look.seasonspring, summer, autumn, wintersummer
Age
0 young and slender, 1 old: fatter trunk, more gnarl, a higher crown base, drooping limbs
look.age0 to 1, step 0.050.6
Health
1 healthy; lower thins the foliage and turns more of it dead brown
look.health0 to 1, step 0.050.9
Bark furrows
spacing of bark furrows around the trunk in voxels; higher gives broader plates
look.furrowWavelength2 to 10, step 0.55
Moss
moss cover on one side of the lower trunk; 0 is none
look.moss0 to 1, step 0.050.25

Presets

Parameteroakmaplebirch
Height192192192
Trunk radius0.0340.0280.024
Taper0.550.70.8
Lean335
Sweep7710
Root flare0.850.850.4
Crown start0.380.340.42
Fork mass2.22.22.2
Foliageyesyesyes
Cluster radius65.64.4
Cluster spacing2.52.52.5
Shell depth14129
Sky holes0.250.250.22
Seasonsummersummersummer
Age0.60.60.6
Health0.90.90.9
Bark furrows543
Moss0.250.250.05

Roles

Voxel values are these roles, in this order (value 1 is the first). The colours are the defaults; a host maps each role to a palette slot and can restyle it.

  • 1Heartwood wood.heart
  • 2Bark dark bark.dark
  • 3Bark mid bark.mid
  • 4Bark light bark.light
  • 5Moss bark.moss
  • 6Crevice bark.crevice
  • 7Twig twig
  • 8Twig dark twig.dark
  • 9Leaf light leaf.hi · may float when refined
  • 10Leaf mid leaf.mid · may float when refined
  • 11Leaf dark leaf.lo · may float when refined
  • 12Leaf edge leaf.edge · may float when refined
  • 13Leaf accent leaf.accent · may float when refined
  • 14Dead leaf leaf.dead · may float when refined
  • 15Blossom blossom · may float when refined
  • 16Snow snow · may float when refined
  • 17Cone cone · may float when refined

Conifer

Id
voxolith/tree.conifer
Version
0.1.0
Scales
10, 20, 50, 100 voxels per metre

Parameters

Shape

ParameterPathRangeDefault
Height
overall height in voxels (10 per metre); the whole tree scales with it
shape.height32 to 240192
Trunk radius
trunk base radius as a fraction of height; higher is a stouter bole
shape.trunk.radiusRatio0.012 to 0.05, step 0.0010.021
Taper
how the trunk narrows: 1 is a straight cone, lower keeps it thick higher up
shape.trunk.taperExp0.3 to 1.4, step 0.051
Lean
most the trunk may lean from vertical, in degrees; the actual lean is random up to this
shape.trunk.leanDeg0 to 12, step 0.51.5
Sweep
total sideways bend of the trunk from base to top, in degrees
shape.trunk.sweepDeg0 to 20, step 0.53
Root flare
extra radius at the foot as a fraction of the base radius; 0 is a straight stem
shape.trunk.flareGain0 to 1.6, step 0.050.55
Crown start
where the lowest branches leave the trunk, as a fraction of its length; higher is a longer bare bole
shape.crownStartRatio0.05 to 0.8, step 0.010.09
Fork mass
pipe-model exponent; higher keeps child branches thicker where they fork
shape.pipeExp1.8 to 3, step 0.052.8

Foliage

ParameterPathRangeDefault
Foliage
grow leaves or needles; off gives the bare wood skeleton
foliage.enabledyes / noyes
Cluster radius
broadleaf leaf clump radius in voxels at height 192; larger clumps give a fuller, lumpier crown
foliage.clusterRadius2 to 9, step 0.16
Cluster spacing
broadleaf gap between clumps along a twig in voxels at height 192; lower packs them closer
foliage.spacing1 to 8, step 0.12.5
Shell depth
leaves deeper than this below the canopy surface are dropped, in voxels at height 192; 0 keeps a solid crown
foliage.shellDepth0 to 40, step 10
Sky holes
size of the sky holes carved through the canopy; 0 carves none
foliage.macroThreshold0 to 0.6, step 0.010.22

Look

ParameterPathRangeDefault
Season
leaf colours and density; a winter broadleaf is bare with snow on its upper faces
look.seasonspring, summer, autumn, wintersummer
Age
0 young and slender, 1 old: fatter trunk, more gnarl, a higher crown base, drooping limbs
look.age0 to 1, step 0.050.6
Health
1 healthy; lower thins the foliage and turns more of it dead brown
look.health0 to 1, step 0.050.9
Bark furrows
spacing of bark furrows around the trunk in voxels; higher gives broader plates
look.furrowWavelength2 to 10, step 0.54
Moss
moss cover on one side of the lower trunk; 0 is none
look.moss0 to 1, step 0.050.25

Presets

Parametersprucepine
Height192192
Trunk radius0.0210.03
Taper10.8
Lean1.54
Sweep38
Root flare0.550.55
Crown start0.090.55
Fork mass2.82.8
Foliageyesyes
Cluster radius66
Cluster spacing2.52.5
Shell depth00
Sky holes0.220.22
Seasonsummersummer
Age0.60.6
Health0.90.9
Bark furrows46
Moss0.250.25

Roles

Voxel values are these roles, in this order (value 1 is the first). The colours are the defaults; a host maps each role to a palette slot and can restyle it.

  • 1Heartwood wood.heart
  • 2Bark dark bark.dark
  • 3Bark mid bark.mid
  • 4Bark light bark.light
  • 5Moss bark.moss
  • 6Crevice bark.crevice
  • 7Twig twig
  • 8Twig dark twig.dark
  • 9Leaf light leaf.hi · may float when refined
  • 10Leaf mid leaf.mid · may float when refined
  • 11Leaf dark leaf.lo · may float when refined
  • 12Leaf edge leaf.edge · may float when refined
  • 13Leaf accent leaf.accent · may float when refined
  • 14Dead leaf leaf.dead · may float when refined
  • 15Blossom blossom · may float when refined
  • 16Snow snow · may float when refined
  • 17Cone cone · may float when refined

See the API reference for generateTree and the parameter types.

On this page