diff --git a/render-worker/scripts/asset_library.py b/render-worker/scripts/asset_library.py index 895c8a9..e611c6f 100644 --- a/render-worker/scripts/asset_library.py +++ b/render-worker/scripts/asset_library.py @@ -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: diff --git a/render-worker/scripts/export_gltf.py b/render-worker/scripts/export_gltf.py index 4a0195e..3be4207 100644 --- a/render-worker/scripts/export_gltf.py +++ b/render-worker/scripts/export_gltf.py @@ -113,20 +113,26 @@ def main() -> None: mark_sharp_edges_by_proximity(sharp_edge_midpoints) print(f"Marked sharp edges from {len(sharp_edge_midpoints)} hint points") - # Apply asset library materials if provided + # Apply asset library materials if provided. + # link=False (append) is required for GLB export: the GLTF exporter can only + # traverse local (appended) Principled BSDF node trees to extract PBR values. + # Linked materials are external references whose node data is not accessible. if args.asset_library_blend and material_map: import os sys.path.insert(0, os.path.dirname(__file__)) from asset_library import apply_asset_library_materials - apply_asset_library_materials(args.asset_library_blend, material_map) + apply_asset_library_materials(args.asset_library_blend, material_map, link=False) - # Export GLB + # Export GLB with full PBR material data try: bpy.ops.export_scene.gltf( filepath=args.output_path, export_format="GLB", export_apply=True, use_selection=False, + export_materials="EXPORT", # export all materials (Principled BSDF → glTF PBR) + export_image_format="AUTO", # embed textures (base color, normal, roughness maps) + export_colors=False, # skip vertex colors (we use library materials) ) except Exception as exc: print(f"GLB export failed: {exc}", file=sys.stderr)