#WGSL Shaders
#Simulation Compute Shader
The simulation shader is generated at runtime by generateComputeWgsl. It specializes the shader for the current ruleset, rule probabilities, random seed, tribe order, grid dimensions, grid topology, virtual boundary tribe, packed grid format, and dispatch plan.
For the persisted rule, selector, clause, outcome, and tribe JSON shapes that feed shader generation, see Rule expressions. For runtime evaluation order and normalization before shader generation, see Rule engine internals.
Key properties:
- It reads from
gridInand writes togridOut. - Workgroup size is .
- Each invocation processes packed word column and row.
- Inside the invocation, it loops over the cells packed into that word.
- It reads the Moore-neighborhood cells according to the compiled topology.
- Toroidal shaders keep the fast wrapping neighbor reads.
- Bounded shaders return the selected boundary tribe for off-grid neighbor reads.
- Bounded shaders use a packed-word interior fast path when every valid cell in the word is away from the edge. Edge-containing words fall back to per-cell interior checks and virtual boundary-aware reads.
- It precomputes unique neighbor count selectors used by non-trivial rule predicates.
- It reduces count-clause predicates to the smallest equivalent check: equality for exact counts, one-sided comparisons for
minandmax, two-sided ranges only for partial intervals, andtruefor always-true ranges such ascount 0..8,min 0, andmax 8. - It evaluates active unmuted rules as a first-match-wins
if/else ifchain. - It wraps probabilistic rules in deterministic hash/threshold checks. Rules with probability skip the hash check and apply directly when their clause matches. Failed probability rolls continue to later rule branches.
- It starts each cell result as the
deadtribe, so no matching rule meansdead. - It packs each resulting cell back into the output word with the active cell mask and shift.
The shader emits packing constants such as CELLS_PER_WORD, WORD_SHIFT, CELL_SHIFT, CELL_INDEX_MASK, and CELL_MASK. This avoids generic bit math branches at runtime.
When at least active rule has probability between and , the generated shader also emits a RANDOM_SEED constant and a probability hash helper. Fully deterministic rules do not need that extra probability branch. In mixed rule chains, only rules whose probability is and call the hash helper; active rules use the direct assignment fast path, and rules are filtered out before code generation.
If the logical dispatch dimensions exceed the device per-dimension limit, plan2DDispatch remaps logical workgroups into a flattened dispatch grid and reconstructs logical coordinates inside WGSL.
#Render Shader
render.wgsl draws a full-screen triangle and maps pixels into grid cells using camera scale, integer offset, and fractional offset. Separating integer and fractional camera offset avoids float precision loss on wide grids.
The fragment shader:
- Converts UV to local cell coordinates.
- Wraps coordinates in toroidal mode.
- Clips off-grid pixels in bounded mode.
- Reads the packed cell value from the active grid buffer.
- Looks up the tribe color from a storage buffer packed as
0x00BBGGRR. - Draws a light brush-preview outline when enabled.
- Draws visual export framing markers while a PNG or MP4 download is being prepared.
The render shader is a template. generateRenderWgsl replaces packing placeholders with constants for the active grid format and injects topology-specific coordinate, preview-distance, and export-overlay code. The worker builds the active render pipeline from the shader variant matching the current topology.
#Brush Shader
The brush shader is generated by generateBrushWgsl. It writes directly into the active packed grid buffer.
Key properties:
- Workgroup size is .
- In toroidal mode, a brush stroke is split into non-wrapping rectangles before dispatch so it can wrap across grid edges.
- In bounded mode, a brush stroke is clipped to the grid edge and does not wrap to the opposite side.
- The shader handles square, round, diamond, vertical line, and horizontal line shapes.
Fullconsiders every cell in the shape.Outlineconsiders only cells on the border of the shape.- Density uses a PCG-style hash to decide which considered cells are written.
- In
FullandOutline, cells skipped by density are left unchanged. - In
Spray, cells skipped by density are written as thedeadtribe. - Multiple selected tribes are selected by hashing into the
tribeIdsarray for cells selected by density.
The brush uniform carries the active density percentage and reserves selected tribe IDs.
#Metric Shaders
Live metrics generate separate WGSL compute shaders:
- Histogram metrics count cells by tribe into atomic counters.
- Boundary metrics count right and bottom cross-state edges into an atomic counter. Toroidal metrics wrap those reads, while bounded metrics skip reads beyond the finite grid edge.
Both use workgroups and the same dispatch remapping strategy as simulation when needed. Histogram results feed population and diversity metrics. Boundary results feed interface metrics.