Expand description
The voxel system (ADR-0268): a 3D cellular automaton in a cube of cells, drawn as a glowing, absorbing volume — or as lit solid cells (ADR-0269) — seen through the shared orbit camera.
§The state
A ping-pong pair of 3D textures of side grid, one u32 a cell packing its
state and its age (shader::STEP_SHADER). One generation is one compute
dispatch that counts each cell’s live neighbours and applies the rule
(rules). The pair is built when a preset is configured, never on a frame.
[voxel] grid is content, not a resolution: a structure is a fixed number of
cells, so the grid decides how large every structure looks. A grid past the
scene’s cap is clamped and announced from configure as a
CapOverflow, never silently reduced.
§Generations, not frames
step_rate is in generations per second, integrated over the injected dt
by the shared common::GenerationClock, so the automaton
advances by the same count in the same wall time at any refresh rate.
§Every cell is drawn from the seed
The field is seeded from an integer hash of each cell’s coordinates and a
seed derived from the preset’s pinned salt (ADR-0051) — never from a clock —
and each step is integer counting, so a volume is a pure function of its
config and the sequence of bound values and dts it was driven with. Each
reseed rise refills a ball whose centre and cells are hashed from the rise
count and the salt.
§The rule list and the music
[voxel] rules is a list of one to eight rules, and the structural rule
parameter indexes it, so a preset moves the rule on the bar through [hold]
without a mask ever passing through an f32 (ADR-0268). The rule a frame
picks runs every generation that frame encodes. The spectrum lights the
cube’s radial shells, bass at the centre, by 1 + shell_gain * level: an
exact identity at zero gain, and the simulation never reads it.
§The present
A fullscreen march: each pixel’s ray is walked cell by cell through the cube
[-1, 1]^3 under emission-absorption (shader::MARCH_SHADER), and stops
once its transmittance is under one 8-bit step. The ray is recovered from the
camera’s world-to-clip rows, whose aspect is the render target’s (ADR-0037).
focus and aperture are inert here: the circle of confusion is per
primitive (ADR-0257), and a march has no primitives.
The march draws into a target of its own — the tier’s
voxel_march_scale of the
render target, held to its
voxel_march_cap — and a
plain stretch presents it. The target is a resolution, not a shape: the
march’s aspect stays the render target’s whatever the target’s own is.
§Solid
Under [voxel] present = "solid" (ADR-0269) the same march stops at the
first live cell. The decay stages in front of it glow and absorb as they do
under glow; the live cell is shaded as a face — its normal the face the
ray entered through, exact from the traversal’s last step — under one
directional key light and an ambient term:
shade = palette(age) * brightness * shell * (ambient * occ + key * max(0, n . l))composited under the light gathered so far, at full coverage. The light is
given in camera space (light_dir), so the lit side turns with an orbit.
occ is the face’s voxel ambient occlusion: each of its four corners is
closed by the live cells beside it in the layer in front of the face — two
sides close it fully, otherwise each of the two sides and the diagonal a
third — and the four are interpolated across the face at the hit point and
mixed in by ao.
§Bounce
bounce (ADR-0272) lets a solid face take light from the live cells in
front of it. A light field of side grid / LIGHT_CELL holds, per texel, the
live fraction of the LIGHT_CELL³ block of cells it covers and that block’s
summed age weighted the same way; a second texture holds it blurred once over
3³ texels by a 1-2-1 tent on each axis. The march samples the blurred field
trilinearly half a cell in front of the face it hit, and adds
bounce * palette(coord at L.age) * L.intensity * brightness * fog * shellwhere L.age is the sampled age over the sampled intensity. The colour is
looked up at shade time, so only the intensity and the age wait for the
next refill. The field has no occlusion: light passes through walls.
The field is refilled beside the brick pass, after every frame that changed
the state, and on the first frame bounce turns on after frames that did
not fill it. It exists only once a frame under solid has bounce > 0:
before that the march binds a one-texel stand-in and the uniform skips the
fetch, so a preset that never binds bounce builds and reads nothing.
§The section plane
cut, cut_yaw and cut_pitch (ADR-0271) hide every cell whose centre c,
in the cube’s [-1, 1]^3 frame, lies beyond one plane:
dot(c, n) > sqrt(3) * (1 - 2 * cut)
n = (cos(cut_pitch) * sin(cut_yaw), sin(cut_pitch), cos(cut_pitch) * cos(cut_yaw))so at cut = 0.5 the plane passes through the centre and at 1 it removes
every cell. The normal is in the cube’s frame, not the camera’s, so the
section turns with the structure. A cut cell is dead to the march, under
either present, and to the solid present’s occlusion, which reads it as
open. The automaton still runs it: only the view is cut. At cut = 0 the
test is switched off by a flag, so every pixel is as it is without the
params.
§Bricks
After every frame that changed the state, a pass marks each 8³ brick of cells that holds any non-dead cell. The march jumps a whole empty brick at once, landing on exactly the cell, crossing parameters and position stepping through it would have (the crossings are computed from the boundary index, never accumulated), so skipping bricks moves no pixel. A brick is skipped on its own empty flag alone: one holding cut cells is marched cell by cell, and the cut is applied there.
Re-exports§
pub use rules::DEFAULT_RULE;pub use rules::Neighbourhood;pub use rules::RosterRule;pub use rules::Rule;pub use rules::RuleList;
Modules§
- rules
- The voxel system’s rules: a 3D automaton in the Generations sense, and the
closed roster of named ones a preset lists in
[voxel] rules(ADR-0268).
Structs§
- Voxel
Config [voxel]— the structural configuration, fixed while the preset is loaded and delivered throughScene::configure.- Voxel
Scene - A 3D automaton in a cube, marched as an emitting, absorbing volume, or as lit solid cells inside the glow of their own decay.
Enums§
- Present
[voxel] present— how the march draws a live cell (ADR-0269).
Constants§
- DEFAULT_
GRID - The grid an absent
[voxel] gridmeans. - FAMILY_
PARAMS - Every parameter only one present reads (ADR-0180 rule 4): the light, which a glowing volume has no surface to take. A parameter missing from here reads the same on both.
- MAX_
GRID - The largest grid the loader accepts and any tier runs: 2.1 M cells, two 4-byte texels each across the ping-pong pair, 16.8 MB.
- MAX_
SHELLS - The most radial shells the spectrum can be laid across: four
vec4s of the march’s uniform. - MAX_
STEP_ RATE - The fastest
step_ratethe clock integrates, in generations per second. Well past the declared range’s top, so it bounds a runaway binding rather than an author. - MIN_
GRID - The smallest grid the loader accepts. Below it a seeded ball is a handful of cells and every rule’s structure is cut by the faces.
- PARAMS
- The parameter names this scene consumes — the vocabulary a preset binding is
checked against at load (ADR-0020). Keep in sync with
set_parambelow;declared_params_match_set_paramincore/tests/suite/preset.rsfails if the two drift.