reikhelm/.dev/2026-06-15-diffusion-pipeline-reliability.md
Parley Hatch 53cd1023e0 feat(pipeline): strength-sweep harness + reliability findings doc
sweep_strength.py renders one open + one closed FPV frame across a
ControlNet strength matrix at fixed seed/prompt and montages them beside
the depth map — the GPU experiment to find the right strength now that
rev-3 depth maps carry a full-range signal (018909b). Findings/plan in
.dev/2026-06-15-diffusion-pipeline-reliability.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 20:25:45 -06:00

64 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Diffusion pipeline reliability — making the depth ControlNet actually followed
**Started:** 2026-06-15 · ongoing (`/loop`)
**Problem (user):** "controlnet maps generated are barely followed; images of the
dungeons are very hit and miss."
## Root cause found (iteration 1)
The FPV depth maps fed to the Z-Image Fun depth ControlNet used only a sliver of
the tonal range. Histogram over all 68 baked seed-7 frames:
- median dynamic range **193 / 255**, worst frame only **54**
- **0/68** frames reached true black (`<32`); the deepest recesses topped out ~mid-gray
- only **35/68** reached near-white at the near surfaces
Cause in `reikhelm-web/fpv.js`: a fixed `t = dpix / maxView` with `maxView = 12`.
The nearest floor sits ~1 cell away (never hit white) and a wall 3 cells ahead
landed at mid-gray (never black), so small rooms collapsed into the 160214 band.
Depth ControlNets are trained on full-range MiDaS / depth-anything maps, so a
washed-out map gives almost no structural signal the model freelances.
## Fix shipped — commit `018909b`
Two-pass raycast in `computeFPVDepth`:
- Pass 1 records each column's wall distance + the frame's true near/far.
- Pass 2 maps depth through a **per-frame window**: near white, deepest visible
recess black, every frame.
- Far plane tracks the deepest *real* surface but is clamped to `minSpan` (5 cells)
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 no phantom-door bait).
- `gamma` 2.0 1.5 (normalization now owns the range). `nearPlane`/`minSpan` are opts.
**Verified offline** (headless `bakeAtlasDepths(7)`, 68 frames):
median range 193 **255**; near-white frames 35/68 **68/68**; worst range 54 106.
Visual before/after (`/tmp/ba.png` during the session): open frames now frame a
black passage; closed frames a clean mid-gray wall.
## Next — needs the render workstation (192.168.1.26:8188, was OFFLINE this iteration)
The depth signal is now strong, so the old strength is almost certainly wrong.
With a weak signal you crank strength to force adherence; a strong signal wants
*less*. `bake_atlas.py` defaults `--strength 0.85`.
1. Re-probe the workstation: `python3 tools/comfy-spike/comfy.py probe http://192.168.1.26:8188`
2. **Strength sweep** (tool already written, validated):
```
python3 tools/comfy-spike/sweep_strength.py http://192.168.1.26:8188 \
--seed-dir tools/out/atlas/7 --open r8_N --closed r0_N \
--strengths 0.55,0.7,0.85,1.0
```
`tools/out/compare/sweep_<run>.png`. Read adherence: does the rendered passage
land on the black recess? does the closed wall stay a wall (no phantom door)?
Pick the lowest strength that still honors geometry, update `bake_atlas.py` default.
3. Then re-bake a full atlas at the chosen strength and spot-check a montage vs the
old `acc8137`/`a12bcbb` bakes.
## Open levers if still hit-and-miss after strength tuning
- `nearPlane`/`minSpan`/`gamma` are now tunable per-export A/B if near surfaces
read too blown-out (the AFTER maps are ~47% near-white; may want a slightly
deeper nearPlane to retain near-field texture).
- Subtle masonry-block relief on closed-wall slices so flat walls render as detailed
stone (offline-buildable, but verify on GPU it doesn't read as structure).
- Strength `start_percent`/`end_percent` scheduling (currently 01 full) easing
control off in late steps frees texture while locking composition.