Commit graph

3 commits

Author SHA1 Message Date
018909b2cd fix(render): full-range per-frame depth normalization for FPV ControlNet
Diagnosis: every baked FPV depth map used only the upper-mid grays
(typ. 160–214, 0/68 frames reaching true black, only 35/68 reaching
near-white). A fixed 0..maxView=12 scale meant the nearest floor (~1
cell) never hit white and a wall 3 cells ahead never went past mid-gray,
so a small room collapsed into a low-contrast band. A depth ControlNet
trained on full-range MiDaS/depth-anything maps gets almost no structural
signal from that — the root cause of "controlnet barely followed / hit
and miss" renders.

Fix: two-pass raycast. Pass 1 records each column's wall distance and the
frame's true near/far. Pass 2 maps depth through a per-frame window so
near surfaces read white and the deepest visible recess reads black every
frame. The far plane tracks the deepest real surface but is clamped to a
minSpan floor so a shallow dead-end nook is NOT stretched into a fake
tunnel — its faced wall stays an honest mid-gray slab (no black recess
for the model to paint a phantom door into). gamma default 2.0→1.5 since
normalization now owns the range. nearPlane/minSpan exposed as opts.

Verified offline (headless bake, seed 7, 68 frames): median dynamic range
193→255; frames reaching true-white near surfaces 35/68→68/68; worst-frame
range 54→106. Visual before/after confirms open frames now frame a black
passage and closed frames a clean mid-gray wall.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:24:29 -06:00
acc8137f4a fix(pipeline): kill dither speckle + atlas geometry lies (post-playtest)
Parley's review: dither full of green spots, baked rooms don't match the
nav graph (doors painted on closed walls, real openings off-center).
Both root-caused:

- pixelate.py: the nearest-color LUT was spaced in LINEAR RGB, cramming
  the whole shadow range into ~4 cells — dark picks were effectively
  arbitrary (green/teal confetti in warm near-blacks). LUT is now
  sRGB-spaced, diffusion error is gamut-clamped (no more blue blobs at
  torch highlights), and a new --overshoot penalty forbids choosing a
  color more saturated than the source. Green-dominant dark pixels on
  the test frame: 5.2% -> 0.02%, while palette usage went UP (107 -> 135
  colors). Recipe rev 2: append --overshoot 6.

- fpv.js: new directedVantage(env, region, dir) — per-(room,facing)
  camera instead of one room-wide vantage. Open ahead: stand in a cell
  whose straight-ahead ray escapes through the actual gap (the passage
  you walk is centered, 2-7 cells deep). Closed ahead: stand ~2 cells
  from the wall, deliberately OFF the room's axis — a symmetric stage
  begs the model to paint a centered focal door; an off-axis dead-end
  corner doesn't. Walls also render under their own fixed seed and an
  emphatic sealed-masonry prompt clause (cfg 1.0 negatives are inert).

Validated on seed 7 room 1: the closed-N phantom door is gone; the open-S
passage is dead-center. Full campaign re-bake follows as its own commit.

Also: rest-overlay no longer sticks without a keyup, in-combat drink
message, feathered sprite mask, no monster packs on floor 1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 00:06:46 -06:00
ed00e31009 feat(render): real-geometry depth export + first-person explorable atlas
Render actual generated dungeons through the AI pipeline — both top-down and
first-person (Eye-of-the-Beholder style) — instead of synthetic test depth.
All renderer-side: derived from the envelope's tiles+regions+theme, the core
stores none of it.

- depth.js: top-down height-field depth exporter (walls raised, pools recessed,
  pillars as bumps, subtle per-theme relief), calibrated to the proven room_depth
  levels so one tall room can't crush every floor dark.
- fpv.js: first-person depth via a Wolfenstein-style grid raycaster (16:9),
  reports straight-ahead distance for opening detection.
- explore.js: room->room nav graph derived from REAL tile openings (scan
  boundary gaps, bin by cardinal, flood the corridor to the destination room) —
  nav + open share one source of truth with the rendered passages.
- bake_atlas.py: bakes per-room x4-facing pixel-art frames; per-theme + per-facing
  (wall vs passage) prompts, fixed diffusion seed for cross-frame style coherence,
  per-run unique prefixes so re-bakes don't silently skip.
- explore.html + explore-viewer.js: WASD first-person dungeon explorer
  (room-to-room movement, turning, minimap), integer-pixel fullscreen.
- serve.py: stdlib dev server — static web root + /out tree + POST /save, no-store.
- main.js/render.js/style.css: export hooks, the depth button, distanceToWall export.
- tools/README.md: Stage 0/1/2/3 docs; .dev/2026-06-01-fpv-prompts.md: prompt
  research (cfg-1 negatives are inert; trigger words summon hands; empty-ruin
  reframe; fixed seed = consistency).

Proven end-to-end on seed 7 (17 rooms). Outputs organized under git-ignored
tools/out/. Control strength: 0.80-0.85 top-down, 0.85 first-person.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 00:02:14 -06:00