# How to paint vertices in different object using python scripts?

I use this code to paint:

import bpy

def random_color(obj):
import random
r = random.random
mesh = obj.data
scn = bpy.context.scene
#check if our mesh already has Vertex Colors, and if not add some... (first we need to make sure it's the active object)
scn.objects.active = obj
obj.select = True
if mesh.vertex_colors:
vcol_layer = mesh.vertex_colors.active
else:
vcol_layer = mesh.vertex_colors.new()
for poly in mesh.polygons:
for loop_index in poly.loop_indices:
loop_vert_index = mesh.loops[loop_index].vertex_index
random_color = [r(), r(), r()]
vcol_layer.data[loop_index].color = random_color

for obj in bpy.data.objects:
if obj.type == 'MESH':
bpy.context.scene.objects.active = obj
bpy.ops.object.mode_set(mode='VERTEX_PAINT')


in the 3D viewer, I only observe the lase part of the plane is painted.

Another problem is,when I render it, the plane is all black because I don't add a light source. But should I add light in vertex paint mode?

As far as I understand, this line

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


only causes the user interface to switch to Vertex Paint mode, which displays the vertex colors in the viewport when the object is active and allows you to paint the vertices on your own. This step is not required if you color the vertices in a script and it does not change the way the final image is being rendered. If these colors should also appear in the final render then you have to set up your material to take vertex colors into account. The answer to this question describes how to do that if you're using the Cycles render engine. You should end up with a material like this:

Unless you're using an Emission shader instead of the Diffuse BSDF you still have to use other light sources in the scene.

And while the script seems to define the random_color function, the function doesn't actually get called. As you ended up with some parts of your model being painted, I assume this is only a missed line when you copied your script. In case it isn't, the last loop should probably be:

for obj in bpy.data.objects:
if obj.type == 'MESH':
bpy.context.scene.objects.active = obj
bpy.ops.object.mode_set(mode='VERTEX_PAINT')
random_color(obj)


It's likely that the viewport will still display only one mesh colored as Blender will only display vertex colors for the active object. All other objects will be displayed according to the Viewport Shading setting. This should explain why only one part of your model is colored while the rest of it remains grey. Once you've set up your material you can switch to Material shading to see the other parts of the plane colored as well.

Here is a bmesh take on this, using the code from this answer.

import bpy
import bmesh
from random import random
context = bpy.context
scene = context.scene
mesh = context.object.data
bm = bmesh.new()

meshes = [o.data for o in scene.objects if o.type == 'MESH']
for mesh in meshes:
bm.from_mesh(mesh)

color_layer = bm.loops.layers.color.get("Col")
if color_layer is None:
color_layer = bm.loops.layers.color.new("Col")
# make a random color table for each vert
# vert_color = random_color_table[vert.index]
random_color_table = [[random() for c in "rgb"]
for i in range(len(bm.verts))]
for face in bm.faces:
for loop in face.loops:
print("Vert:", loop.vert.index)
loop[color_layer] = random_color_table[loop.vert.index]
print(loop[color_layer])
bm.to_mesh(mesh)
mesh.update()
bm.clear()


As pointed out by @binweg use How Can Vertex Paint Be Rendered to render.