2
$\begingroup$

I have a list with 150 colors, all representing a type of object in a scene (for example: walls, ceiling, grass, cabinet, painting, water, chair, table etc).

you can see the list here

I want to create a reusable node group to quickly change an objects color.

What I have done in the past (if i had less than 10 colors):

Node Group

Add every color as RGB node, group them and name every output according to the color

Screenshot of the custom color node group

Pros: Colors are available to use in procedural materials, I can hide unneeded colors quickly

Cons: potentially long list and inconvinient to set up for large amount of colors

Seperate material for each color

Pros: quickly apply colors to objects, searchable

Cons: inconvinient to set up for a large amount of colors, not usable for procedural materials


Any idea for a more convenient way to achieve this is greatly appreciated. Easy to set up would be great as well as some kind of searchability.

Currently I am thinking about just making a seperate node group for every color/object.

$\endgroup$
3
  • $\begingroup$ What I would do, in order to not pollute custom groups, is I would use "RGB" nodes, that I would name in a particular way, for example IMPORT_earth. Then I could have Python parse the csv file to map all names to colors, then go through all RGB nodes starting with IMPORT_, and update them to the color mapping[name.split('_')[1]], allowing it to produce an error if the key is not found (a typo). $\endgroup$ May 16, 2023 at 8:36
  • $\begingroup$ But this meens i need to create the rgb node for every color, name it and update it EVERY TIME I use that color in a new context (i.e. new material), correct? The node and its name isn't saved anywhere to quickly add to a different material. $\endgroup$
    – bstnhnsl
    May 16, 2023 at 8:53
  • $\begingroup$ "I need to create the rgb node for every color" - yes, as opposed to creating a custom group for every color. "name it" - that's an additional step, though you could say the difference is naming the node instead of choosing the color from available sockets or from available custom groups; naming is choosing color. "update it EVERY TIME I use that color in a new context (i.e. new material)" - no, that's the part done by Python. If you want to have a convenient list of available names, you could create a custom operator that allows you to choose one, and maybe creates the node then. $\endgroup$ May 16, 2023 at 9:41

1 Answer 1

3
$\begingroup$

Creating a separate node group for each color is probably one of the most flexible solutions. They are searchable, available for different materials and if you want to change the color and it's inside a group, it will update everywhere it is used.

If we are talking about setting up hundreds of groups, Python will be the way to go. That's how it might look:

import bpy, requests, csv, io

# Your color values are in sRGB color space (I guess and hope so)
# so we need to convert them to Blender's linear colors with 
# some random code I found online. Hopefully it's OK. 
def srgb2lin(s):  
    if s <= 0.0404482362771082:
        lin = s / 12.92
    else:
        lin = pow(((s + 0.055) / 1.055), 2.4)
    return lin

# You can load CSV file from Google sheets
sheet_id = "1se8YEtb2detS7OuPE86fXGyD269pMycAWe2mtKUj2W8" 
#that's the ID I found in the URL you shared
url = "https://docs.google.com/spreadsheets/d/" + sheet_id+ "/gviz/tq?tqx=out:csv"
r = requests.get(url)
reader = csv.reader(io.StringIO(r.text))
next(reader)    
for row in reader:
    group = bpy.data.node_groups.new(row[8], 'ShaderNodeTree')
    group.outputs.new("NodeSocketColor", "Color")
    group.use_fake_user = True 
    color_node = group.nodes.new('ShaderNodeRGB')
    c = []
    for value in row[5][1:-1].split(","):
        c.append(srgb2lin(1/255*float(value)))
    c.append(1) # thats alpha, because the color in the node is in RGBA format
    color_node.outputs[0].default_value = c
    output_node = group.nodes.new("NodeGroupOutput")
    output_node.location = (200, 0)
    group.links.new(color_node.outputs[0], output_node.inputs[0])

You could also generate a material for each node group that would use the node group for it's color at the same time.

$\endgroup$
5
  • $\begingroup$ The problem I see about many custom groups is 'namespace pollution'. Especially when you create some kind of an asset, if using this asset floods the "Custom Group" menu with possibly hundreds of custom groups, it could be an annoyance for some users. This is one reason why I avoid using a single-use custom groups in geonodes and I just create big node trees using frames. $\endgroup$ May 16, 2023 at 11:51
  • $\begingroup$ Well, I can see where this personal preference comes from, but the way I see it it's just that - personal preference. Custom node group functionality is there to be used. I see no reason not to use it. It's possible to manage them with Outliner and also they can be searched by name. You can't make an omelette without breaking some eggs... $\endgroup$ May 16, 2023 at 11:56
  • $\begingroup$ Sure, I only meant it as a subjective criticism, a thing to consider. As for removing the header, perhaps not the idiomatic way, but maybe data = [row for row in reader][1:]. I checked if maybe the hex field can be set directly, but nothing shows in Info panel. Found the conversion in source: math_color.c, ported to Python: (0 if c<0 else c/12.92) if c<0.04045 else ((c+0.055)/1.055)**2.4 (basically same result as your srgb2lin) $\endgroup$ May 16, 2023 at 12:19
  • 2
    $\begingroup$ I meant, I was sure there was a nice way to just skip the first line containing the header. Apparently you can just do next(reader) and then have only one loop with the reader itself. I did not know how to use it. I have never used an iterator before. I'll edit the answer. $\endgroup$ May 16, 2023 at 12:38
  • 1
    $\begingroup$ This answer is probably the way to go in my case. I won't have a lot of node groups besides those colors and it seems to be pretty convenient for me. I added a few node groups manually and its really quick and flexible. I'll accept the answer as soon as I tried it via python and everything works for me. $\endgroup$
    – bstnhnsl
    May 16, 2023 at 12:48

You must log in to answer this question.

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