Refine NPC fabric UVs and remove baked AO blotches
Full build / Import + headless tests (push) Successful in 37s
Full build / Full desktop build + optional release (push) Skipped

This commit is contained in:
zwitschi committed 2026-11-02 20:28:25 +01:00
1 parent 31574b8d82
commit d7220c1a0a
12 files changed
+64 -13

No files matched your search

+28
View File
@@ -3,6 +3,7 @@ extends RefCounted
## styles, queue slots, LOD tiers/labels, and the articulated rig structure.
const NpcAvatar := preload("res://src/game/npc_avatar.gd")
const Materials := preload("res://src/game/materials.gd")
const NpcProfile := preload("res://src/core/npc_profile.gd")
const Rules := preload("res://src/core/rules.gd")
@@ -333,6 +334,33 @@ func test_skinned_outfit_tints_the_material_slots() -> bool:
avatar.free()
return a and b and c and d
func test_fabric_uv_scale_avoids_the_baked_ao_pattern() -> bool:
var avatar := _avatar(Rules.NpcType.TOURIST, 44)
var mi := avatar.find_child("npc_base", true, false) as MeshInstance3D
var fabric := 0
var skin_ao := false
var problems: Array[String] = []
for index in mi.mesh.get_surface_count():
var source := mi.mesh.surface_get_material(index)
var material := mi.get_surface_override_material(index) as StandardMaterial3D
if source == null or material == null:
continue
var slot := str(source.resource_name)
if slot in ["cloth", "pants"]:
fabric += 1
if not material.uv1_scale.is_equal_approx(
Materials.NPC_FABRIC_UV_SCALE):
problems.append("%s uv=%s" % [slot, str(material.uv1_scale)])
if material.ao_enabled:
problems.append("%s still uses baked AO" % slot)
elif slot == "skin" and material.ao_enabled:
skin_ao = true
var a := TestUtils.check(fabric > 0 and problems.is_empty(),
"cloth/pants use the fine-UV scale and skip baked AO (%s)" % str(problems))
var b := TestUtils.check(skin_ao, "skin keeps its baked AO")
avatar.free()
return a and b
func test_forced_fallback_still_builds_the_procedural_rig() -> bool:
var profile := NpcProfile.new()
profile.id = "fallback_test"