In Blender/Python 2.8, I can't get my code to create the surface node I want (it creates a shader node along with a surface node that I don't want). The objective is to assign an image texture to an object as seen in three related posts (1, 2 and 3):

The manual process produces the desired result by setting up the node as follows: Surface node Diffuse BSDF

In Python I am attempting to do the same (code below), but the results aren't working out. First I'll show the output, then the code:

Here's the objectionable output:

enter image description here

And here's the node tree as created by my code; when I make the manual adjustments I note in the picture I get the final result that I want:

enter image description here

My flawed code is below. Before you criticize the obvious problem (that I am creating shaders), I have tried other approaches (replacing "Shader" with "Surface" and various other words) without success. I am also baffled as to why the "Principled BSDF" node appears out of nowhere.

Here's my code. Your suggestions would be highly appreciated. Thanks in advance!

matP = bpy.data.materials.get(matP_name)
if matP is None:
    matP = bpy.data.materials.new(matP_name)
nodes = matP.node_tree.nodes
diffuse_BSDF = matP.node_tree.nodes.new(nodeID)
imgTex = bpy.data.images.load(path)
node_texture = nodes.new(type='ShaderNodeTexImage')
node_texture.image = imgTex
node_texture.location = 0,200
links = matP.node_tree.links
link = links.new(node_texture.outputs[0], nodes.get('Diffuse BSDF').inputs[0])
  • 1
    $\begingroup$ If I read correctly this code does not link the diffuse to the output. Also creating a new material will create principled and output by default. So you need to clear them. material.node_tree.links.clear() material.node_tree.nodes.clear() $\endgroup$ – lemon Jul 29 at 16:02
  • $\begingroup$ @lemon Doesn't this create the link? link = links.new(node_texture.outputs[0], nodes.get('Diffuse BSDF').inputs[0]) $\endgroup$ – vndep Jul 29 at 16:11
  • 1
    $\begingroup$ Yes but between texture and diffuse, not between diffuse and output $\endgroup$ – lemon Jul 29 at 16:11
  • $\begingroup$ @lemon What python code would link diffuse and output? $\endgroup$ – vndep Jul 29 at 16:13

Small code that can bring the indication you need.

import bpy

# Clear all nodes in a mat
def clear_material( material ):
    if material.node_tree:

# Create a node corresponding to a defined group
def instanciate_group( nodes, group_name ):
    group = nodes.new( type = 'ShaderNodeGroup' )
    group.node_tree = bpy.data.node_groups[group_name]

materials = bpy.data.materials

mat_name = 'test'

material = materials.get( mat_name )

if not material:
    material = materials.new( mat_name )

# We clear it as we'll define it completely
clear_material( material )

material.use_nodes = True

nodes = material.node_tree.nodes
links = material.node_tree.links

output = nodes.new( type = 'ShaderNodeOutputMaterial' )

diffuse = nodes.new( type = 'ShaderNodeBsdfDiffuse' )

#With names
link = links.new( diffuse.outputs['BSDF'], output.inputs['Surface'] )
#Or with indices
#link = links.new( diffuse.outputs[0], output.inputs[0] )

Note: when you create a new material (materials.new(...)), it creates two nodes by default (principled linked to ouput).

  • 1
    $\begingroup$ thanks a lot ... that solves the problem. $\endgroup$ – vndep Jul 29 at 17:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.