color masks for objects

I’m trying to create a render that I will then paint over with with Photoshop and I’d like selection masks for each object in the scene. I’ve found sort of a solution


by extracting IndexOB and then Map Range -ing it to a file, but I have a feeling this is a hack and there must be a better way to do it because

  1. for this to work i have to go through each object in a scene and set it’s “pass index” to a different number. This is okay for a scene with 3 objects but can get annoying with 100. Isn’t there a way to have it automatically assigned/extracted?
  2. because of mapping like this the colors are still pretty similar, all grey, isn’t there a way to obtain more colors?

Any advice to doing something like this would be appreciated.

Sure.

Say you have 100 objects (indices). What I’d do would be to divide IndexOB by 100 and plugged this into “Hue” of Combine HSVA node leaving value and saturation at 1. The other thing I’d do would be to plug Alpha into Value, so everything with Alpha of zero would become black.
In my example I have 16 objects, so I divide by 16. Of-course you can also play with value and saturation to have more variations.


Woow, thank you very much! The colors are just beautiful. That totally answers part 2) of my question, about the 1st part, how did you get those colors? did you go through each cube and manually increase it’s pass index? i see from your screenshot that you also get groups of colors and not a separate color for each cube. Isn’t there an automatic way to obtain unique colors/id without having to do anything so 100 cubes would each be 100 different colors that a color picker could select as separate?

Thank you so very much! Your solution is brilliant and your response was so incredibly fast. Thank youuuuuuuu!!!

Wow, Bartek that is so cool! How do you make your brain think like that? It seems so out of the box it is hard to grasp. Is this from another technique perhaps? If so what does it solve?

The way I got indices of my objects was by using a little script:


import bpy
for i, ob in enumerate(bpy.context.selected_objects):
    ob.pass_index = i + 1

This code assigns unique indices to all selected objects.
The code can be tweaked a bit to get more randomization:


import bpy, random
sel = bpy.context.selected_objects
q = len(sel)
indices = list(range(q))
random.shuffle(indices)
for i, ob in enumerate(sel):
    ob.pass_index = indices[i]

This code gives random indices, so when you run it next time - colors get randomized.

@3pointEdit:
Well… It doesn’t come from any other technique. I simply figured it out to solve the problem described here. Colors can be defined by RGB or HSV. Driving hue by something will simply give different colors. No rocket science here. :slight_smile:
The only thing I took from another solution is the script.
I use it very often. Indices can be used for sooooo many things, that being able to randomly asign them seemed important for me, so I wrote those scripts.

Yeah, math is an intriguing subject provided that you stick with it long enough to be able to grasp subtleties like this one! :wink:

Have to agree that it’s so straightforward that it’s (almost) scary :slight_smile:

woooow! this is incredible! Thank you so very much. Though from a programming background I have never before run a python script in Blender, and thanks to you not only did i learn that coloring trick but also passed this big psychological barrier :smiley: Thaaaaaaaaaaaanks!!! WHaaaat an amazing day for learning!

I really liked your solution to transform value into color hue. One thing I didn’t understand about it is why you hooked up alpha to V, I expected just a 1. I mean it works and i’m loving it, but is that making black transparent objects? Thank you very much for the scripts, and especially for starting with a simple one that helped with understanding before the more complex one. It’s also great that you didn’t go through all objects in the scene just the selected. Quite brilliant. Thank you very very much!

please forgive me for daring to ask another question. I tried to modify a bit that simple script to have it add a decimate modifier to all selected objects since I do this often when i jump them from Zbrush, but the script gave an error.


import bpy
for i, ob in enumerate(bpy.context.selected_objects):
         ob.modifier_add(type='DECIMATE')
         ob.object.modifiers["Decimate"].ratio = 0.1

I’m probably doing something really silly and please forgive my daring to bother you again after you’ve been so generous with your knowledge, but I thought I’d ask.

This should probably be moved to scripting forum, but because we started all this here, let me answer it here as well.
Below you’ll find the script that will do exactly what you want.
It requires understanding of the structure of blender’s API. Not all functions can be called from any place, so sometimes we need to use some tricks.


import bpy
scn = bpy.context.scene
active = scn.objects.active
for ob in [o for o in bpy.context.selected_objects if o.type == 'MESH']:
    scn.objects.active = ob
    bpy.ops.object.modifier_add(type='DECIMATE')
    ob.modifiers["Decimate"].ratio = 0.1
scn.objects.active = active

and now let me go line by line explaining what and why is done.

import bpy

obvious… we simply import blender’s python module to be able to control blender via python.

scn = bpy.context.scene

just for simplification. I want to later just say “scn” instead of “bpy.context.scene” every time I want to refer to the scene I am working on.

active = scn.objects.active

“active” will from now on be the object that is active. Later on the script will make other objects active, so I simply store currently active object to make it active again after all operations are executed.

for ob in [o for o in bpy.context.selected_objects if o.type == 'MESH']:
    scn.objects.active = ob

Here I iterate through all selected objects making sure that only mashes will be taken into account and begin by making the object active.
Adding modifier can be done only for the active object. It doesn’t matter if it’s selected or not.

    bpy.ops.object.modifier_add(type='DECIMATE')

then I add the modifier. Please note the correct operator for adding modifiers.

    ob.modifiers["Decimate"].ratio = 0.1

Now I set “ratio” for the modifier. As you can see I access the modifier that already exists (added in previous step) in completely different manner. I access it through the object.

scn.objects.active = active

The last line restores the state before executing the script. I make the object that was active at the beginning active again.

like wooooooooooooooow. Thank you so so soooooo much! This was so so soooo much more than I was even daring to hope. I mean I thought the solution would be a simple semicolon or addressing, and if not I wasn’t even daring hope for an answer and yet you not only gave me a working solution (works great, thank you so so so very much!) but you also went through the trouble of explaining it to me line by line, thank you so very much!

Maaan, what a joy what a joy! I’m constantly transferring objects back and forth from Zbrush to Blender And this script will help me a lot! Thank you so very very very much for all your fantastic help! Like WOOW!!!

Hi!

There is no automatic way of getting this Object or Material pass: one must set a number for each object or material prior to rendering, right?

EDIT: I just read Bartek’s post… Never again will I ask a question without reading the entire post first…
I just need to learn how to use the script though…

It’s brilliant!

So brilliant and useful (I use index pass on every job I make), I really think it should be included in Blender!

Thanks so much!