# 2026-07-07 - HD-2D material-render prototype (Bevy, landed behind F3) ``` Type: log ``` ## Intent Cameron wanted to judge an "HD-2D" (Octopath Traveler technique) look for the Bevy frontend from screenshots before any art-direction spec was written. The prototype screenshots were approved with the verdict "land the toggle + write the art spec," so this session landed the frontend-only material preview behind F3 and folded the findings into [bevy-digital-real-canvas.md](../interface/bevy-digital-real-canvas.md). ## What was built (src/bin/bevy.rs only; no sim/save changes) - **F3 render-mode toggle** for the physical/real canvas. Default OFF keeps the existing flat sensorium render byte-for-byte. ON switches to the material render: a `Camera3d` pitched 40 degrees down, perspective FOV 35, anchored to the same cursor tile and framed to the known-content extent (no postage-stamp map, per bevy-visual-floor.md). - **Same-frame canvas** (views.md/bevy-digital-real-canvas.md): one 3D unit per map tile, identical anchors as the flat render. Floor tiles are textured planes; wall/rock/door tiles are extruded boxes reusing the existing tile PNGs; machines/props are upright billboarded quads with their existing sprites; people are billboarded procedural bone silhouettes shown only under earned camera coverage. - **Light rig:** low cool global ambient, one cold fluorescent overhead point light (shadows on), and two warm amber point lights at the core rack and the nearest known device anchor — amber stays machine-presence only. - **Fog contract in 3D:** unknown space spawns/reveals no geometry (sensor darkness); heard is a dim presence floor with no shape; blueprint is unlit schematic planes/ghost mass; remembered is unlit stale-textured model state; only seen surfaces participate in lighting (camera truth is lit, model state is unlit). - **Digital layer stays anchored:** reach traces and the amber attention reticle draw in the material render at the same tile anchors, via a separate gizmo group on the 3D camera's render layer. - **UI unchanged in both modes:** the 2D camera keeps rendering the sidebar and panels over the 3D frame (it stops clearing in material mode); the sidebar labels the current representation (`render: SENSORIUM/MATERIAL`) and F3 joins the input vocab. Mouse tile-picking works in both modes (ray-to-floor-plane in 3D). - **Dev screenshot harness:** `MISALIGNED_SHOT=flat|wide|close` (+ `MISALIGNED_SHOT_PATH`) stages a deterministic scenario (ops top-up, scan, tap/splice known devices, advance until a person is inside coverage), freezes player input (the window steals focus; stray keystrokes polluted early captures), saves one PNG via Bevy's Screenshot API, and exits. Dev-only; inert without the env var. ## Technical findings for a future art-direction spec - Nearest-neighbor sampling (`ImagePlugin::default_nearest`) carries over to `StandardMaterial` textures; pixels stay crisp on 3D planes and boxes. - Billboard z-fighting is manageable: alpha-mask materials (no blend sorting), and the person quad nudged +0.08 toward the camera clears prop quads on the same tile. - UI-over-3D composites cleanly with two cameras: `Camera3d` order -1 on render layer 1, the existing `Camera2d` order 0 with `ClearColorConfig::None` in material mode, `IsDefaultUiCamera` pinning UI to the 2D camera. Gizmos need per-layer config groups or they leak across cameras. - `Visibility::Visible` on children overrides a hidden root: systems that toggle per-entity visibility under a mode root must use `Visibility::Inherited` (this bug leaked 2D overlays into the 3D frame). - Materials must be pooled by (tile, fog, part) — mutating thousands of unique `StandardMaterial`s per tick would re-upload every material each frame; handle-swapping from a small cache is cheap. - The door PNG reads purple in 3D (stale-palette flag already known from the pixel pipeline); lights positioned at device anchors must only use known-at-setup anchors or they would rim-light unearned geometry. - Wall boxes occlude interiors at 40 degrees when a room sits "behind" its south wall; a real pass wants either shorter south-facing walls, cutaway, or a slightly steeper camera. ## Screenshots (reviewed with Cameron before merge) Saved under the session scratchpad `hd2d/`: `flat.png` (current sensorium render), `wide.png` (material render, known-content framing), `close.png` (material render close-up: rack pixel art, amber glow, person silhouette). Cameron's verdict: land the F3 toggle and write the art/spec direction. ## Verification `./tools/check.sh` green on the branch; Bevy launch check clean in both modes (the only ERROR line is the machine-local gilrs IOHIDManager gamepad noise, present on any launch). Flat-mode screenshot confirmed identical in composition to the pre-change frame; sim state is untouched by the toggle (frontend resource only, never saved).