fix(gltf): append materials (link=False) for proper PBR export to GLB

Linked materials are external references — Blender's GLTF exporter cannot
traverse their node trees to extract Principled BSDF PBR values (metallic,
roughness, base color, normal maps). Appended materials are local copies
that the exporter can fully traverse.

Changes:
- asset_library.py: add link=True parameter (default unchanged for renders)
- export_gltf.py: call apply_asset_library_materials with link=False
- export_gltf.py: add export_materials='EXPORT' + export_image_format='AUTO'
  to embed textures and ensure full PBR data in the GLB

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 15:11:33 +01:00
parent 5ee4b2e3b5
commit e2eda92d82
2 changed files with 18 additions and 9 deletions
+9 -6
View File
@@ -13,13 +13,16 @@ import logging
logger = logging.getLogger(__name__)
def apply_asset_library_materials(blend_path: str, material_map: dict) -> None:
"""Link materials from an asset library .blend and apply them to mesh slots.
def apply_asset_library_materials(blend_path: str, material_map: dict, link: bool = True) -> None:
"""Load materials from an asset library .blend and apply them to mesh slots.
Args:
blend_path: Absolute path to the .blend library file.
material_map: Mapping of current slot material name -> library material name.
E.g. {"Steel--Stahl": "SCHAEFFLER_010101_Steel-Bare"}
link: If True (default), link materials (external reference, good for rendering).
If False, append materials (local copy — required for GLB/GLTF export so
that the exporter can traverse Principled BSDF node trees for PBR values).
"""
import bpy # type: ignore[import]
@@ -28,12 +31,12 @@ def apply_asset_library_materials(blend_path: str, material_map: dict) -> None:
target_names = set(material_map.values())
# Link materials from the library
with bpy.data.libraries.load(blend_path, link=True, assets_only=True) as (src, dst):
# Link or append materials from the library
with bpy.data.libraries.load(blend_path, link=link, assets_only=True) as (src, dst):
dst.materials = [name for name in src.materials if name in target_names]
linked = {m.name for m in dst.materials if m is not None}
logger.info("Linked %d materials from %s", len(linked), blend_path)
loaded = {m.name for m in dst.materials if m is not None}
logger.info("%s %d materials from %s", "Linked" if link else "Appended", len(loaded), blend_path)
# Apply to all mesh object material slots
for obj in bpy.data.objects: