Grass
@voxolith/gen-grass: ground cover (grass, meadow with flowers, reeds with seed heads, arching ferns, dry grass) as blades that each reach the ground.
@voxolith/gen-grass makes patches of ground cover. A patch is many independent blades, not one
connected object: tufts scatter over a disc, each tuft fans a handful of blades out of the ground,
and every blade is a single stem one voxel thick that bends under its own weight.
import { seededRandom } from "@voxolith/renderer/core";
import { generateGrass, PRESETS } from "@voxolith/gen-grass";
const { entity, stats } = generateGrass(PRESETS.meadow, seededRandom(42));
// entity.kind === "groundcover"; stats.blades, stats.flowers, stats.seedHeadsUnlike a tree, the result is deliberately many pieces. The guarantee is that every blade reaches the ground, which is what the contract's grounding check asks.
How it works
Tufts. Tuft centres scatter over a disc of radius footprint, with a square-rooted radius so
the scatter is even rather than bunched at the centre. Each tuft fans its blades out of a small base
at fanDeg from vertical, at lengths between lengthMin and 1 of height.
Blades. Every blade is a level-0 stem grown by growBranches with no trunk rigidity: gravity
(arc) is the whole silhouette, from standing straight up to arching right over. A fern adds one
level of children in pairs down both sides of the midrib: its leaflets.
Rasterise, recording which blade wrote each voxel. Blades under a voxel radius are DDA lines, 6-connected by construction.
Colour along each blade, dark at the base to light at the tip, per blade rather than per patch. Whole blades dry off, never individual voxels: speckling reads as noise rather than as a dry season.
Heads on the tips of whole blades: flower heads in three colours (flowers) or elongated seed
heads (seedHeads). In winter, snow dusts the top faces.
Prune whatever does not reach the ground, flooding from the whole ground plane rather than from one point, since the blades are independent.
The look comes almost entirely from three things: how far blades splay from vertical (fanDeg), how
hard they arc over (arc), and the gradient along each blade. Voxel values are tuned for a 24-tall
patch and scale with shape.height.
Presets
| preset | character |
|---|---|
grass | a patch of lawn-like tufts |
meadow | taller, more tufts, with flower heads and a few dry blades |
reeds | tall, upright, barely fanned, with seed heads |
fern | arching fronds carrying leaflets down both sides of a midrib |
dry | short, heavily arched, mostly dried off, with small seed heads |
Finer scales
At 20, 50 and 100 voxels per metre the blades are redrawn from the skeleton as thin rods a voxel or two across, rooted and arching like the coarse ones and shaded base to tip from them; flowers become small petal discs and seed heads stay compact. Flowers, seed heads and snow are loose roles. See scales and refinement.
Development
bun run --cwd generators/grass verify # every blade reaches the ground, budget, determinism
bun run --cwd generators/grass preview species # contact sheets into previews/ (also: seeds, seasons)
bun run --cwd generators/grass gen # bake .vox files into out/Grass
voxolith/grass starts from the grass preset.
- Id
voxolith/grass- Version
- 0.1.0
- Scales
- 10, 20, 50, 100 voxels per metre
Parameters
Shape
| Parameter | Path | Range | Default |
|---|---|---|---|
Blade length length of the tallest blade in voxels (10 per metre); shorter blades are a fraction of it | shape.height | 4 to 80 | 24 |
Patch radius radius of the disc the tufts are scattered over, in voxels | shape.footprint | 2 to 48, step 1 | 11 |
Fan how far blades splay from vertical, in degrees; 0 stands them upright | shape.fanDeg | 0 to 60, step 1 | 13 |
Arc downward bend per voxel of blade; 0 is straight, high values arch right over | shape.arc | 0 to 0.12, step 0.002 | 0.012 |
Blade thickness blade radius in voxels; below 1 a blade is a clean one-voxel line | shape.radius | 0.3 to 2, step 0.05 | 0.6 |
Look
| Parameter | Path | Range | Default |
|---|---|---|---|
Season blade colours; winter also dusts the upper faces with snow | look.season | spring, summer, autumn, winter | summer |
Dry blades fraction of whole blades that have dried off to straw | look.dry | 0 to 1, step 0.02 | 0.1 |
Flowers fraction of blades ending in a flower head, in three colours | look.flowers | 0 to 0.6, step 0.01 | 0 |
Seed heads fraction of blades ending in a seed head, as on reeds and cereals | look.seedHeads | 0 to 1, step 0.02 | 0 |
Presets
| Parameter | grass | meadow | reeds | fern | dry |
|---|---|---|---|---|---|
| Blade length | 24 | 30 | 56 | 34 | 22 |
| Patch radius | 11 | 15 | 14 | 12 | 11 |
| Fan | 13 | 16 | 7 | 30 | 22 |
| Arc | 0.012 | 0.014 | 0.004 | 0.01 | 0.032 |
| Blade thickness | 0.6 | 0.6 | 0.65 | 0.7 | 0.6 |
| Season | summer | summer | summer | summer | summer |
| Dry blades | 0.1 | 0.08 | 0.18 | 0.1 | 0.75 |
| Flowers | 0 | 0.14 | 0 | 0 | 0 |
| Seed heads | 0 | 0 | 0.3 | 0 | 0.2 |
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.
- 1Blade base
blade.lo - 2Blade mid
blade.mid - 3Blade tip
blade.hi - 4Dry blade
blade.dry - 5Stalk
stalk - 6Seed head
seed· may float when refined - 7Flower A
flower.a· may float when refined - 8Flower B
flower.b· may float when refined - 9Flower C
flower.c· may float when refined - 10Snow
snow· may float when refined
Meadow
voxolith/meadow starts from the meadow preset.
- Id
voxolith/meadow- Version
- 0.1.0
- Scales
- 10, 20, 50, 100 voxels per metre
Parameters
Shape
| Parameter | Path | Range | Default |
|---|---|---|---|
Blade length length of the tallest blade in voxels (10 per metre); shorter blades are a fraction of it | shape.height | 4 to 80 | 30 |
Patch radius radius of the disc the tufts are scattered over, in voxels | shape.footprint | 2 to 48, step 1 | 15 |
Fan how far blades splay from vertical, in degrees; 0 stands them upright | shape.fanDeg | 0 to 60, step 1 | 16 |
Arc downward bend per voxel of blade; 0 is straight, high values arch right over | shape.arc | 0 to 0.12, step 0.002 | 0.014 |
Blade thickness blade radius in voxels; below 1 a blade is a clean one-voxel line | shape.radius | 0.3 to 2, step 0.05 | 0.6 |
Look
| Parameter | Path | Range | Default |
|---|---|---|---|
Season blade colours; winter also dusts the upper faces with snow | look.season | spring, summer, autumn, winter | summer |
Dry blades fraction of whole blades that have dried off to straw | look.dry | 0 to 1, step 0.02 | 0.08 |
Flowers fraction of blades ending in a flower head, in three colours | look.flowers | 0 to 0.6, step 0.01 | 0.14 |
Seed heads fraction of blades ending in a seed head, as on reeds and cereals | look.seedHeads | 0 to 1, step 0.02 | 0 |
Presets
| Parameter | grass | meadow | reeds | fern | dry |
|---|---|---|---|---|---|
| Blade length | 24 | 30 | 56 | 34 | 22 |
| Patch radius | 11 | 15 | 14 | 12 | 11 |
| Fan | 13 | 16 | 7 | 30 | 22 |
| Arc | 0.012 | 0.014 | 0.004 | 0.01 | 0.032 |
| Blade thickness | 0.6 | 0.6 | 0.65 | 0.7 | 0.6 |
| Season | summer | summer | summer | summer | summer |
| Dry blades | 0.1 | 0.08 | 0.18 | 0.1 | 0.75 |
| Flowers | 0 | 0.14 | 0 | 0 | 0 |
| Seed heads | 0 | 0 | 0.3 | 0 | 0.2 |
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.
- 1Blade base
blade.lo - 2Blade mid
blade.mid - 3Blade tip
blade.hi - 4Dry blade
blade.dry - 5Stalk
stalk - 6Seed head
seed· may float when refined - 7Flower A
flower.a· may float when refined - 8Flower B
flower.b· may float when refined - 9Flower C
flower.c· may float when refined - 10Snow
snow· may float when refined
Fern
voxolith/fern starts from the fern preset. Its leaflets are a branch level in the preset, not a
parameter, so a share code carries the fern's shape by its generator id.
- Id
voxolith/fern- Version
- 0.1.0
- Scales
- 10, 20, 50, 100 voxels per metre
Parameters
Shape
| Parameter | Path | Range | Default |
|---|---|---|---|
Blade length length of the tallest blade in voxels (10 per metre); shorter blades are a fraction of it | shape.height | 4 to 80 | 34 |
Patch radius radius of the disc the tufts are scattered over, in voxels | shape.footprint | 2 to 48, step 1 | 12 |
Fan how far blades splay from vertical, in degrees; 0 stands them upright | shape.fanDeg | 0 to 60, step 1 | 30 |
Arc downward bend per voxel of blade; 0 is straight, high values arch right over | shape.arc | 0 to 0.12, step 0.002 | 0.01 |
Blade thickness blade radius in voxels; below 1 a blade is a clean one-voxel line | shape.radius | 0.3 to 2, step 0.05 | 0.7 |
Look
| Parameter | Path | Range | Default |
|---|---|---|---|
Season blade colours; winter also dusts the upper faces with snow | look.season | spring, summer, autumn, winter | summer |
Dry blades fraction of whole blades that have dried off to straw | look.dry | 0 to 1, step 0.02 | 0.1 |
Flowers fraction of blades ending in a flower head, in three colours | look.flowers | 0 to 0.6, step 0.01 | 0 |
Seed heads fraction of blades ending in a seed head, as on reeds and cereals | look.seedHeads | 0 to 1, step 0.02 | 0 |
Presets
| Parameter | grass | meadow | reeds | fern | dry |
|---|---|---|---|---|---|
| Blade length | 24 | 30 | 56 | 34 | 22 |
| Patch radius | 11 | 15 | 14 | 12 | 11 |
| Fan | 13 | 16 | 7 | 30 | 22 |
| Arc | 0.012 | 0.014 | 0.004 | 0.01 | 0.032 |
| Blade thickness | 0.6 | 0.6 | 0.65 | 0.7 | 0.6 |
| Season | summer | summer | summer | summer | summer |
| Dry blades | 0.1 | 0.08 | 0.18 | 0.1 | 0.75 |
| Flowers | 0 | 0.14 | 0 | 0 | 0 |
| Seed heads | 0 | 0 | 0.3 | 0 | 0.2 |
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.
- 1Blade base
blade.lo - 2Blade mid
blade.mid - 3Blade tip
blade.hi - 4Dry blade
blade.dry - 5Stalk
stalk - 6Seed head
seed· may float when refined - 7Flower A
flower.a· may float when refined - 8Flower B
flower.b· may float when refined - 9Flower C
flower.c· may float when refined - 10Snow
snow· may float when refined
See the API reference for generateGrass and the parameter types.