# Turn weight paint(vertex groups) into vertex paint?

Can I turn weight paint(vertex group data) into vertex paint? I would like to take the weight paint value and convert it into a black and white grey scale vertex paint map.

• you forgot a tag that may help a lot here -> Python! – MarcClintDion Aug 21 '14 at 17:16
• @MarcClintDion Tag the question, not the answers. Even if the only solution is python, if the OP isn't specifically looking for a python solution, then I think the current tags are fine. – gandalf3 Aug 21 '14 at 21:08
• True but for some reason I felt that GiantCowFilms would not have a problem with Python solutions as well. Maybe I'm remembering history wrong. Anyways, the reason I brought it up is because some people may just be skimming the tags only and moving past questions with no Python tag and I was pretty sure there was no built in tool to do this. – MarcClintDion Aug 22 '14 at 5:42
• I don't mind python if there is no alternative. – GiantCowFilms Aug 22 '14 at 14:37
• @MarcClintDion It seems there are differing opinions on this.. e.g. meta.stackexchange.com/q/59333/238438 and meta.stackexchange.com/q/184658/238438 (the second one has no answers, but links to a bunch of related/duplicate questions with answers) – gandalf3 Aug 22 '14 at 19:22

I think you will still have to do a bit of scripting to get the following to work but it does most of what you want. A while back, someone posted a question about how to convert an existing script that turns Weight Paint to Vertex Color Paint, he posted the script link and there are a couple reasons why I decided to post this as an answer instead of only directing you to the link. First, there is an important step necessary to get this to work properly. Second, I'd like to also post the script here directly in case the link to the external site goes down, this way it will still be available here.

To start with, Vertex Color Paint starts off as all white and if you try to use the Addon with the Vertex Colors as all White then it fails weirdly. The first results I got looked like the following. It transitions from white to grey then back to white. It's not black where the blue is in Weight Paint mode.

However, if you first add a Color vertex group and then make that group black, the Addon works fine. Just set the brush color to black and use the Set Vertex Color shift +k

Now you will have all black vertex colors.

So now you can enter weight paint mode and use the Addon which can be found in the spacebar search menu under Weight2VertexCol

You should get results something like the following.

