Native shared-material import pilot
===================================

Godot's built-in workflow solves this small shared-material job. No add-on is required for the tested case.

Tested: Godot 4.7.2 stable (ed1daf0bf), Blender 4.5.14 LTS (62c1db4208e8), Linux x86-64. The original fixture is a wall, floor and post with one 64x64 atlas and one Blender material named SharedAtlas. All geometry, texture, harness code and instructions were AI-generated for this experiment. This is a reproducibility fixture, not a production asset pack.

What was measured
-----------------

                                 Loaded materials/textures  Project PNGs  Embedded GLB image bytes
Default separate GLBs                      3 / 3             3 (1527 B)           1527
GLBs + Extract Once                        1 / 1             3 (1527 B)           1527
GLBs + Extract Once + Discard textures      1 / 1             1 ( 509 B)           1527
Separate glTF + shared atlas + Extract Once  1 / 1             1 ( 509 B)              0

Loaded resource identity, project files and source payloads are different things. Extract Once reuses a material and its referenced texture but does not remove the other GLB-extracted PNGs. Discard All Textures prevents new extracted image files when an existing external material already points to a canonical texture; it does not rewrite the GLB sources or clean old files. Separate glTF exports reference one external atlas and contain no embedded image payload.

The checker compares actual image bytes and base-level decoded pixels. GLB-extracted textures defaulted to mipmaps here; the external PNG initially did not. The recorded cache-file sizes therefore are not a controlled compression comparison. GPU memory, rendered appearance, exported PCK/game size and performance were not measured.

Repeatable native workflow
--------------------------

1. Keep a stable, unambiguous Blender material name and a canonical atlas. In Blender export each selected object as glTF Separate (.gltf + .bin + textures), into the same model folder with the same textures subfolder. Check that the three glTF image URIs point to the same atlas file.
2. In Godot select the model imports and set Materials > Extract to Extract Once, with one common Extract Path (this fixture uses res://materials). Reimport. Do not choose Extract and Overwrite if you want to keep Godot edits.
3. Edit the shared .tres material. Re-export changed geometry to the original model paths, retaining the .import settings and stable material names. Reimport.

The project-wide equivalent tested by this harness is:
[importer_defaults]
scene={"materials/extract": 1, "materials/extract_format": 0, "materials/extract_path": "res://materials"}

The documented per-material alternative is Advanced Import Settings > Actions > Extract Materials for the first model, then Materials > Use External for the others, pointing them to the same .tres. The explicit Use External mapping is also exercised by case 06. UI button interaction itself was not tested; the harness writes Godot's native settings and runs the real importer. No post-import material-replacement plug-in is used.

Revision and name boundaries
---------------------------

In cases 02 and 04, Godot roughness was changed from 0.73 to 0.123 and tint to (0.32, 0.65, 0.9, 1). Blender revision r2 raised the wall height from 2 to 2.5. Reimport changed the mesh vertices/AABB while preserving the material file byte-for-byte, its path/UID, edits, and one shared loaded instance.

For headless fixture authoring, the edit script saves those values with ResourceSaver and explicitly retains the pre-existing UID with ResourceSaver.set_uid. Runtime saves do not serialize UIDs automatically. The subsequent native import test does not repair or rewrite the material; identity is compared after the edit against after reimport.

Case 05 renames the wall material: Extract Once creates a different material and the old edit no longer applies to that wall. Case 06 explicitly maps the renamed material to the existing .tres and restores sharing. This is a documented remapping boundary.

Case 07 deliberately exports different PBR definitions under the same material name. Extract Once reuses one file by name; it does not determine whether those definitions mean the same material. The floor's definition won in these runs. Do not rely on import order: use distinct material names/paths when the materials are intentionally different.

Reproduce on Linux
------------------

Use the tested versions or record any substitutions. Blender and Godot executables are not included; no paid tools or third-party packages are required. The harness restricts engine subprocesses to CPU cores 0 and 1 at nice 15, uses headless execution, and disables GPU backends. The host must permit those CPU IDs.

From the extracted folder:
python3 scripts/run_pilot.py all --godot /path/to/Godot --blender /path/to/blender --output-root fresh-run
python3 scripts/account.py fresh-run

Use a new output directory for every run; the harness refuses to overwrite cases. Generated .blend sources pack the atlas. The ZIP includes glTF/GLB inputs, existing imported project configurations and read-only observations, but omits engine binaries, import caches and machine logs. A fresh run recreates its own sources, logs and comparisons. Case 04 is saved after the edited-material geometry revision.

RESULTS.json summarizes the checked run. evidence/ contains resource observations, image accounting and revision comparisons. MANIFEST.json hashes every delivered file except itself. Official references are in SOURCES.json. Files are licensed under LICENSE.txt.
