Create random materials and assign to objects in the scene

Hello friends,

I have a blender file that contains 6 different individual objects in the scene
I would like to assign them random materials that follow color gradient schemes (see examples in the attachment)

Any idea how to do it in Python?

I guess that it could be something like:

  • create Material1 with a random color (example HSV 0.1,1,1) and apply it to the first object
  • create Material2, assign the color that Material1 has -0.02 on the H value (which means 0.08,1,1), apply it to the second object
  • create Material3, assign the color that Material1 has -0.04 on the H value (which means 0.06,1,1), apply it to the third object
  • create Material4, assign the color that Material1 has -0.06 on the H value (which means 0.04,1,1), apply it to the fourth object
  • and so on…

Can someone help?

I would be fine also with other ways to reach a similar result

Thank you very much in advance

You may find the answers listed here helpful.

python - Randomly coloring with script doesn’t work correctly - Blender Stack Exchange

This snippet should nudge you in the right direction


import numpy as np
import bpy
from mathutils import Color, Vector

if __name__ == "__main__":
    bpy.data.batch_remove(bpy.data.objects)  # Uncomment to clear everything before running script
    bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)

    cubes = 10  # Number of cubes to instantiate

    mat = bpy.data.materials.new("My Material")
    mat.use_nodes = True
    node_tree = mat.node_tree
    nodes = node_tree.nodes

    principled = next(n for n in nodes if isinstance(n, bpy.types.ShaderNodeBsdfPrincipled))

    info = nodes.new(type="ShaderNodeObjectInfo")
    info.location = principled.location - Vector((200, 0))
    links = node_tree.links
    links.new(info.outputs["Color"], principled.inputs["Base Color"])

    hsv_base = Color((1, 0, 0))
    for i, hue in zip(range(cubes), np.linspace(0, 1, cubes + 1)):
        bpy.ops.mesh.primitive_cube_add(location=(0, i * 3, 0))  # This should be replaced by non-ops function if you have performance problems
        bpy.ops.object.material_slot_add()
        cube = bpy.context.active_object
        cube.material_slots[0].material = mat
        hsv = hsv_base.copy()
        hsv.h = hue
        cube.color = (hsv.r, hsv.g, hsv.b, 1)

This will create a series of cube with a single material, and use the object info node to color the shader according to the object color. Tweak the upper bound of the np.linspace function to change the hue change factor

capture

Added perk : You don’t even have to be in preview mode to see the colors, you can use the shaded object color view.

image

1 Like

Hello Gorgious,

thank you very much for this awesome script and for the information, really awesome!

Unfortunately I need to apply materials to objects that I already have in the scene (not new ones), and the materials need to be Principled BSD with a normal base color (no additional nodes) so that it can be seen also in a glb format) :frowning:
So I need to find a different solution

This can be adapted to apply to existing objects, just remove the part where it instances cubes and fetch your objects there.
Also I think glb supports vertex colors ? You can try with that too. You can access vertex colors with a node in the shader editor

Thank you for your answer.
I have been struggling to find a solution but no way (I am still a newbie).

Any idea how to apply the colors to all the existing objects in the scene instead of applying them to new cubes?

All the scripts that I can find apply them to new meshes, which is what I cannot afford to do (because my meshes are too complex to be created in python according to my skills)