Bake library AO and lift environment textures
Full build / Full desktop build + optional release (push) Successful in 3m43s
Full build / Import + headless tests (push) Successful in 29s

Phase 4 of the v0.6.0 graphics plan:

- tools/bake_ao.py bakes 256² AO maps for every Blender character/gear/prop
  (Cycles, existing UVs) next to each GLB; Materials.apply_ao() wires the red
  channel into character slots, gear, and props. Compatibility has no SSAO.
- Regenerated brick/concrete/asphalt at 1024² with OpenRouter, derived tangent
  normal maps via tools/make_normal_maps.py, and wired them through
  SurfaceMaterials.textured() without changing UV scales.
- Evaluated Forward+: boots on desktop Vulkan, but the renderer is project-wide
  and Web must stay GL Compatibility; v0.6.0 keeps Compatibility (decision in
  MEMORY/plan). A desktop-only override is deferred.
- Recaptured screenshots; compare 11 good / 0 bad. Fixed marquee text alignment.
- Tests: baked AO maps exist for all 46 assets; prop/character AO material
  checks; headless 222/222, Python 69/69, all smokes pass.
- Version 0.6.0; ADR-0013 accepted; README/architecture/blender-assets/plan and
  TODO/DONE updated.
This commit is contained in:
zwitschi committed 2026-11-01 15:07:27 +01:00
1 parent d8cfddbf89
commit d872034388
78 files changed
+390 -28

No files matched your search

