29

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).

zeffii
  • 39,634
  • 9
  • 103
  • 186
user1759333
  • 391
  • 1
  • 3
  • 4
  • Are you asking how to get the RGB of a color in weight paint mode? – CharlesL Jun 11 '13 at 19:44
  • 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 ? – user1759333 Mar 29 '16 at 21:43
  • i'll edit my answer. – zeffii Mar 30 '16 at 09:10

4 Answers4

28

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

Mentalist
  • 19,092
  • 7
  • 94
  • 166
zeffii
  • 39,634
  • 9
  • 103
  • 186
  • 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? – twerdster Feb 01 '14 at 16:21
  • 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? – iKlsR Feb 23 '15 at 12:39
  • @iKlsR using vertex_normals then, might be worth asking a separate question. – zeffii Feb 23 '15 at 14:35
  • @iKlsR https://gist.github.com/zeffii/90399b67820dbf64628b vertex.normal – zeffii Feb 23 '15 at 14:44
  • @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. – iKlsR Feb 23 '15 at 14:56
  • i don't know what you mean by 'color under the normal'.. https://gist.github.com/anonymous/6a74de7ea17a66b67c2f ? – zeffii Feb 23 '15 at 15:01
  • best go for a new question, you will get some definitive answers - no doubt. – zeffii Feb 23 '15 at 15:03
  • Sorry for the late answer... my question is about the GUI, not using Python. Vertex paint is vertex-based, right ? The face selection trick is almost ok, is there some way doing it per vertex as you can in Python ? I would expect it in edit mode, in some panel... but can't find it – user1759333 Mar 29 '16 at 21:19
  • Very helpful answer! If there is already a vertex color map that we want to keep, I figured out that we can modify the code as follows. 1. define a variable for the name: vcol_map = "Something" 2. Remove the conditional if not mesh.vertex_colors: and change the line below it to mesh.vertex_colors.new(name = vcol_map) (no indentation). 3. Define color_layer by the vcol_map variable instead of a name string: color_layer = mesh.vertex_colors.get(vcol_map) If the code is run a second time, the Something vertex color map gets renamed to Something.001 and a new Something is created. – Mentalist Nov 14 '20 at 08:35
5

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.

1

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]
legel
  • 113
  • 5
0

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)

Gorgious
  • 30,723
  • 2
  • 44
  • 101