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

VariableDescriptionRange
indexStrand index0 to count-1
countTotal strand count
lengthStrand lengthWorld units
maxLengthMaximum strand length in systemWorld units
widthStrand widthWorld units
tPosition along strand0 (root) to 1 (tip)

Spatial Coordinates

VariableDescriptionRange
uUV X coordinate0–1
vUV Y coordinate0–1
xWorld X positionWorld units
yWorld Y positionWorld units
zWorld Z positionWorld units

Clumping

VariableDescription
clump_idClump index (when using Clumping modifier)

Constants

ConstantValue
pi3.14159...
tau6.28318... (2π)
e2.71828...

Operators

Arithmetic

+ - * / ^ (or **) ()

Comparison

< > <= >= == !=

Returns 1.0 (true) or 0.0 (false).

Ternary

condition ? value_if_true : value_if_false

Functions

Random & Noise

FunctionDescription
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

FunctionDescription
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

FunctionDescription
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

  1. Use index for per-strand randomization — consistent, deterministic
  2. Use t for along-strand effects — 0 at root, 1 at tip
  3. Use clump_id for per-clump variation — all strands in a clump get the same value
  4. Clamp extreme valuesclamp(expr, 0.2, 0.8) avoids outliers
  5. Start simple — test with constants, add complexity gradually
  6. Custom variables for tweaking$varName creates real-time sliders
  7. 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