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

+7 -1
View File
@@ -229,8 +229,14 @@ func test_skinned_outfit_tints_the_material_slots() -> bool:
var a := TestUtils.check(found == 5, "five material slots stay separate")
var b := TestUtils.check(tinted == found, "every slot carries the outfit tint")
var c := TestUtils.check(outfit["shirt"] != Color.WHITE, "seed gives a non-white outfit")
var ao_ok := false
for index in mi.mesh.get_surface_count():
var material := mi.get_surface_override_material(index) as StandardMaterial3D
if material != null and material.ao_enabled and material.ao_texture != null:
ao_ok = true
var d := TestUtils.check(ao_ok, "character slots carry the baked AO map")
avatar.free()
return a and b and c
return a and b and c and d
func test_forced_fallback_still_builds_the_procedural_rig() -> bool:
var profile := NpcProfile.new()