Now the fun part, you have to modify the Addon to invert black and white. Fortunately, the math for this is easy, unfortunately I don't know Python scripting very well and I'm mediocre with math. Now if I think correctly(which I don't always do) you can use (x*-1.0)+1.0 to invert black and white. So I assume if we find the place in the script that writes the Vertex Colors and we place that variable where the x is in the above formula then the script should do what you want.

I'll just post the script for now and then maybe someone can figure this last part out. I'll be really surprised if that code works without some indentation reformatting using a program like PyCharm CE since the code window here botched the copy and paste and I had to do a bunch of manual indentation. Anyways, here is the link to the script on the external site so people can just use this copy as a last resort.

The script has the filename -> vertex_color_weight_transfer.py in case anyone from the future wants to Google it. His name is listed in the script below.

I put some notes after the script about how I think you can modify it to make Red = 0.0 and Blue = 1.0 instead of what it does now(Unless I'm confused and it already does.)

import bpy
from mathutils import Color
import random
from bpy.props import *

import bmesh

bl_info = {
"name": "Weight2VertexCol",
"version": (0, 1, 0),
"blender": (2, 6 ,6),
"location": "View3D > UI panel >CopyWeightColors",
"description": "Transfers Weights as Vertex Colors",
"warning": "",
"wiki_url": "",
"tracker_url": "",
"category": "3D View"}

class Weight2VertexCol(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.weight2vertexcol"
bl_label = "Weight2VertexCol"
bl_space_type = "VIEW_3D"
bl_options = {'REGISTER', 'UNDO'}

method=bpy.props.BoolProperty(name="Color", description="Choose the coloring method", default=False)

@classmethod
def poll(cls, context):
return context.active_object is not None

def execute(self, context):
transferWeight2VertexCol(context, self.method)
context.active_object.data.update()
return {'FINISHED'}

def transferWeight2VertexCol(context, method):
me=context.active_object
verts=me.data.vertices

col=Color()
col.h=0
col.s=1
col.v=1

#vcolgrp=bpy.context.active_object.data.vertex_colors.keys()

try:
assert bpy.context.active_object.vertex_groups
assert bpy.context.active_object.data.vertex_colors

except AssertionError:
bpy.ops.error.message('INVOKE_DEFAULT',
type = "Error",
message = 'you need at least one vertex group and one color group')
return

vgrp=bpy.context.active_object.vertex_groups.keys()

vcolgrp=bpy.context.active_object.data.vertex_colors

#Check to see if we have at least one vertex group and one vertex color group
if len(vgrp) > 0 and len(vcolgrp) > 0:
print ("enough parameters")

#Colored
if method:
for poly in me.data.polygons:
for loop in poly.loop_indices:
vertindex=me.data.loops[loop].vertex_index

#Check to see if the vertex has any geoup association
try:
weight=me.vertex_groups.active.weight(vertindex)
except:
continue

#col=Color ((r, g, b ))
col.h=0.66*weight
col.s=1
col.v=1
me.data.vertex_colors.active.data[loop].color = (col.b, col.g, col.r)

if not method:
for poly in me.data.polygons:
for loop in poly.loop_indices:
vertindex=me.data.loops[loop].vertex_index
#weight=me.vertex_groups['Group'].weight(vertindex)

#Check to see if the vertex has any geoup association
try:
weight=me.vertex_groups.active.weight(vertindex)
except:
continue

col.r=weight
col.g=col.r
col.b=col.r
me.data.vertex_colors.active.data[loop].color = (col.b, col.g, col.r)

class MessageOperator(bpy.types.Operator):
bl_idname = "error.message"
bl_label = "Message"
type = StringProperty()
message = StringProperty()

def execute(self, context):
self.report({'INFO'}, self.message)
print(self.message)
return {'FINISHED'}

def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_popup(self, width=800, height=200)

def draw(self, context):
self.layout.label("A message has arrived")
row = self.layout.split(0.25)
row.prop(self, "type")
row.prop(self, "message")
row = self.layout.split(0.80)
row.label("")
row.operator("error.ok")

#
#   The OK button in the error dialog
#
class OkOperator(bpy.types.Operator):
bl_idname = "error.ok"
bl_label = "OK"
def execute(self, context):
return {'FINISHED'}

self.layout.operator_context = 'INVOKE_REGION_WIN'
self.layout.operator(Bevel.bl_idname, "Weight2VertexCol")

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

#error window
bpy.utils.register_class(OkOperator)
bpy.utils.register_class(MessageOperator)

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

if __name__ == "Weight2VertexCol":
register()


The following lines look like where the Red and Blue are being transferred to Black and White. The col.r = weight is a pretty good indication. So is the fact that all three color channels are being assigned the same information. That is how you make a grey scale color which is what we are looking for here.

col.r=weight

col.g=col.r

col.b=col.r

So, as a starting point, I would modify the first line of that snippet to be

col.r= (weight*-1.0)+1.0

and then I would test it. It should do what you want I think.

What would be even better is if you were to find a way to modify the code so that it automatically makes the Vertex Colors all black for you as part of the script which will save you a few steps.

UPDATE: I tested the invert formula and now the script seems to do what you want, here is the result. Also, with the greyscale inversion added, the initial Vertex Colors should start off white instead of black so this saves a bit of setup for you.

• This is a really old thread, but I want to add a little correction: the best way to invert a color/alpha value is to simply subtract it from one. It's actually the same math, x*-1 + 1 = 1-x, but one fewer calculation can save time. I do this a lot in shaders, where performance does matter. – Joseph Brandenburg May 9 '19 at 16:33
• Comment on old threads all you want, it's not an offense. Your point is valid especially with shaders. I use 1-x in GLSL as well. It slipped past me here, thanks for pointing it out. – MarcClintDion May 25 '19 at 18:52

Here's a script for Blender that does the same thing, works in 2.8. It borrows some from the other script, but it's mostly my own. It's a little rough around the edges, I haven't made it into an addon yet. It'll be a while before I bother to improve it, though, so I'll post it here for anyone that needs it.

How to use:

Select the object you want to copy WP to VP or VP to WP. The active WP or VP layer will be copied to VP or WP (respectively) and take the same name + '_Copy'. If you want to copy VP to WP, run the script as it is. If you want to copy WP to VP, comment out line 56 that says CopyVPaintToVWeight(obAct) and uncomment the line beneath it that says CopyVWeightToVPaint(obAct)

At some point, I'll polish this, add features, and update it. It's not a priority for me at the moment, though!

#feel free to use this code for any purpose, anywhere
import bpy
from mathutils import Color

def CopyVWeightToVPaint(ob):
values = GetListFromVertexDataLayer( "VW", ob)
vCol = (ob.vertex_groups.active.name + "_Copy")
ob.data.vertex_colors.new(name = vCol)
for l in ob.data.loops:
i = l.vertex_index
val = values[i]
ob.data.vertex_colors[vCol].data[l.index].color =  (val, val, val, val)

def CopyVPaintToVWeight(ob):
values = GetListFromVertexDataLayer( "VP", ob)
grp = (ob.data.vertex_colors.active.name + "_Copy")
ob.vertex_groups.new(name = grp)
for key in values:

def DesaturateColor(col):
#just a simple average is good enough for now
noAlpha = []
for i in (range(len(col)-1)):
noAlpha.append(col[i])
return (sum(noAlpha)/len(noAlpha))

def GetListFromVertexDataLayer(layerType, ob):
outList = {}
if (layerType == "VP"):
print ("Getting " + str((len(ob.data.loops))) + " values from paint layer:", ob.data.vertex_colors.active.name)
for l in (ob.data.loops):
i = l.vertex_index
#should check if there's already an i in outList
j = l.index
col=[]
for channel in (ob.data.vertex_colors.active.data[j].color):
col.append(channel)
val = DesaturateColor(col)
outList[i] = val
elif (layerType == "VW"):
print ("Getting " + str((len(ob.data.vertices))) + " values from weight layer:", ob.vertex_groups.active.name)
for v in ob.data.vertices:
try:
weight = ob.vertex_groups.active.weight(v.index)
#I'm sure there's a better way
except:
weight = 0
outList[v.index] = weight
print ("Length of output:", len(outList), "Expected Length:", len(ob.data.vertices))
return outList

obAct = bpy.context.active_object
obActData = obAct.data
CopyVPaintToVWeight(obAct)
#CopyVWeightToVPaint(obAct)


Tissue addon 0.3.38 for Blender 2.8 can convert weights to vertex color.

• Your answer would be much better if you added how to convert vertex colors with the addon and not just simply said that it can do such. – David Dec 25 '19 at 12:58