Language Fundamentals
Recipe files are indentation-based documents made from declarations, named blocks, fields, and scalar expressions. They are data, not unrestricted scripts: recipes cannot loop arbitrarily, access the filesystem, or mutate gameplay state.
Document kinds
A document contains one of the following root kinds:
- one
Tiledeclaration; - one or more
Material <id>declarations; or - one or more
Sdf <id>declarations.
Root kinds cannot be mixed in one file. Keeping them separate lets each consumer request a clear output contract while sharing the same procedural vocabulary.
Syntax rules
- Use the
.recipeextension. - Indent blocks with spaces. Tabs are rejected.
//starts a line comment.- Block and field names are case-insensitive.
- Strings use double quotes.
- Booleans are
trueandfalse. I2(x, y)is an integer pair andF2(x, y)is a floating-point pair.- Unknown fields, unknown references, duplicate definitions, and cyclic scalar references are errors.
// One named field feeding another block.
Noise Grain
type = Gradient
scale = F2(8.0, 8.0)
Value Face
source = Smoothstep(0.2, 0.8, Grain)
Scalar expressions
Scalar fields are shared by Tile height, pattern masks, material channels, and color mixing.
source = Clamp(Stones.height * 0.85 + Grain * 0.15, 0.0, 1.0)
Expressions support:
- literals, parentheses, and
+,-,*,/; - named
Noise,Height, andValuefields; - pattern channels such as
Stones.height,Stones.edge, andStones.center; - normalized coordinates
U,V,Radius, andAngle; - functions including
Abs,Invert,Sin,Cos,Fract,Sqrt,Min,Max,Pow,Clamp,Mix,Smoothstep,Random, andWave.
Final output channels are clamped to 0..1. Division by zero evaluates to zero.
Noise and patterns
Noise creates reusable scalar variation. Its root seed, local seed, scale, fractal, octave count, and persistence make the result deterministic.
Noise Wear
type = Gradient
fractal = Ridged
scale = F2(9.0, 9.0)
octaves = 3
persistence = 0.48
seed = 3
Implemented noise kinds are Value and Gradient; Perlin aliases Gradient. Implemented fractals are FBm, Ridged, Billow, and Turbulence.
Pattern divides a domain into stable units. Implemented generators are Bricks, Voronoi, and Discs. They expose .height, .edge, .center, and a stable .id for keyed variation.
Coordinate domains
Recipes normally evaluate in normalized U and V coordinates. A consumer maps its surface into that domain.
Globalevaluates continuously over the complete target.<Pattern>.localrestarts coordinates within every unit of that pattern.- Avatar bindings additionally choose how the consumer constructs the target surface before the material is evaluated.
Domain selection is what lets a stone vary independently per Voronoi cell or a wood material restart inside every plank without hard-coding a special stone or wood shader.
Wrapping and tiling
Root wrap accepts:
| Mode | Behavior |
|---|---|
Clamp | Hold sampling at the closest outer edge. |
Repeat | Wrap both axes seamlessly. |
Mirror | Reflect alternate repetitions. |
Consumer bindings may also provide a tiling value. Tiling scales coordinates before the recipe's wrapping mode is applied. Values above 1 repeat more often; positive values below 1 enlarge the authored repeat.
Determinism
A recipe produces the same result for the same source, palette, root seed, render options, and consumer mapping. Use:
- the root
seedfor the overall result; - per-block
seedvalues to decorrelate operations; - stable pattern
.idvalues withRandomorkey; - consumer-provided seed offsets for stable per-item variants.
Do not derive important variation from frame order or wall-clock time. Animation is explicit through an Animation block and Wave(...), or through a consumer-provided evaluation time.
Diagnostics
Parser errors include stable codes such as PR0001 for syntax, PR0004 for duplicates, and PR0008 for unknown references. Tooling should match the structured code rather than parsing the explanatory message.
The exhaustive block-by-block reference currently remains in crates/procedural_recipes/README.md. It will be migrated into this chapter as the public language stabilizes.