Skip to main content

Module shape_field

Module shape_field 

Source
Expand description

The mark roster, drawn at frame scale as a distance field (ADR-0105, Plan 0091).

Every other scene here hands the palette a level — a noise field, a chemical concentration, a particle’s depth. This one hands it a distance, and that single substitution is the whole scene:

palette coordinate = mark_distance(p) * color_span + color_center

(that is coord_mode’s default; the second coordinate is below.)

Because a band of the palette coordinate is now a band of constant distance, turning palette_steps up produces concentric offset contours of the chosen shape — not concentric circles, and not an outline sampled to straight segments. It is per pixel, resolution-independent, and there is no geometry to facet (which is the entire argument of ADR-0105 against routing this through the line renderer). palette_contour then draws thin outlines at those band boundaries, and this is the third scene that param does anything in.

§Two coordinates now, and the second is the one the references asked for

(ADR-0111, Plan 0098)

An offset family is an erosion, and erosion rounds a reflex corner while keeping convex ones sharp — so a nested heart keeps its bottom point and loses its top notch as the contours move inward, and no amount of tuning reaches the construction two batches of user reference images have asked for. coord_mode = "1" hands the palette

s = length(p) / r_boundary(theta)

instead — 0 at the centre and exactly 1 on the outline, the same contract, but its level sets are scaled copies of the outline. The ring count is then palette_steps alone and the innermost figure is a scaled copy at any count, so notch sharpness stops trading against ring count.

The distance stays the default and stays bit-identical, which is what keeps every shipped preset and every golden baseline on the arithmetic it has today. The two are not interchangeable settings of one knob: color_span means a different thing under each, because the exterior is divided by the shape’s inradius under one and grows linearly in r under the other.

§It shares the shape vocabulary rather than restating it

The silhouettes come from marks — the same WGSL chunk swarm and emitter splice in, and the same CPU-side quantizers for the shape selector and the points count. So a mark a particle can wear and a figure this scene can be cannot drift apart, and the roster stays closed at five names (ADR-0084’s consequence, restated in ADR-0105).

§A silhouette can also be authored (ADR-0107)

A [path] table hands this scene a closed contour parsed from inline SVG path data, and it takes the place of the roster’s arm in exactly one spot: where the shader asks for the figure’s coordinate. Everything downstream — both coord_modes, gamma, the banding, the contours, the palette — is the same code reading the same d, so an authored figure gets the whole colour surface for free. The roster is untouched and still closed at five names; a preset naming no path executes not one instruction of the contour walk.

Two things fall out of the distance being a min over segments. It is O(N) per pixel and the field is fullscreen, so the arity is a per-frame cost paid whether or not the figure is on screen — MAX_SAMPLES is where core/tests/path_cost.rs measured that becoming half the floor tier’s frame budget, and asking for more is a load error. And fill and stroke stop being two routes: the interior is d < 1 and the outline is abs(d - 1) < w on the one evaluation, which is what the stroke param is.

What is new is that this scene reads the field outside the silhouette, where the particle path never looked. Plan 0091 Phase 2 measured that region and repaired the two arms that were wrong out there; see marks.rs’s own header for what it found and what it deliberately left approximate.

§The aspect comes from the render target (ADR-0037)

There is no internal grid here to take an aspect from by accident, which removes the usual mechanism for that bug but not the obligation. The figure is drawn in a square-unit space built by stretching NDC x by the render target’s aspect, so a disc is round at every window shape. tests renders at 2:1 and 1:2 and measures the figure’s own width against its height, because both 1920x1080 and this box’s 2048x1152 quantize to exactly 16:9 — where no test can tell a right aspect source from a wrong one.

Structs§

ShapeFieldScene
A fullscreen signed-distance figure from the shared mark roster, coloured through the shared palette.

Constants§

PARAMS
The parameter names this scene consumes — the vocabulary a preset binding is checked against at load (ADR-0020). Keep in sync with set_param below; declared_params_match_set_param in core/tests/preset.rs fails if the two drift.