29
$\begingroup$

I can't find a way to display RGB values (or equivalent) without using the python shell.

I would like to get and set color values numerically (ie. not painting), I can't find it for weight painting either (I expected it to appear in the "n" panel with something like "vertex" as a title).

$\endgroup$
3
  • $\begingroup$ Are you asking how to get the RGB of a color in weight paint mode? $\endgroup$
    – CharlesL
    Commented Jun 11, 2013 at 19:44
  • $\begingroup$ Sorry for the late answer ! Yes, I needed a way to edit or read the color's data of a vertex, thanks for the nice answer @zeffii , but I'm looking for something in the UI, without Python. At the UI level why is it at face level ? $\endgroup$ Commented Mar 29, 2016 at 21:43
  • $\begingroup$ i'll edit my answer. $\endgroup$
    – zeffii
    Commented Mar 30, 2016 at 9:10

4 Answers 4

28
$\begingroup$

I would like to get and set color values numerically (ie. not painting),

There may be add-ons that cater to this, but at present (March 2016)

  • Blender doesn't have a (non-Python) way to set the Vertex Colors per selected vertex/vertices. Per face is however, as stated below, not a problem.

  • There is no built-in interface (yet) to get the rgb value of a selected Vertex. Each vertex can be shared by a number of faces, therefore a vertex doesn't necessarily have one color associated with it. Behind the scenes the Vertex Colors are not stored in the data per vertex but in a Vertex Color layer, which stores vertex colors for each face of the mesh.

    Possibly this explains that a bit more clear. There are 9 verts in this subdivided plane, and the middle vertex is used in 4 faces and therefore has 4 different colors associated. enter image description here

Vertex Color Map

You can set a collection of faces to one colour in vertex paint mode, by selecting them and setting the colour from the colour picker, then shift+K (while the mouse cursor is inside the viewport) will fill the selection with that colour. You can enter numericals into the Blender colour picker.

You can pick faces with face selection masking enter image description here

If you want to do it by script:

import bpy
import random
 
# start in object mode
obj = bpy.data.objects["Cube"]
mesh = obj.data

if not mesh.vertex_colors:
    mesh.vertex_colors.new()

"""
let us assume for sake of brevity that there is now 
a vertex color map called  'Col'    
"""

color_layer = mesh.vertex_colors["Col"]

# or you could avoid using the color_layer name
# color_layer = mesh.vertex_colors.active  

i = 0
for poly in mesh.polygons:
    for idx in poly.loop_indices:
        r, g, b = [random.random() for i in range(3)]
        color_layer.data[i].color = (r, g, b, 1.0)
        i += 1

# set to vertex paint mode to see the result
bpy.ops.object.mode_set(mode='VERTEX_PAINT')

Also a small blogpost about vertex colours here and here, if you are so inclined.

For Weight Painting, i'm not sure -- i'll let someone more familiar with that give an answer

$\endgroup$
9
  • $\begingroup$ How would you change this script to set the vertex colors equal to the value of the vertices themselves? I.e. each vertex RGB = XYZ? $\endgroup$
    – twerdster
    Commented Feb 1, 2014 at 16:21
  • $\begingroup$ How could I set the color to the value under the normal of a face or the approximate blended color if the vertices of that face are different? $\endgroup$
    – iKlsR
    Commented Feb 23, 2015 at 12:39
  • $\begingroup$ @iKlsR using vertex_normals then, might be worth asking a separate question. $\endgroup$
    – zeffii
    Commented Feb 23, 2015 at 14:35
  • $\begingroup$ @iKlsR gist.github.com/zeffii/90399b67820dbf64628b vertex.normal $\endgroup$
    – zeffii
    Commented Feb 23, 2015 at 14:44
  • $\begingroup$ @zeffii The color under the normal or the color in the middle of a polygon. I've never used vertex paint programmatically before so not even sure the api allows this. $\endgroup$
    – iKlsR
    Commented Feb 23, 2015 at 14:56
5
$\begingroup$

You can try this code to apply color to vertices selected in edit mode:

import bpy

