The title is general: how can we use the API to edit Principled BSDF properties?

More specifically, I have a mesh that has vertex colors in it. The colors are fine, and I can use the mouse to have vertex colors as base color using the Shader Editor. Likewise, I can use the Material Properties and select "Vertex Colors | Color" for the base color of the material assigned to the mesh. This is all fine and both are equivalent ways.

However, how to accomplish that programmatically, via the API? I could do that in 2.7x but don't seem to be able to do the same in 2.81. Any idea?

EDIT: here a minimal example that works with 2.7x:

import bpy
mat = "MyMaterial"

Traceback (most recent call last):
  File "<blender_console>", line 1, in <module>
AttributeError: 'Material' object has no attribute 'use_vertex_color_paint'
  • 1
    $\begingroup$ The concept remains pretty much the same in 2.8x. Perhaps you can add your current script for 2.79 to your question and explain what particular part you have trouble implementing in 2.81. $\endgroup$
    – Robert Gützkow
    Dec 4, 2019 at 22:34
  • $\begingroup$ Thanks for the suggestion. I've just added above. The "use_vertex_color_paint" has been removed from the current API, according to the release notes. $\endgroup$
    – amwink
    Dec 5, 2019 at 1:43
  • $\begingroup$ This post on Stack overflow stackoverflow.com/a/36194568/808940 just use "ShaderNodeVertexColor" instead. $\endgroup$
    – Moog
    Dec 5, 2019 at 2:30
  • $\begingroup$ Thanks. It seems this would also work. The one below is straight to the point and very general, so I'm taking it as 'the' answer. $\endgroup$
    – amwink
    Dec 5, 2019 at 12:30

1 Answer 1


Add and link the vertex colour node.

Adds a new material using mat = bpy.data.materials.new()

Recommend: almost never use bpy.ops.materials.new() The material bpy.data.materials[mat] in script in question is confusing and varies dependant on pre existing materials "Material" and "MyMaterial".

Notice I used the index of the io when making links. Could use vcol.outputs["Color"] for vcol.outputs[0], however if the user is using a different language, then "Color" will be in that language.

The principled bsdf base color is input 0. A simple test in python console to save counting by eye.

>>> for i, o in enumerate(bsdf.inputs):
...     i, o.name
(0, 'Base Color')
(1, 'Subsurface')
(2, 'Subsurface Radius')
(3, 'Subsurface Color')
(4, 'Metallic')
(5, 'Specular')
(6, 'Specular Tint')
(7, 'Roughness')
(8, 'Anisotropic')
(9, 'Anisotropic Rotation')
(10, 'Sheen')
(11, 'Sheen Tint')
(12, 'Clearcoat')
(13, 'Clearcoat Roughness')
(14, 'IOR')
(15, 'Transmission')
(16, 'Transmission Roughness')
(17, 'Emission')
(18, 'Alpha')
(19, 'Normal')
(20, 'Clearcoat Normal')
(21, 'Tangent')

Script to add material, add vertex colour node, link it to base color of bsdf.

import bpy

newmat = bpy.data.materials.new("VertCol")
newmat.use_nodes = True
node_tree = newmat.node_tree
nodes = node_tree.nodes

bsdf = nodes.get("Principled BSDF") 
# alternatively

output, bsdf = nodes

assert(bsdf) # make sure it exists to continue

vcol = nodes.new(type="ShaderNodeVertexColor")
vcol.layer_name = "VColor" # the vertex color layer name

# make links

node_tree.links.new(vcol.outputs[0], bsdf.inputs[0])
  • 1
    $\begingroup$ This worked perfectly. Also, looping and providing all indices comes in handy, many thanks. I've upvoted but because my rep is still <15 it seems it won't appear public yet. Thanks! $\endgroup$
    – amwink
    Dec 5, 2019 at 12:29
  • 1
    $\begingroup$ Now checked! Thanks! $\endgroup$
    – amwink
    Dec 5, 2019 at 14:29

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.