+101 -6
View File
@@ -64,13 +64,13 @@ Detailed plan: [`docs/plan-graphics-v0.6.md`](docs/plan-graphics-v0.6.md) · [AD
- [x] Re-measure `smoke_npc_budget.gd`; tune `LOD_TIERS` if the skinned rig is heavier up close.
- [x] Re-verify the focus-cone smoke (`smoke_focus_radial.gd`) and the movement smoke.
### Phase 4 — Environment and lighting lift
### Phase 4 — Environment and lighting lift ✅
- [ ] Bake AO for the prop set through the Blender library (replacements above) or into the ORM/albedo maps behind the existing `WorldBuilder` contract; keep the procedural fallback.
- [ ] Regenerate higher-resolution brick / concrete / asphalt textures via `asset_pipeline.py` with normal maps, keeping the current UV scales; apply the same map discipline to the library's street materials.
- [ ] Evaluate a desktop-only Forward+ export preset (SSAO/SSIL/volumetrics); keep the Web preset on GL Compatibility with `thread_support=false`.
- [ ] Record the renderer decision in an ADR addendum or `MEMORY.md`.
- [ ] Regenerate `docs/screenshots/` with `capture_screenshots.gd` and run `screen_designs.py compare`.
- [x] Bake AO for the prop set through the Blender library (replacements above) or into the ORM/albedo maps behind the existing `WorldBuilder` contract; keep the procedural fallback.
- [x] Regenerate higher-resolution brick / concrete / asphalt textures via `asset_pipeline.py` with normal maps, keeping the current UV scales; apply the same map discipline to the library's street materials.
- [x] Evaluate a desktop-only Forward+ export preset (SSAO/SSIL/volumetrics); keep the Web preset on GL Compatibility with `thread_support=false`.
- [x] Record the renderer decision in an ADR addendum or `MEMORY.md`.
- [x] Regenerate `docs/screenshots/` with `capture_screenshots.gd` and run `screen_designs.py compare`.
### Phase 5 — Verification and release
@@ -129,6 +129,101 @@ and scene visuals with those mockups — verified with
- [ ] Run `screen_designs.py judge` and clear every `diff` verdict (target `match`/`review`).
- [ ] Add the capture + compare step to CI or a repeatable smoke so drift is caught early.
## Improve in-game pop-ups
- [ ] Improve the visual appearance of in-game pop-ups (layout, button style, palette, icons, and text styling).
## Realistic backgrounds, textures and scene references
Goal: replace the outdated flat skyline backdrop (`assets/textures/skyline.png`, black boxes
with dot windows) and the flat-looking surface tiles with AI-generated, more realistic
backgrounds and textures. Add a larger set of example 3D scene images as art direction, and
measure the in-game result against that target with the screenshot tools. Plan:
[`PLAN.md` → Visual Quality Direction → Realism pass](PLAN.md#realism-pass).
**Rule for every step: never overwrite an existing image.** New outputs get new paths. When a
path is taken, the tools pick the next free `-vN` suffix. Raw AI output stays on disk under
`assets/textures/ai/v2/raw/` (gitignored like the other raw AI folders). Processed game-ready
candidates go to `assets/textures/ai/game_ready/v2/`, scene references to `docs/screens/concepts/`,
and trial captures and reports to `docs/screens/realism/<run>/`.
### Step 1 — Tooling (`tools/scene_concepts.py`)
- [ ] Add a catalogue of prompts in three groups: `scene` (16:9 example 3D game frames),
`backdrop` (4:1 skyline panoramas with transparent sky), and `texture` (seamless PBR
surface tiles). Each entry has a name, prompt, role and target path.
- [ ] `generate [--group] [--only] [--variants N]`: call the OpenRouter image API through
`generate_textures.generate_image` (key from the repo `.env`), save raw output, and never
overwrite (`next_free_path`). Print every file written.
- [ ] `process`: turn raw backdrops into 2048×512 RGBA strips that tile horizontally (edge
crossfade, sky made fully transparent, hard alpha for the alpha-scissor material). Turn raw
textures into seamless 1024² tiles (`asset_pipeline.make_seamless`) plus a normal map
(`make_normal_maps.normal_map`). Skip outputs that already exist.
- [ ] `audit`: run `asset_pipeline.audit_image` on the processed candidates (`backdrop` /
`tile` roles) and fail on any bad result.
- [ ] `realism`: for each trial capture, report the Pillow detail metrics (edge density,
contrast, colour spread, saturation) next to the matching concept image. Optionally ask a
vision model (`google/gemini-2.5-flash-lite`) for 0–10 realism scores (lighting,
materials, texture detail, backdrop, overall) with concrete fixes. Write a new JSON +
Markdown report per run.
- [ ] Unit tests (`tools/test_scene_concepts.py`): catalogue shape, the no-overwrite path
picker, backdrop/tile processing on synthetic images, metrics, and the judge payload/parse
(offline, no network).
### Step 2 — Example 3D scene images
- [ ] Generate 3D-game-style example frames for every venue and time of day: Hollywood entrance
(morning, golden hour, rainy night), boulevard skyline view (day, dusk), Joke Shop alley
(evening, close-up of the door), studio stage door (night arrival), sidewalk material
close-up, entrance steps and podium, crowd-control barrier line, and a responder arrival
wide shot.
- [ ] Review the set and record the visual targets each frame sets (sky, haze, material detail,
backdrop depth) in the report.
### Step 3 — Backgrounds (replace the outdated skyline)
- [ ] Generate skyline panoramas for day, dusk and night (lit windows): Hollywood/Los Angeles
mid-rise blocks, palm silhouettes, the hills on the horizon, a transparent sky, and a
straight-on view, in several variants each.
- [ ] Process them into `assets/textures/ai/game_ready/v2/skyline_{day,dusk,night}.png`,
seamless horizontally for the 3× UV repeat around the backdrop ring.
### Step 4 — Textures
- [ ] Generate higher-detail seamless tiles: red brick facade, granite/limestone facade
(studio), sidewalk concrete pavers with joints, asphalt with aggregate, wet night asphalt,
stone steps, striped awning canvas, and stucco wall.
- [ ] Process them into 1024² game-ready tiles plus normal maps in
`assets/textures/ai/game_ready/v2/` and audit them.
### Step 5 — In-game trial captures (no game-code change)
- [ ] Add `src/test/capture_realism.gd`. It boots the Hollywood venue, captures a fixed shot
list (entrance day, boulevard/skyline day, boulevard night), and can swap textures at
runtime from `--skyline=` / `--brick=` / `--concrete=` / `--asphalt=` user arguments. The
swap finds materials by their current texture, so baseline and candidate frames use the
same camera. Writes to `user://screenshots/realism/<tag>/`.
- [ ] Capture the baseline (current assets) and the candidate set (v2 skyline + textures), and
copy them into `docs/screens/realism/<run>/{baseline,candidate}/`.
### Step 6 — Compare against the realistic target
- [ ] Run `scene_concepts.py realism` on baseline and candidate. Record the metric deltas and the
vision scores, and note which candidate textures/backdrops win.
- [ ] Note the remaining realism gaps (sky/fog, lighting, building geometry, NPC fidelity) as
follow-up tasks below.
### Step 7 — Adopt the winners (after the in-flight normal-map/AO work is committed)
- [ ] Point `WorldBuilder.T_SKYLINE` at the chosen v2 skyline (separate day/night textures through
`set_night_mode`), and retune `albedo_color` for the realistic strip.
- [ ] Switch `materials.gd` / `world_builder.gd` surface preloads to the chosen v2 tiles + normal
maps, keeping the current UV scales. Update `test_materials.gd` / `test_world.gd`.
- [ ] Regenerate `docs/screenshots/` with `capture_screenshots.gd`, then run
`screen_designs.py compare` + `judge` and `scene_concepts.py realism`. There must be no
`diff` verdict regressions, and realism scores must not drop.
- [ ] Update `README.md` (tool usage + gallery), `MEMORY.md` and `docs/architecture.md`.
## Future ideas (optional, not scheduled)
- [ ] Live 3D body-camera replay (the timeline is text-only today).