3
$\begingroup$

I have to import various fbx file scenes , bringing in a large amount (>10.000 Objects) into the scene with each single import. Each import scene stands on its own. Imported fbx files will not be combined. Each object has its own material assigned, and each single material is a material with a principled BSDF. But there are only a few different colors (for example, 10.000 Objects have 10.000 unique materials, but 3333 green ones, 3333 red ones, 3334 blue ones). All of them have the sample principled shader material, they only differ in the diffuse color setting.

The materials in the imported scene are named as follows: enter image description here enter image description here

the first digits are always the RGB value channels of the diffuse color of the principled bsdf. The suffix after the "." is the number of copies of the material.

the overal number of materials will differ from scene to scene, as this is just an example for one scene. Other scenes that will be imported will differ in number of objects, as well as in number of materials.

Is there a way to merge all shaders with the same settings, so that in the end there are only three materials instead of 10.000? In simple words: Merge aller materials with the same diffuse color. means 3333 object share one green shader, 3333 objects share one red shader, and 3334 objects share one blue shader? (The numbers are just examples, not the actual amount). In the end, the number of materials will be drastically lower.

I found a similiar topic here, but this one works only for Blender internal and causes an error in Blender 2.8.

Thanks for help!

$\endgroup$

1 Answer 1

2
$\begingroup$
import bpy

for obj in bpy.data.objects.keys():
    bpy.context.view_layer.objects.active = bpy.data.objects[obj]
    activeobj = bpy.context.active_object 
    try:
        if "." in activeobj.active_material.name:            
            mat = bpy.context.object.active_material.name[:-4]
            activeobj.data.materials[0] = bpy.data.materials[mat]
    except:
        pass

for mat in bpy.data.materials.keys():
    if bpy.data.materials[mat].users == 0:
        bpy.data.materials.remove(bpy.data.materials[mat])

Try this out and let me know

$\endgroup$
2
  • $\begingroup$ Dear Arthur, your script solved the problem. Thank you very much for your help! The script reduced the amount of materials from 7.800 to 37. One thing i had to modify: for some materials, there were more than 1000 copies. Means that the code line mat = bpy.context.object.active_material.name[:-4] has to have a "5" instead of a "4" at the end. Then, the modified script has to be started again to eliminate the material with more than 1000 copies. Again, thank you very much for your support! $\endgroup$ Oct 14, 2019 at 8:30
  • $\begingroup$ Didn't think of that! But glad you got it working in the end :) $\endgroup$
    – globglob
    Oct 14, 2019 at 8:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .