1
$\begingroup$

The Original Problem (SOLVED, thank you Gorgious) :

The script below is what I'm using, now. It converts the materials to Principle BSDF, then sets some properties, then flips the normals. This prepares me to take imported .mqo models and export them to .glb for 3D modeling purposes.


import bpy

# Convert Materials to Principled BSDF
for mat in bpy.data.materials:
    if not mat.use_nodes:
        continue
    nodes = mat.node_tree.nodes
    specular = next((n for n in nodes if isinstance(n, bpy.types.ShaderNodeEeveeSpecular)), None)
    output = next((n for n in nodes if isinstance(n, bpy.types.ShaderNodeOutputMaterial)), None)
    if specular is None or output is None:
        continue
    principled = nodes.new("ShaderNodeBsdfPrincipled")
    principled.inputs[0].default_value = specular.inputs[0].default_value
    principled.inputs[9].default_value = specular.inputs[2].default_value
    principled.inputs[19].default_value = (0, 0, 0, 0)
    principled.inputs[21].default_value = 1 - specular.inputs[4].default_value
    principled.inputs[14].default_value = specular.inputs[6].default_value
    principled.inputs[15].default_value = specular.inputs[7].default_value
    
    principled.location = (specular.location[0] - 100, specular.location[1])    
    mat.node_tree.links.new(principled.outputs[0], output.inputs[0])
    nodes.remove(specular)
 
 
    
# Set Material Properties
def remove_links(socket: bpy.types.NodeSocket, node_tree: bpy.types.NodeTree):
    for link in socket.links:
        node_tree.links.remove(link)

def fix_node(node: bpy.types.Node, node_tree: bpy.types.NodeTree):
    if node.type == 'BSDF_PRINCIPLED':
        node.inputs['Specular'].default_value = 0.5
        node.inputs['Metallic'].default_value = 0.0
        remove_links(node.inputs['Alpha'], node_tree)
        remove_links(node.inputs['Normal'], node_tree)

def fix_material(material: bpy.types.Material):
    for node in material.node_tree.nodes:
        fix_node(node, material.node_tree)

def fix_selected():
    for object in bpy.context.selected_objects:
        for material_slot in object.material_slots:
            fix_material(material_slot.material)



# Flip Normals
scn = bpy.context.scene
sel = bpy.context.selected_objects
meshes = [o for o in sel if o.type == 'MESH']

for obj in meshes:
    bpy.context.view_layer.objects.active = obj
    bpy.ops.object.editmode_toggle()
    bpy.ops.mesh.select_all(action='SELECT')
    bpy.ops.mesh.flip_normals()
    bpy.ops.object.mode_set()


if __name__ == "__main__":
    fix_selected()
$\endgroup$
3
  • $\begingroup$ Are there things linked to the specular bsdr or are there only values ? You can check it out by going in the shader editor. If there are link going out of the left of the shader node, then there are links. For context I'm asking this because it would be pretty easy to convert specular bsdf to principled but a little bit harder if there are links $\endgroup$
    – Gorgious
    Commented Feb 13, 2022 at 20:45
  • $\begingroup$ does it look like this or that ? $\endgroup$
    – Gorgious
    Commented Feb 13, 2022 at 20:59
  • $\begingroup$ Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. $\endgroup$
    – Community Bot
    Commented Feb 13, 2022 at 21:03

1 Answer 1

1
$\begingroup$

This will swap all Specular BSDf nodes to Principled BSDF nodes. However the specular color parameter isn't available on the Principled BSDF so you may experience loss of data there.

enter image description here enter image description here

import bpy

for mat in bpy.data.materials:
    if not mat.use_nodes:
        continue
    nodes = mat.node_tree.nodes
    specular = next((n for n in nodes if isinstance(n, bpy.types.ShaderNodeEeveeSpecular)), None)
    output = next((n for n in nodes if isinstance(n, bpy.types.ShaderNodeOutputMaterial)), None)
    if specular is None or output is None:
        continue
    principled = nodes.new("ShaderNodeBsdfPrincipled")
    principled.inputs[0].default_value = specular.inputs[0].default_value  # Color
    principled.inputs[9].default_value = specular.inputs[2].default_value  # Roughness
    principled.inputs[19].default_value = specular.inputs[3].default_value  # Emission color
    principled.inputs[21].default_value = 1 - specular.inputs[4].default_value  # Alpha
    principled.inputs[14].default_value = specular.inputs[6].default_value  # Clearcoat
    principled.inputs[15].default_value = specular.inputs[7].default_value  # Clearcoat roughness
    
    principled.location = (specular.location[0] - 100, specular.location[1])    
    mat.node_tree.links.new(principled.outputs[0], output.inputs[0])
    nodes.remove(specular)
$\endgroup$
3
  • $\begingroup$ Hey Gorgious, this worked! There's only one last value that I'm unsure on how to set. I would like to change the "Emission" (specifically, the "H" / "S" / "V" / "A" that it default displays)... all to zero. I'm currently looking around for the answer, but haven't been able to combine it into the script, yet. Any ideas on this? $\endgroup$ Commented Feb 14, 2022 at 17:01
  • $\begingroup$ @DerekHettinger sure replace the line principled.inputs[19].default_value = specular.inputs[3].default_value with principled.inputs[19].default_value = (0, 0, 0, 0) $\endgroup$
    – Gorgious
    Commented Feb 14, 2022 at 17:05
  • $\begingroup$ Thank you, again. The OP reflects the script I'm using. Pretty much, 1 click to prepare the models for export into .GLB. You saved me a TON of time! $\endgroup$ Commented Feb 14, 2022 at 17:39

You must log in to answer this question.

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