A 3D Voronoi cell structure as a spatial field — cell-wall line art, cracked and crazed surfaces, stained-glass leading, organic panelling, all sampled in 3D so they cross any surface without a UV, a seam, or a pole.
JavaScript API:
VoronoiSpatialField
This is the Voronoi member of the SpatialField family: like every
field it turns where into how much — a scalar weight over space that
consumers read by #id (field="#id") to gate material alpha, tonemap
coverage, or colour-map weight alike. Because it is sampled at a 3D position,
a surface simply shows the cross-section of the volumetric cells it cuts
through — immune to the seams and poles that plague a tiled 2D pattern.
Key attributes. output chooses the scalar: distance-to-edge (default,
the unsigned distance to the nearest cell wall — this is the mode that makes
line art), f1/f2 (distance to the nearest / second-nearest seed, classic
Worley), or cell-id (a stable per-cell hash for per-cell variation). scale
sets cell density; jitter is the seed displacement within each cell (0 is a
regular lattice, Blender calls this randomness). seed is a CONTINUOUS
re-roll axis and seed-period the advance that returns the identical field,
so a linear seed animation loops seamlessly. swell fillets junctions where
three or more cells meet, in the field's distance units, without widening
straight runs (distance-to-edge only). voronoi-type selects xy/yz/zx
(an extruded prism of cells, constant along the omitted axis) or xyz (full
3D packing). The field rides its own frame, so animating its x/y/z or
rotation moves and turns the cells with it.
**Width and softness come from remapCurve, not attributes.** A line of a
given width is a threshold on the distance-to-edge scalar — a pointwise
remap — so it is expressed through the base's SpatialField.remapCurve
(e.g. remap-curve="step:0.05" for a crisp wall, inverse:... to flip which
side survives), never a bespoke width/softness attribute.
Related. It shares the field="#id" model with every field; its smooth
counterpart is sk-noise-spatial-field and its uncorrelated one
sk-random-spatial-field. To turn cells into COLOUR, drive a
sk-color-map-source intensity-field with this field. Typical
consumers are a sk-tonemap (gate coverage), a sk-plain-material
(gate alpha), and sk-field-constraint (drive a property per cell).
Serve these docs to run the live example.
WebGPU needs a secure context — open this page via grunt serve
rather than double-clicking the file. The Markup tab works from disk.
<!-- 3D Voronoi cell-wall line art on a sphere. The field emits the distance
to the nearest cell wall; its `remap-curve` thresholds that distance into
a thin wall (`step:0.06` — weight is 0 in the thin band next to a wall and
1 across the cell interior). The color-map then paints cell interiors
cream and the walls near-black. Sampled in 3D, the walls wrap the sphere
with no UV, seam, or pole. A linear `seed` animation re-rolls the cells
and LOOPS seamlessly, because advancing `seed` by exactly one
`seed-period` returns the identical field. -->
<sk-scene>
<sk-directional-light p="50deg" h="25deg" intensity="1.1"></sk-directional-light>
<sk-ambient-light intensity="0.45"></sk-ambient-light>
<sk-voronoi-spatial-field id="cells" scale="1.3" jitter="0.85"
output="distance-to-edge" seed="0" seed-period="16"
remap-curve="step:0.06">
<sk-animation duration="9000ms" iterations="Infinity">
<sk-keyframe offset="0" seed="0"></sk-keyframe>
<sk-keyframe offset="1" seed="16"></sk-keyframe>
</sk-animation>
</sk-voronoi-spatial-field>
<!-- The field's weight (0 at a wall, 1 in the cell interior) selects along
the ramp: walls → near-black, interiors → cream. -->
<sk-ramp-color-map id="cm">
<sk-color-stop stop-offset="0" stop-color="#141414"></sk-color-stop>
<sk-color-stop stop-offset="1" stop-color="#f4f1e8"></sk-color-stop>
</sk-ramp-color-map>
<sk-color-map-source id="walls" intensity-field="#cells" color-map="#cm"></sk-color-map-source>
<sk-plain-material id="mat" base-color-source="#walls"></sk-plain-material>
<sk-sphere radius="3" segments="48">
<sk-surface-paint material="#mat"></sk-surface-paint>
</sk-sphere>
</sk-scene>
| Attribute | Type | Default | Description |
|---|---|---|---|
id |
<id> |
— | The element's unique identifier — the standard HTML global id attribute. |
remap-curveanimatable |
<remap-curve> |
— | Optional remapping curve to reshape the field's [0, 1] output. |
remap-phaseanimatable |
<number> |
0 |
Horizontal remap phase — an animatable scalar that translates a present |
voronoi-type |
<voronoi-type> ("xy" | "yz" | "zx" | "xyz") |
"xyz" |
Which plane(s) the cells pack in. A 2D type is constant along the omitted axis. |
output |
<voronoi-output> ("distance-to-edge" | "f1" | "f2" | "cell-id") |
"distance-to-edge" |
Which scalar to emit. |
scaleanimatable |
<number> |
1.0 |
Cell density — higher packs more, smaller cells into the same space. |
jitteranimatable |
<number> |
1.0 |
Seed displacement within its cell (Blender's randomness). 0 is a regular lattice, 1 fully random. |
seedanimatable |
<number> |
0 |
Re-roll axis. Continuous, NOT an integer index. |
seed-periodanimatable |
<number> |
— | The seed advance that returns the identical field. |
swellanimatable |
<number> |
0 |
Junction fillet radius, in the field's distance units (distance-to-edge only; 0 disables). |
xanimatable |
<number> |
0 |
X position. |
yanimatable |
<number> |
0 |
Y position. |
zanimatable |
<number> |
0 |
Z position. |
hanimatable |
<angle> |
0 |
Heading (Y-axis rotation) in radians. |
panimatable |
<angle> |
0 |
Pitch (X-axis rotation) in radians. |
banimatable |
<angle> |
0 |
Bank (Z-axis rotation) in radians. |
visualize |
<boolean> |
false |
Whether to show visualization (wireframe splines + center marker). Default: false |
interactive-controls |
<boolean> |
false |
Whether to show interactive controls (draggable markers). Requires visualize. Default: false |