def color_to_vertices(color):
    mesh = bpy.context.active_object.data
    bpy.ops.object.mode_set(mode = 'VERTEX_PAINT')

    selected_verts = []
    for vert in mesh.vertices:
        if vert.select == True:
            selected_verts.append(vert)

    for polygon in mesh.polygons:
        for selected_vert in selected_verts:
            for i, index in enumerate(polygon.vertices):
                if selected_vert.index == index:
                    loop_index = polygon.loop_indices[i]
                    mesh.vertex_colors.active.data[loop_index].color = color

    bpy.ops.object.mode_set(mode = 'EDIT')

import random

RGB = [random.uniform(0,1) for i in range(3)]
color_to_vertices(RGB)

The result will be like this:

enter image description here

Don't forget about proper material node setup if you want to see the result in edit mode (material viewport shading) and render:

enter image description here

For convenience sake you maybe want to create some panel and an operator.

$\endgroup$
1
  • $\begingroup$ Thank you so much! I've been struggling with this all day and I finally got somewhere with my plugin! $\endgroup$ Commented May 15, 2021 at 3:33
1
$\begingroup$

If you happen to be working with .ply files (or can convert your model to that), I recommend using the Point Cloud Visualizer, like so:

from space_view3d_point_cloud_visualizer import PlyPointCloudReader

ply_filename = "some_file.ply"
point_cloud = PlyPointCloudReader(ply_filename).points

# get color of point at index 100
red = point_cloud['red'][100]
blue = point_cloud['blue'][100]
green = point_cloud['green'][100]
$\endgroup$
1
$\begingroup$

Update for 4.0 and the new Attribute API.

IN OBJECT MODE

import bpy
import random

obj = bpy.context.active_object
if obj.type == 'MESH':
    mesh = obj.data

    point_color_attribute = mesh.color_attributes.get("MyPointColors") or mesh.color_attributes.new(name="MyPointColors", type="BYTE_COLOR", domain="POINT")
    point_colors = [None] * len(mesh.vertices) * 4
    point_color_attribute.data.foreach_get("color_srgb", point_colors)  # Get Point Colors
    print(point_colors)

    for _ in range(len(mesh.vertices)):
        point_colors.extend((random.random(), random.random(), random.random(), 1))
    point_color_attribute.data.foreach_set("color_srgb", point_colors)  # Set Point Colors
    print(point_colors)

    corner_color_attribute = mesh.color_attributes.get("MyCornerColors") or mesh.color_attributes.new(name="MyCornerColors", type="BYTE_COLOR", domain="CORNER")
    corner_colors = [None] * len(mesh.loops) * 4
    point_color_attribute.data.foreach_get("color_srgb", corner_colors)  # Get Corner Colors
    print(corner_colors)

    for _ in range(len(mesh.loops)):
        corner_colors.extend((random.random(), random.random(), random.random(), 1))
    corner_color_attribute.data.foreach_set("color_srgb", corner_colors)  # Set Corner Colors
    print(corner_colors)

IN EDIT MODE

In edit mode the regular way to access attributes yields empty sequences. You have to use the bmesh construct.

import bpy
import bmesh
import random

obj = bpy.context.active_object
if obj.type == 'MESH':
    mesh = obj.data
    bm = bmesh.from_edit_mesh(mesh)

    point_color_attribute = mesh.color_attributes.get("MyPointColors") or mesh.color_attributes.new(name="MyPointColors", type="BYTE_COLOR", domain="POINT")
    point_color_layer = bm.verts.layers.color[point_color_attribute.name]
    point_colors = []
    for vert in bm.verts:
        point_colors.extend(vert[point_color_layer])  # Get Point Colors
    print(point_colors)

    point_colors = []
    for vert in bm.verts:
        vert[point_color_layer] = (random.random(), random.random(), random.random(), 1)  # Set Point Colors

    corner_color_attribute = mesh.color_attributes.get("MyCornerColors") or mesh.color_attributes.new(name="MyCornerColors", type="BYTE_COLOR", domain="CORNER")
    corner_color_layer = bm.loops.layers.color[corner_color_attribute.name]
    corner_colors = []
    for face in bm.faces:
        for loop in face.loops:
            corner_colors.extend(loop[corner_color_layer])  # Get Corner Colors
    print(corner_colors)

    for face in bm.faces:
        for loop in face.loops:
            loop[corner_color_layer] = (random.random(), random.random(), random.random(), 1)  # Set Corner Colors
            
    bmesh.update_edit_mesh(mesh)
$\endgroup$

You must log in to answer this question.

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