How to handle absent textures procedurally?

First time poster, long time lurker here.

I'm using a script in a vector drawing program that separates color fields into greyscale bitmaps, that can then be interpreted as areas with different shaders in a Blender material. These shaders can be metal, glitter, flip flop paint, so just using a texture doesn't work. I'm dealing with 1000s of designs, each needing different shaders from a limited but huge set. Automation to the rescue!

I've neatly lined up all the nodes, so the data can flow without obstruction, but I've run into a problem:

Every design only utilizes a few of the total amount of defined shaders, so at the moment I need to generate fully black 2x2 pixel textures for the unused shaders, otherwise the missing texture gets interpreted as being mid-grey all over.

Is there a more elegant solution to handle this problem procedurally, from within the nodes system? That way I can render Blender's output from the command line without having to edit every single node tree by hand, or generate about 50 bitmaps for each design (instead of only the ones actually used).

The image below the result of CreeDorofl's offered solution. This trick just moves the problem one node further upstream, but when I use "linear light" instead of "add" mode it almost works. Almost, because it shrinks the shader area - it seems to influence the way the mask is interpreted, and when using a blurred texture, it becomes clear that it chops of the darker tones, turning them all black. Zooming in shows the way it shrinks the green shader area, and it means I can't use gradients in the mask. [

• if I understand the question right...when a texture is missing, you want a specific replacement texture (2x2 black pixel tiled) rather than the blender medium gray substitute? Maybe you could mix together two materials using a mixRGB mode. One of them will be your desired black color/image. The other will be something else (let's say a bright green image texture), using a blending mode that completely obscures the dark color. Let's say "add". So if the green image is present, you see all green on your object. But if it's missing, the underlying black texture shows instead. – CreeDorofl Jul 28 '18 at 16:48
• Thanks very much for your suggestion. So close... See image added in the post above. – Ron Netgrazer Jul 28 '18 at 21:28
• shoot, shoulda known it wouldn't be that easy. Only other thing I can think of is to add a coloramp node between maybe the linear light node and first image texture. Then use the color ramp to reset the boundary of when linear light cuts off color and turns it to black. I usually have to just experiment to figure out how to make coloramp do what I want. You're either moving the black slider all the way in towards the white, or vice versa. Not sure if it'll affect it the way I think. – CreeDorofl Jul 28 '18 at 21:53
• You should automate it. Not just the import and render, also create the materials with python, so each time all the required nodes are created. – sambler Jul 29 '18 at 4:37
• CreeDorofl, I've tried the colorramping, didn't work, and even if it did it would be too imprecise for my needs. Too bad. Thanks again! – Ron Netgrazer Jul 29 '18 at 8:26

The solution would be to automate creating the material nodes, that way you add the number of colours you want and then add the black filler at the end.

import bpy

obj = bpy.context.object
if obj.active_material is None:
obj.active_material = bpy.data.materials.new('Material')

mat = obj.active_material
mat.use_nodes = True

mat_nodes = mat.node_tree.nodes
# remove everything except the output node
for n in mat_nodes:
if n.type != 'OUTPUT_MATERIAL':
mat_nodes.remove(n)

#  RGBA           red       green      blue
colour_list = [(1,0,0,1), (0,1,0,1), (0,0,1,1)]
data_imgs = bpy.data.images
# length should not be less than colour_list
img_list = [data_imgs['img.001'], data_imgs['img.002'],data_imgs['img.003']]

out_node = mat_nodes[0]
col_space = 200
prev_mix = None

for x in range(len(colour_list)):
mix_node.location = (out_node.location.x - (mix_node.width+padding) - (col_space*x),
out_node.location.y)
if x == 0:
else:
prev_mix = mix_node

img_node.image = img_list[x]

dif_node.inputs['Color'].default_value = colour_list[x]

• The for loop creates, positions and connects three nodes for each colour placed in the colour list, then after the loop the extra black diffuse node is created. If you look at one line at a time, you should be able to get an idea of what it is for. You just need to fill in the colour_list and img_list for each material, then the loop will create enough nodes for your colours. – sambler Aug 2 '18 at 14:22