FollicleScript Expressions
FollicleScript is FollicleFX's expression language for procedural hair control. Write simple expressions that are evaluated in real time on 100,000+ strands.
Quick Start
Click the ƒx button next to any parameter to open expression mode.
0.8 # Constant value
rand(index) # Random 0-1 per strand
rand3(0.7, 1.0, index) # Random in range per strand
lerp(0.5, 1.0, v) # UV-based gradient
v > 0.5 ? 1.0 : 0.5 # Conditional
Variables
Strand Properties
| Variable | Description | Range | |----------|-------------|-------| | index | Strand index | 0 to count-1 | | count | Total strand count | — | | length | Strand length | World units | | maxLength | Maximum strand length in system | World units | | width | Strand width | World units | | t | Position along strand | 0 (root) to 1 (tip) |
Spatial Coordinates
| Variable | Description | Range | |----------|-------------|-------| | u | UV X coordinate | 0–1 | | v | UV Y coordinate | 0–1 | | x | World X position | World units | | y | World Y position | World units | | z | World Z position | World units |
Clumping
| Variable | Description | |----------|-------------| | clump_id | Clump index (when using Clumping modifier) |
Constants
| Constant | Value | |----------|-------| | pi | 3.14159... | | tau | 6.28318... (2π) | | e | 2.71828... |
Operators
Arithmetic
+ - * / ^ (or **) ()
Comparison
< > <= >= == !=
Returns 1.0 (true) or 0.0 (false).
Ternary
condition ? value_if_true : value_if_false
Functions
Random & Noise
| Function | Description | |----------|-------------| | rand(seed) | Deterministic random 0–1 | | rand3(min, max, seed) | Random in range [min, max] | | noise(x) / noise(x, y) / noise(x, y, z) | Smooth organic noise |
Math
| Function | Description | |----------|-------------| | abs(x) | Absolute value | | sqrt(x) | Square root | | pow(x, y) | Power | | exp(x) | e^x | | log(x) | Natural logarithm | | sign(x) | Returns -1, 0, or 1 | | mod(x, y) | Modulo | | min(a, b) | Minimum | | max(a, b) | Maximum |
Trigonometry
sin(x) cos(x) tan(x) — Input in radians.
Rounding
floor(x) ceil(x) frac(x)
Interpolation
| Function | Description | |----------|-------------| | clamp(x, min, max) | Clamp to range | | lerp(a, b, t) | Linear interpolation | | smoothstep(edge0, edge1, x) | Smooth S-curve | | select(cond, a, b) | If cond > 0 then a, else b |
Texture Sampling
map(u, v) # Sample bound texture at UV coordinate
Custom Variables (Dynamic Sliders)
Use $varName syntax to create UI sliders automatically:
$base + rand(index) * $variation
This creates "base" and "variation" sliders that you can adjust in real-time. Up to 16 custom variables supported.
Common Patterns
Per-Strand Randomization
rand(index) # Random 0-1
rand3(0.8, 1.2, index) # Random range
clamp(rand(index), 0.2, 0.8) # Clamped random
Gradients
v # Bottom to top (0→1)
1.0 - v # Top to bottom (1→0)
u # Left to right
lerp(0.5, 1.5, v) # Custom range gradient
Along-Strand Effects
t # Root to tip (0→1)
1.0 - t # Tip to root
lerp(1.0, 0.1, t) # Taper
smoothstep(0.0, 1.0, t) # Smooth taper
Center/Edge Falloff
1.0 - abs(u - 0.5) * 2.0 # Dense in center
abs(u - 0.5) * 2.0 # Dense at edges
Per-Clump Variation
rand(clump_id) # Random per clump
0.5 + rand(clump_id) * 0.5 # Clumps vary 0.5–1.0
clump_id % 2 # Alternating clumps
Conditional Logic
v > 0.5 ? 1.0 : 0.5 # Top/bottom split
rand(index) * 0.5 # Per-strand variation
index < 100 ? 0.8 : 1.0 # First 100 strands different
Noise Patterns
noise(u * 10, v * 10) # 2D organic pattern
noise(u * 5, v * 5, index) # Per-strand noise
0.7 + noise(u * 3, v * 3) * 0.3 # Noise in range
Modifier-Specific Examples
Clumping — Per-Clump Tightness
rand3(0.6, 0.9, clump_id)
Frizz — Per-Strand Variation
rand(index) * 0.5
Cut — Random Trim (Keep 80–100%)
rand3(0.8, 1.0, index)
Cut — Remove 1–3% Per Strand
1.0 - rand3(0.01, 0.03, index)
Density — UV-Based
lerp(0.5, 1.0, v)
Width — Taper to Tips
lerp(1.0, 0.1, t)
Coil — Per-Strand Count Variation
5.0 + rand(index) * 3.0
Tips
- Use
indexfor per-strand randomization — consistent, deterministic - Use
tfor along-strand effects — 0 at root, 1 at tip - Use
clump_idfor per-clump variation — all strands in a clump get the same value - Clamp extreme values —
clamp(expr, 0.2, 0.8)avoids outliers - Start simple — test with constants, add complexity gradually
- Custom variables for tweaking —
$varNamecreates real-time sliders - Most parameters expect 0–1 — check the parameter's range
Performance Notes
- Expressions are evaluated in real time on all strands simultaneously
- Simple expressions (arithmetic, rand) are very fast
- Complex expressions (noise, trig) are slightly slower
- No practical limit on expression complexity