1
$\begingroup$

I have imported Google Map tiles as a single object with many materials using Blosm. By default, every material has an Emission shader applied. I would like to change this Emission node to a Diffuse BSDF so that I can better control the render output.

I know how to do this on an individual Material manually. See the image below illustrating the final node structure I want. I need to do this to hundreds of materials that have the same node structure, but different texture maps. Therefore, I believe the right solution would be to run a Python script, but I know virtually nothing about coding.

enter image description here

Can anyone help me modify this script I found to work? When I try to modify this code it returns a NoneType error on line starting with emmNode.

import bpy

emmNode = mat.node_tree.nodes.new(type="ShaderNodeEmission") # creates Emission shader node. Store the node in a variable. By default Emission value is 1
origNode = mat.node_tree.nodes["Principled BSDF"] # store original BSDF node in a variable.
OutputNode = mat.node_tree.nodes["Material Output"] # store Materil Output node in a variable.
    
origCoordinates = origNode.location # get location of the original BSDF node and store it in a variable
emmNode.location = origCoordinates # set the coordinates of new emmision node same as the original BSDF has

for l in mat.node_tree.links: # for all links
    if l.to_socket == origNode.inputs[0]: # if link destination is in THE BSDF node
        inputNodeOut = l.from_socket # store into variable Base Color input socket
        mat.node_tree.links.new(emmNode.inputs[0], inputNodeOut) # re-link original input socket into new Emission node
    
mat.node_tree.links.new(OutputNode.inputs[0], emmNode.outputs[0]) # creates link between new emission Shader and Material Output
mat.node_tree.nodes.remove(origNode) # deletes original BSDF node

Any help or insight would be greatly appreciated!

$\endgroup$

1 Answer 1

0
$\begingroup$

Try this, it modifies the materials on all selected objects. Save beforehand just in case.

import bpy

def swap_emission_for_diffuse(mat):
    if not mat.use_nodes: return
    nodes = mat.node_tree.nodes
    links = mat.node_tree.links

    # Find all emission nodes
    emi_nodes = [n for n in nodes if n.type == 'EMISSION']

    for emi_node in emi_nodes:
        x, y = emi_node.location

        # Record sockets connected to the emission node so
        # we can recreate them on the diffuse node
        in_sockets = []
        out_sockets = []
        for link in links:
            if link.to_socket == emi_node.inputs['Color']:
                in_sockets.append(link.from_socket)
            if link.from_socket == emi_node.outputs[0]:
                out_sockets.append(link.to_socket)

        nodes.remove(emi_node)
        dif_node = nodes.new(type='ShaderNodeBsdfDiffuse')

        dif_node.location = x, y
        for soc in in_sockets: links.new(soc, dif_node.inputs['Color'])
        for soc in out_sockets: links.new(dif_node.outputs[0], soc)

for ob in bpy.context.selected_objects:
    for slot in ob.material_slots:
        if not slot.material: continue
        swap_emission_for_diffuse(slot.material)
$\endgroup$
1
  • $\begingroup$ Incredible. Worked perfectly. Thank you very much! I've been battling with this all morning. $\endgroup$
    – RadioTrout
    Jan 5 at 22:29

You must log in to answer this question.

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