Detail the NPC avatars and finish the realism follow-ups
Blender library - Rebuild the face: sclera, iris and upper lid per eye, brow ridge, cheekbones, nose bridge and tip, ears with lobes, split upper/lower lips. - Give each hand four fingers plus a thumb and end every sleeve in a cuff ring. - Raise CHAR_MAX_VERTS 4000 -> 5000 (16 avatars still cost ~6.9 ms of a 50 ms frame), decimate the body to 26 %; characters are now 3,974-5,026 tris and 3,744-4,807 verts. Rebuild all 8 variants and re-bake their AO maps. Capture tooling - Add a `portrait` stage to capture_realism.gd: freeze one NPC, park the crowd out of frame, stand the subject on open sidewalk, turn it into the camera and put the guard on the sunlit side. New --portrait-type=N picks the role. - Add the npc_portrait_day concept and map the shot to it, so avatar detail is scored against a portrait instead of a wide street frame. Flashlight - Drop the fake additive beam (Materials.light_beam + the cone mesh): on GL Compatibility a first-person camera inside the cone renders it as a filled disc with a bright far ring. Keep the tight spot (14 deg, 20 m, energy 4.2) and its headless test; the visible shaft is now planned behind a Forward+ preset. Docs and task tracking - Move the finished realism follow-ups (ground exposure, flashlight, NPC detail, judge re-check) to DONE.md and expand TODO.md with step-by-step plans for NPC gear fit, venue geometry plus the committed gallery, and the Forward+ preset. - Record the decisions, gotchas and portrait recipe in MEMORY.md; update the Blender contract, the concept README and the capture section of README.md. - Refresh the gallery captures affected by the avatar rebuild. Checks: headless 228/228, Python 86/86, blender_assets audit exit 0, scene_concepts audit all GOOD, screen_designs compare 11 good / 0 bad, smoke_npc_budget OK, boot clean (only the known headless mesh warning).
This commit is contained in:
1 parent
2624b54b23
commit
1ee32215b0
53 files changed
+1853
-151
No files matched your search
@@ -1,28 +1,97 @@
|
||||
# TODO
|
||||
|
||||
## Realism follow-ups (v0.6.1 candidates)
|
||||
Work is grouped by theme. Each item should be small enough to complete and verify on its own;
|
||||
see `AGENTS.md` for the workflow and `MEMORY.md` for the decisions behind these plans.
|
||||
|
||||
- [x] Fixed ground exposure for the entrance view: the morning sun now sits at 34° elevation
|
||||
instead of 50°, so the facade shades the near sidewalk and props cast long shadows. Ground
|
||||
luminance went 95 → **83** against the concept's 78 (it was 173 before the realism pass),
|
||||
with the boulevard at 82 and the street at 81.
|
||||
- [x] Make the flashlight read in the dark: narrowed the cone (30° → 14°, range 20 m, forward
|
||||
aim) so it lights the door instead of washing the facade, raised the spot/glow at night, and
|
||||
staged the two night captures in LATE instead of dusk (`capture_screenshots.gd`). The judge
|
||||
moved `06-night-flashlight` from **diff (1.00) to review (0.10)**. A visible beam *shaft*
|
||||
is not possible on GL Compatibility (no volumetrics): an additive cone was tried and
|
||||
rejected because a first-person view inside it renders as a filled disc, so it is tracked
|
||||
as a follow-up for a Forward+ desktop preset.
|
||||
- [-] NPC skin/clothing still reads as low-poly next to the concepts (judge `characters` ≈ 0–1).
|
||||
The Blender library has the budgets for one more detail pass (fingers, sleeves, faces).
|
||||
- [x] Re-check the `screen_designs.py judge` default model (`google/gemini-2.5-flash-lite`): on
|
||||
2026-11-01 it returned 7 match / 4 review / 0 diff without a provider error; `--model`
|
||||
override is documented in `README.md`.
|
||||
- [ ] Add a true flashlight light shaft (volumetric spot) once a desktop Forward+ preset exists;
|
||||
the Compatibility fallback stays the tight pool. See `DONE.md` → environment renderer note.
|
||||
- [ ] Add the two venue stages to the committed gallery (they are capture-only today) and give
|
||||
the Joke Shop and studio their own geometry so their concept comparisons are geometric,
|
||||
not just lighting.
|
||||
## NPC gear fit (v0.6.1)
|
||||
|
||||
The 2026-11-01 detail pass fixed the bodies but not the props worn on them. In the portrait
|
||||
capture (`--stages=day,portrait`, see the report in `docs/screens/realism/2026-11-01-npc/`) the
|
||||
sunglasses span the whole upper face and the shoulder bag cuts through `npc_coat`'s skirt. Blender sources for gear
|
||||
live in `tools/blender_assets.py` (`_build_gear()`), the contract in `docs/blender-assets.md`
|
||||
(gear budget 1500 tris, `GEAR_ATTACH` points in `NpcAvatar`).
|
||||
|
||||
- [ ] Measure the fit in Blender, not by eye: extend `blender_assets.py audit` (or add a `fit`
|
||||
subcommand) to print, per head/back/chest gear piece, its bounding box against the avatar
|
||||
head width (measured 0.314 m on `npc_coat`), the head height band (y 1.55–1.81) and the
|
||||
clothing radius (coat/dress skirt flare 0.225–0.26 m), for every character variant.
|
||||
- [ ] Narrow `sunglasses` from 0.28 m to ~0.20 m. The width is driven by the arms/hinges
|
||||
(`Hinge` at `x = ±0.11` with a 0.06 box, `Arm` at `±0.138`), not by the 0.03 m lenses, so
|
||||
pull those in first and shrink the lenses to ~0.024 m radius; keep the lens plane at
|
||||
`y = -0.152` (in front of the sclera) and `z = 0.035` (eye line) so it does not ride up
|
||||
over the new brow ridge.
|
||||
- [ ] Fix `shoulder_bag` clipping through `npc_coat`/`npc_dress`: the bag body spans `|x|`
|
||||
0.17–0.25 at the hip while the skirt flares to 0.225–0.26, so its inner half is inside the
|
||||
cloth. Move it outboard (or up onto the belt line) until the inner face clears the flare,
|
||||
and keep the strap tube outside the same radius.
|
||||
- [ ] Same pass for `cap`/`beanie`/`hood`/`firefighter_helmet`: they must not clip the new
|
||||
brow/ear geometry, and `hood` must still leave the face readable for hoodie avatars.
|
||||
- [ ] Rebuild the gear (`build`) and re-bake AO (`tools/bake_ao.py`), then
|
||||
`godot --headless --path . --import`.
|
||||
- [ ] Add a regression test: `tools/test_blender_assets.py` checks the glasses width against the
|
||||
head width, and `src/test/tests/test_npc_character.gd` checks the head/back attach nodes
|
||||
stay outside the body silhouette radius.
|
||||
- [ ] Re-capture the portrait (`--stages=day,portrait`) and the gallery shots; record the
|
||||
before/after in `docs/screens/realism/<date>-gear/`.
|
||||
- [ ] Consider a second character close-up for a hoodie/winter NPC so headgear is covered too
|
||||
(`--portrait-type=5` already forces a hooded role for comparison).
|
||||
|
||||
## Venue geometry and the committed gallery (v0.6.1)
|
||||
|
||||
Today all three venues share the Hollywood `WorldBuilder` geometry, so the Joke Shop and studio
|
||||
concepts are only compared on lighting (noted in `tools/scene_concepts.py` `SHOTS`). They also
|
||||
have no stage in the committed `docs/screenshots/` gallery, only in `capture_realism.gd`.
|
||||
|
||||
- [ ] Extract a geometry spec per venue instead of branching inline: a `scenario.` (or
|
||||
`WorldBuilder`) table of facade width/height, door style, window rows, awning/marquee
|
||||
flags, street furniture set, palette and props, defaulting to the Hollywood values so
|
||||
nothing regresses.
|
||||
- [ ] Joke Shop: narrow brick alley (10–12 m wide), one warm wall lantern as the key light,
|
||||
recessed door with a step, shuttered window, dumpster/AC clutter, no skyline ring — the
|
||||
alley concept has depth, not a horizon.
|
||||
- [ ] TV Studio: granite/stone facade, bulb canopy instead of the marquee, glossy black car on
|
||||
the curb, stanchions and barrier line at the door, no palm trees.
|
||||
- [ ] Keep navigation working: regenerate/verify the `NavigationRegion3D` bake per venue,
|
||||
update sidewalk/steps/door waypoints (Joke Shop and Studio already have `sidewalk` and
|
||||
`steps_end`), and confirm NPCs still reach the door (smoke + `test_venue_*`).
|
||||
- [ ] Split the concept mapping so each venue is judged on its own frame (`joke_shop_*`,
|
||||
`studio_*`) and drop the "shared geometry" caveat in `tools/scene_concepts.py`.
|
||||
- [ ] Add both venues to the committed gallery: two new stages in
|
||||
`src/test/capture_screenshots.gd` (`12-joke-shop.png`, `13-studio-arrival.png`) reusing the
|
||||
existing `joke_shop_queue` / `studio_arrival` designs, then `check_screenshots.sh` and a
|
||||
fresh judge run.
|
||||
- [ ] Update `docs/architecture.md` (venue geometry), `README.md` (gallery) and the screenshot
|
||||
table when the stages land.
|
||||
|
||||
## Forward+ desktop preset and a volumetric flashlight (v0.7.0)
|
||||
|
||||
The Compatibility renderer has no volumetrics, so the flashlight is a tight pool of light with
|
||||
no visible shaft. A second desktop build can render it properly without touching the CI/default
|
||||
path.
|
||||
|
||||
- [ ] Write the preset as an `override.cfg` (Godot reads it beside the binary/project) that sets
|
||||
`rendering/renderer/rendering_method="forward_plus"`, enables `volumetric_fog_*` and SDFGI,
|
||||
and keeps the Compatibility build as the default (`project.godot` unchanged).
|
||||
- [ ] Gate the effect in code: only give the flashlight a volumetric component when the renderer
|
||||
is Forward+ (`RenderingServer.get_rendering_device() != null`), so Web/CI builds are
|
||||
untouched and the existing headless tests keep passing.
|
||||
- [ ] Tune `light_volumetric_fog_energy`/`fog_density` for the LATE phase and re-check the
|
||||
entrance so the shaft does not wash the facade again (the reason the wide cone was cut).
|
||||
- [ ] A/B the two renderers with `capture_realism.gd` (same stages, two `--out` dirs) and record
|
||||
the diff + judge scores in `docs/screens/realism/<date>-forward-plus/`.
|
||||
- [ ] Add the preset to `tools/build_releases.sh` and `docs/RELEASING.md` as an optional
|
||||
"desktop HQ" artifact, and note the runtime requirement (Vulkan driver) in `README.md`.
|
||||
- [ ] Test: a headless run must still boot when Forward+ is unavailable (the preset must degrade
|
||||
to Compatibility instead of failing to start).
|
||||
|
||||
## Realism follow-ups (deferred)
|
||||
|
||||
- [ ] Human-authored tree/hedge silhouettes: the whole scene now reads well except the foliage,
|
||||
which is still flat-shaded clumps (`_shrub()`/`_tree()` in `tools/blender_assets.py`).
|
||||
Only worth doing if a higher-poly organic builder is added to the library.
|
||||
- [ ] Camera height: the concept frames are shot at ~1.55 m with a slightly wider lens; the game
|
||||
camera sits at 1.7 m. Decide whether the first-person height should match the art direction
|
||||
or stay at the current gameplay value.
|
||||
|
||||
## Future ideas (optional, not scheduled)
|
||||
|
||||
|
||||
Reference in new issue
Block a user