A smoother mesh and a better camera can still produce an unattractive
result. In one deterministic ShoggothOx render, an eight-turn
NearRing spent much of its time as a featureless white solid.
Thin colored bands proved that the audio texture was present, but most of
the surface looked like white plastic.
The selected hippy palette supplied the immediate
explanation: entry zero is (252, 252, 252), while inactive
simulation cells contain index zero. The deeper problem was semantic. A
palette lookup tells a 2D framebuffer exactly which color to emit. On a
curved object, the same color is only one input to a material.
Screen mode remains a literal indexed-color display. Buffer index
n must produce palette entry n, including an
intentionally white zero. Changing the palette globally would make the
ordinary visualizer disagree with its authored configuration.
Object modes now take a separate, exhaustively selected path. A new
uniform is zero for Screen and one for every 3D display.
Adding a future display mode therefore requires a compile-time decision
about its material semantics rather than silently inheriting either
behavior.
The renderer already interpolates each fragment's world position. Screen derivatives of that position give the two local surface directions; their cross product gives a geometric normal:
let normal =
normalize(cross(dpdx(world_pos), dpdy(world_pos)));
let diffuse = abs(dot(normal, light_direction));
let surface_light = 0.28 + 0.72 * diffuse;
This avoids storing and maintaining another normal vector on every mesh vertex. It also works for HeightField displacement because the derivatives follow the displaced position delivered to the fragment shader.
Buffer values zero through twelve fade smoothly from inactive to active. Quiet fragments use a subdued base coat derived from palette entry 16, rather than treating entry zero as opaque paint. Active fragments retain their exact indexed color as a brighter emissive layer:
let activity =
smoothstep(0.0, 12.0 / 255.0, index_value);
let base_color = palette(16.0 / 255.0);
let surface_albedo =
mix(base_color * 0.18, indexed_color, activity);
let material_color =
surface_albedo * surface_light
+ indexed_color * activity * 0.24;
The result is neither a hard black color key nor a recolored framebuffer. A quiet object remains visible as a dark palette-related shape, surface curvature remains readable, and music-driven regions keep the palette's vivid colors.
Material shading removed the white slab, but some views were still mostly an inactive base color. The reason was geometric coverage. NearRing's centerline winds around the origin eight times while its longitudinal parameter moves from zero to one, yet its texture coordinate also moved only from zero to one. A sparse vertical band in the simulation therefore occupied only a narrow wedge of the whole object.
ShoggothOx already uses mirrored texture wrapping to make non-tileable simulation edges continuous. One forward-and-reverse mirrored cycle spans two texture-coordinate units. Advancing by two units per turn gives each coil a complete, seam-safe copy:
let uv = [
u * f32::from(NEAR_RING_TURNS) * 2.0,
v * 2.0,
];
The existing deterministic playlist was kept unchanged and rendered with the normal repository command:
nix develop --command cargo xtask video \
"Aces High" --reuse-playlist
Matching frames were checked at 1:05 and 1:10, then contact sheets sampled the complete NearRing interval from 0:45 through 1:27. That wider check matters: one frame can flatter almost any animation. Across the interval, quiet moments now read as a shaded green surface and active moments spread multicolored audio structure around the full ring.