Plan the v0.6.0 graphics pass and add Blender-authored NPC assets
This commit is contained in:
1 parent
a27e8cb74c
commit
b24d0aeb61
33 files changed
+1005
-2
No files matched your search
@@ -0,0 +1,85 @@
|
||||
# ADR-0013: Blender-authored NPC characters and baked materials
|
||||
|
||||
- **Status:** Proposed
|
||||
- **Date:** 2026-11-01
|
||||
|
||||
## Context
|
||||
|
||||
NPCs are the procedural capsule-and-box rig from
|
||||
[ADR-0010](0010-procedural-npc-presentation.md): articulated `Node3D` limbs,
|
||||
flat `StandardMaterial3D` colors, and sphere hair/eyes. ADR-0010 accepted this
|
||||
as a placeholder and recorded that a later skinned-mesh pass would replace the
|
||||
rig while keeping the `Head` contract. The props already moved to generated
|
||||
`.glb` assets ([ADR-0012](0012-surface-materials-and-generated-props.md)), but
|
||||
people remain the lowest-fidelity part of the scene: no UVs, no baked normal or
|
||||
ambient-occlusion maps, and silhouettes built from capsules.
|
||||
|
||||
The project renders with the **GL Compatibility** backend (no SSAO/SSIL), so
|
||||
visual quality has to come from the assets and baked maps rather than a renderer
|
||||
change. CI must stay offline: the Blender step is a developer tool, not a build
|
||||
dependency.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **Author the NPC body in Blender** and export a skinned, UV-mapped base mesh
|
||||
as `assets/models/generated/npc_base.glb`, driven by a new
|
||||
`tools/npc_pipeline.py` (`build` / `audit`) invoked through the Blender
|
||||
flatpak in headless mode. The `.blend` source is committed under
|
||||
`assets/models/npc/`.
|
||||
2. **Bake material maps in Blender** — neutral albedo, normal, and a packed ORM
|
||||
(occlusion/roughness/metallic) map per material slot (`skin`, `cloth`,
|
||||
`pants`, `accessory`, `hair`). Ambient occlusion is baked into the albedo or
|
||||
the ORM R channel, since Compatibility has no screen-space AO.
|
||||
3. **Keep a procedural fallback.** `NpcAvatar` loads the imported `PackedScene`
|
||||
when it exists and falls back to the current `_build_body()` rig otherwise,
|
||||
mirroring `WorldBuilder._add_prop_model()`. Committed assets mean CI never
|
||||
needs Blender, and the headless suite runs against the fallback when the
|
||||
import is absent.
|
||||
4. **Preserve the `Head` contract and seed determinism.** The armature bones are
|
||||
named after the current nodes (`Head`, `HipL/R`, `KneeL/R`, `ShoulderL/R`,
|
||||
`ElbowL/R`, `HandL/R`); `outfit_for` and friends stay pure and drive the
|
||||
material slots. A thin `_set_limb_rotation()` wrapper lets `_animate()` /
|
||||
`_idle_layer()` target either `Node3D` pivots or `Skeleton3D` bones.
|
||||
5. **AI tooling supplies art direction only.** `tools/asset_pipeline.py`
|
||||
generates seamless clothing albedos, `tools/model_pipeline.py`'s palette
|
||||
helpers (`dominant_colors`, `assign_roles`) derive per-role palettes from
|
||||
concept sheets, and `tools/screen_designs.py judge` closes the loop. All AI
|
||||
outputs are committed; generation is dev-time and never a runtime or CI
|
||||
dependency.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- NPCs gain real geometry, UVs, and baked normal/AO/roughness, so they read as
|
||||
people at cinematic distance without a renderer switch.
|
||||
- Skinned meshes collapse ~33 draw calls per avatar into one, which can offset
|
||||
the skinning cost at `MAX_LIVE_NPCS = 16`.
|
||||
- The asset contract stays behind the same `.glb` + audit discipline that props
|
||||
already use; the procedural fallback keeps offline CI deterministic.
|
||||
- AO baked into the maps compensates for the absence of SSAO in Compatibility.
|
||||
|
||||
### Negative
|
||||
|
||||
- A new toolchain (Blender flatpak + `npc_pipeline.py`) and its path/colour-space
|
||||
gotchas enter the repo; contributors must run `audit` after changing the
|
||||
`.blend`.
|
||||
- Skinning shifts cost from draw calls to CPU; the 16-NPC frame budget must be
|
||||
re-measured before raising the cap.
|
||||
- Two avatar backends (skinned + fallback) must stay behaviourally identical, or
|
||||
tests that assume the fallback will silently pass against one and not the
|
||||
other.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
- **Keep the procedural rig and only add textures.** Rejected: textures on
|
||||
capsules do not fix the silhouette; the rig is the fidelity ceiling.
|
||||
- **Use Mixamo / a downloaded skinned character.** Rejected: licensing and
|
||||
retargeting overhead exceed the value; a low-poly base authored in-house keeps
|
||||
the art direction and the `Head`/bone contract under our control.
|
||||
- **Switch the renderer to Forward+ for SSAO/SSIL.** Rejected as a prerequisite;
|
||||
it would break the Web export assumptions. A desktop-only Forward+ preset
|
||||
remains a follow-up, not a dependency of this decision.
|
||||
- **A 3D-model (image-to-mesh) API instead of Blender.** Rejected for characters;
|
||||
output topology is not controllable enough to satisfy the bone/UV contract.
|
||||
It remains a possible prop-only follow-up (ADR-0012).
|
||||
Reference in new issue
Block a user