What does it do?
In 2.92 If you add a new material and select "use nodes" you are presented with two nodes, neither of which has name "Diffuse BSDF" ... so one imagines that this was the case back when the script was written.
The Python console.
The expectation isn't that you will be a python wizard overnight. The beauty of python is it doesn't need to be compiled, hence can take lines of code and run them in the console and see what happens.
When assigning a variable like, below, no feedback is good news, it worked.
>>> color = D.materials.new("Color")
>>> color.use_nodes = True
Can test in UI to see that there is a new material named "Color" or "Color.001" if run again.. etc etc and it is to use nodes...
Next line, uh oh have seen this before.
blenders api descriptions is too cryptic for me to understand properly
>>> Diffuse_BSDF = color.node_tree.nodes['Diffuse BSDF']
Traceback (most recent call last):
File "<blender_console>", line 1, in <module>
KeyError: 'bpy_prop_collection[key]: key "Diffuse BSDF" not found'
Or in lay-mans terms there is no node named "Diffuse BSDF", if only cryptic crosswords were as simple.
Let's see what nodes this newly created material does have, hmmm they look familiar.
>>> color.node_tree.nodes.keys()
['Principled BSDF', 'Material Output']
Can be sure that if a new material is added, use nodes it has these two nodes, in same order.
Ok then lets have a go at making the make_material
function work, paste this in text editor and run script..
import bpy
def make_material(color):
alpha = 1.0
red, green, blue, alpha = color
color_name = '%(red)03d_%(green)03d_%(blue)03d' % {"red": red, "green": green, "blue": blue}
color = bpy.data.materials.new(color_name)
color.use_nodes = True
bsdf, output = color.node_tree.nodes
bsdf.inputs[0].default_value = [red, green, blue, alpha]
return color
make_material((1, 0, 0, 1))
And there it is
IMO a little confusing passing a color list, then making a material with same variable name, so let's refine this further, by instead calling the new material mat
import bpy
def make_material(color):
red, green, blue, alpha = color
color_name = '%(red)03d_%(green)03d_%(blue)03d' % {"red": red, "green": green, "blue": blue}
mat = bpy.data.materials.new(color_name)
mat.use_nodes = True
bsdf, output = mat.node_tree.nodes
bsdf.inputs[0].default_value = color
return mat
make_material((1, 0, 0, 1))
_Note: haven't tested to see if any other changes are needed, or amended to instead use a "Diffuse BSDF" node.+
Optimizing.
The script is going to be sloooooooooooooooooooow.
Object creation slows over time
Python performance with Blender operators
As it is to create each cube for an image on M x N pixels the script is calling 2 x M x N operators.
Instead Create one object and duplicate it. Even if this lone object is created with operator, it will be one call. Can be done with none. Consider even using the array mnodifier to very quickly make N x M grid of cubes then separate
How can I create many objects quickly?
Copying an object with python without actually creating a new object
Use numpy
to read the image pixels. See Read pixel color with foreach_get() on image data (looping is one almost always a rate determining step.)
Make one material. Randomly coloring with script doesn't work correctly which if used in conjunction with this would mean making one material, and assigning pixel color to material color of the voxel.
Vertex colors. Another option is to have no materials and set vertex colors to pixel color.
You can export it from blender as an FBX and then import to Unity.
Unity will create a materials file from the vertex colors you don't
need to do anything special.
How to get random color variation on a single mesh?
(Suggest array method here to create object NxM array of cubes, apply array, use the order to set the vertex colors en masse with numpy, separate into multiple objects.)
Making these changes will see huge improvement in speed gain.