Brush Engine
Pressure dynamics, wet mix, scatter, jitter, alpha lock.
Deterministic stroke simulation. Same input + same settings = bit-identical dabs. That's what makes timelapse replay drive the actual canvas, and what'll enable co-op editing.
Stroke Pipeline#
- Input sampling: pressure + position
- 1-Euro filter: adaptive smoothing (more on slow strokes, less on fast)
- Catmull-Rom interpolation: smooth spline through sparse samples
- Dab placement: spacing rules emit dabs along the path
- GPU compositing: each dab paints with chosen blend mode
Every other parameter decorates this pipeline.
Pressure Dynamics#
Pressure drives size, opacity, flow independently. Each interpolates between Min and Max with a per-curve exponent (concave for light-touch sensitivity, linear, or convex).
Pressure works on Wacom Pro Pen, Apple Pencil, and most styluses. Tilt and rotation pass through pointer events but aren't wired into the brush engine yet.
For mouse painting, the 1-Euro smoother is the difference between a wobbly line and a clean one.
Blend Modes#
Thirteen modes, applied per-dab:
normal, erase, smudge, multiply, screen, overlay, soft light, hard light, color dodge, color burn, darken, lighten, difference
The Blend node and layer panel expose a larger 22-mode set (full Photoshop, including HSL and advanced light modes). The brush stays focused on this 13.
Wet Mix#
| Parameter | Effect |
|---|---|
| Dilution | Bristle fades over the stroke (dry-brush) |
| Charge | How much paint the bristle holds before depleting |
| Attack | Speed to reach full deposition at stroke start |
| Pull | Canvas color sampled into bristle (wet-into-wet) |
| Wet edges | Pigment pools at edges (watercolor) |
| Burnt edges | Soft bloom along the stroke |
| Wet blur | Softens fresh paint into surrounding pixels |
| Wetness jitter | Per-dab randomization |
Pull + wet edges + low charge -> watercolor washes. High opacity + zero wet -> hard ink.
Scatter & Jitter#
| Parameter | Effect |
|---|---|
| Spacing | Distance between dabs as fraction of brush size |
| Spacing jitter | Irregular dot patterns |
| Lateral jitter | Wiggle perpendicular to stroke |
| Linear jitter | Wiggle along stroke |
| Scatter | Place dabs around path radially / laterally |
Jitter seeded by strokeID. Same stroke always produces the same pattern.
Brush Shape & Grain#
Two image inputs:
- Shape: silhouette of one dab (default soft round; load any PNG). Always positioned per dab.
- Grain: paper/canvas/noise texture multiplied into each dab. Moving (follows the stroke) or texturized (pinned in canvas space).
Both embed in the document. Brushes look identical on reload.
Alpha Lock#
Paint only over existing pixels. Toggle on the layer or in brush settings. Enforced in the GPU shader for sub-pixel-perfect edges.
QuickShape#
Hold at end of stroke to snap to line, ellipse, circle, rectangle, or quad. Adjust live before lifting. Toggle, hold duration, and confidence threshold live in Settings > Painting.
Determinism#
Same (input samples, brush settings, strokeID) always produces bit-identical output. Brush algorithm is versioned. Older recordings replay against the version they were recorded with.
Next#
- Selection & Lasso: pixel selections, free transform
- User Library: saving and reusing brushes