How to merge different coloured materials into single material? I have imported a .wrl model into 2.8 (via 2.79) that is made up of lots of individual objects, each with an assigned coloured material. 
  

All objects that are the same colour share a single material. If I join all these separate objects into one, the materials all transfer and I retain the correct colours, however I now want to modify these materials in order to add different normal/roughness etc. maps.
 

I cannot add these maps individually to each coloured material as there are potentially hundreds of different materials. So I need a method of merging all the colour data into one material which I can then change the other aspects of without the individual vertices losing their colour information. 

The model was originally exported from UCSF Chimera. I can use either Blender 2.79 or 2.8. I would prefer to have the whole model as one object but would be ok with it remaining as separate objects. Colours must remain exactly the same and in the exact same place (very important, no manual recolouring).
This might serve as a kick-off. If the multiple  materials are simple enough, you could bake the diffuse color component of those materials into a vertex-color layer of your meshes, and then access those colors through an Attribute node in your universal material.

This script writes the various materials' diffuse colors into a vertex-color layer named 'dif_color' of all selected mesh-objects, as far as I've tested it, in 2.79:

import bpy

def lin2srgb(rgb_color):       
    rgba=[0,0,0,1]
    a = 0.055    
    for c, x in enumerate(rgb_color):
        if x &lt;= 0.0031308:
            rgba[c] =  x * 12.92
        else:
            rgba[c] = (1 + a) * pow(x, 1 / 2.4) - a 
    return rgba

context = bpy.context
layer_name = 'dif_color'

for obj in context.selected_objects:
    if obj.type == 'MESH':
        me = obj.data
        if not layer_name in me.vertex_colors:  
            me.vertex_colors.new(name=layer_name)  
        dif_layer =  me.vertex_colors[layer_name]

        for poly in me.polygons:
            slot = obj.material_slots[poly.material_index]
            mat = slot.material
            if mat is not None:
                # convert from  RGB to sRGB,A..
                sRGB_col = lin2srgb(mat.diffuse_color)
                for loop_idx in poly.loop_indices:
                    dif_layer.data[loop_idx].color = sRGB_col


Cut and paste this into a text-block, select the objects with multiple materials, and run the script.

Then you could extend this node tree, (which picks up the diffuse colors from the vertex color layer through the Attribute node) to do anything else you like with other attributes of your merged material.



If you've got a ton of stuff to deal with, it would be more economical to make a dictionary of materials > sRGB colors first. to avoid the calculation in the loop.. but this is just a one-shot, so that shouldn't matter too much.

I fully expect corrections to come from people who know better than me..