1
$\begingroup$

I'm trying to create a script in Blender that sets the viewport colors of objects based on the properties of their physically-based rendering (PBR) materials. However, I'm encountering difficulties in achieving this functionality.

Here's the Python script I've been working with:

import bpy
import numpy

class SetViewportColorFromMaterialOperator(bpy.types.Operator):
    bl_idname = "object.set_viewport_color_from_material"
    bl_label = "Set Viewport Color from Material"

    def execute(self, context):
        # Iterate through all selected objects
        for obj in bpy.context.selected_objects:
            # Check if the object is a mesh
            if obj.type == 'MESH':
                avg_color = [0, 0, 0, 1]  # Initialize average color as black
                material_count = 0

                # Iterate through all materials of the object
                for material_slot in obj.material_slots:
                    material = material_slot.material

                    # Check if the material uses nodes
                    if material.use_nodes:
                        # Iterate through all nodes in the material node tree
                        for node in material.node_tree.nodes:
                            if node.type == 'BSDF_PRINCIPLED':
                                # If a Principled BSDF node is found, check the base color
                                base_color = node.inputs['Base Color'].default_value
                                avg_color = numpy.add(avg_color, base_color)
                                material_count += 1

                # Calculate the average color
                if material_count > 0:
                    avg_color /= material_count

                # Set the viewport color of the object
                obj.color = avg_color[:3]  # Set the RGB values

        return {'FINISHED'}

def register():
    bpy.utils.register_class(SetViewportColorFromMaterialOperator)

def unregister():
    bpy.utils.unregister_class(SetViewportColorFromMaterialOperator)

if __name__ == "__main__":
    register()

In this script, I'm iterating through selected objects and their materials, aiming to set the viewport color of each object based on properties of its associated material, such as color, metallicness, and roughness.

Could someone assist me in completing the script by providing the necessary code to set the object's viewport color using its PBR material properties?

Any help or guidance would be greatly appreciated. Thank you!

$\endgroup$

1 Answer 1

1
$\begingroup$

If you want to set the object color

import bpy
import numpy


class SetViewportColorFromMaterialOperator(bpy.types.Operator):
    bl_idname = "object.set_viewport_color_from_material"
    bl_label = "Set Viewport Color from Material"

    def execute(self, context):
        # Iterate through all selected objects
        for obj in bpy.context.selected_objects:
            # Check if the object is a mesh
            if obj.type == 'MESH':
                avg_color = [0, 0, 0, 1]  # Initialize average color as black
                material_count = 0

                # Iterate through all materials of the object
                for material_slot in obj.material_slots:
                    material = material_slot.material

                    # Check if the material uses nodes
                    if material.use_nodes:
                        # Iterate through all nodes in the material node tree
                        for node in material.node_tree.nodes:
                            if node.type == 'BSDF_PRINCIPLED':
                                # If a Principled BSDF node is found, check the base color
                                base_color = node.inputs['Base Color'].default_value
                                avg_color = numpy.add(avg_color, base_color)
                                material_count += 1

                # Calculate the average color
                if material_count > 0:
                    avg_color /= material_count

                # Set the viewport color of the object
                obj.color = avg_color  # Set the RGB values

        return {'FINISHED'}


def register():
    bpy.utils.register_class(SetViewportColorFromMaterialOperator)


def unregister():
    bpy.utils.unregister_class(SetViewportColorFromMaterialOperator)


if __name__ == "__main__":
    register()

Enable Viewport Shading > Color > Object

enter image description here

If you want to set the material viewport color, metallic, roughness etc.

import bpy
import numpy


class SetViewportColorFromMaterialOperator(bpy.types.Operator):
    bl_idname = "object.set_viewport_color_from_material"
    bl_label = "Set Viewport Color from Material"

    def execute(self, context):
        # Iterate through all selected objects
        for obj in bpy.context.selected_objects:
            # Check if the object is a mesh
            if obj.type == 'MESH':
                avg_color = [0, 0, 0, 1]  # Initialize average color as black
                material_count = 0

                # Iterate through all materials of the object
                for material_slot in obj.material_slots:
                    material = material_slot.material

                    # Check if the material uses nodes
                    if material.use_nodes:
                        # Iterate through all nodes in the material node tree
                        for node in material.node_tree.nodes:
                            if node.type == 'BSDF_PRINCIPLED':
                                # If a Principled BSDF node is found, check the base color
                                base_color = node.inputs['Base Color'].default_value
                                avg_color = numpy.add(avg_color, base_color)
                                material_count += 1

                # Calculate the average color
                if material_count > 0:
                    avg_color /= material_count

                # Set the viewport color of the object
                for mat in obj.data.materials:
                    mat.diffuse_color = avg_color  # Set the RGB values
                    mat.metallic = 0.5
                    mat.specular_color = (1.0, 1.0, 1.0)
                    mat.specular_intensity = 0.5
                    mat.roughness = 0.5

        return {'FINISHED'}


def register():
    bpy.utils.register_class(SetViewportColorFromMaterialOperator)


def unregister():
    bpy.utils.unregister_class(SetViewportColorFromMaterialOperator)


if __name__ == "__main__":
    register()
$\endgroup$
2
  • $\begingroup$ Thank you for your response. Did the first script you provided work for you? I'm looking to change the 'object color,' not the material color, as suggested in your second script. The first script is supposed to take a sample from the UV area of the material and set it as the 'object color.' However, it doesn't seem to be working for me. It doesn't actually change any colors. $\endgroup$
    – Larry
    Commented Mar 15 at 10:17
  • $\begingroup$ yes, to see the color enable Viewport Shading > Color > Object $\endgroup$
    – Karan
    Commented Mar 15 at 12:34

You must log in to answer this question.

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