def map_vertex_color(self, layer_name: str = 'Col', active_shading: bool = True): """ Maps existing vertex color to the base color of the principled bsdf node or a new background color node. :param layer_name: Name of the vertex color layer. Type: string. :param active_shading: Whether to keep the principled bsdf shader. If True, the material properties influence light reflections such as specularity, roughness, etc. alter the object's appearance. Type: bool. """ if active_shading: # create new shader node attribute attr_node = self.nodes.new(type='ShaderNodeAttribute') attr_node.attribute_name = layer_name # connect it to base color of principled bsdf principled_bsdf = self.get_the_one_node_with_type("BsdfPrincipled") self.links.new(attr_node.outputs['Color'], principled_bsdf.inputs['Base Color']) else: # create new vertex color shade node vcol = self.nodes.new(type="ShaderNodeVertexColor") vcol.layer_name = layer_name node_connected_to_output, material_output = Utility.get_node_connected_to_the_output_and_unlink_it( self.blender_obj) # remove principled bsdf self.nodes.remove(node_connected_to_output) background_color_node = self.nodes.new(type="ShaderNodeBackground") if 'Color' in background_color_node.inputs: self.links.new(vcol.outputs['Color'], background_color_node.inputs['Color']) self.links.new(background_color_node.outputs["Background"], material_output.inputs["Surface"]) else: raise Exception( "Material '{}' has no node connected to the output, " "which has as a 'Base Color' input.".format( self.blender_obj.name))
def add_alpha_channel_to_textures(blurry_edges): """ Adds transparency to all textures, which contain an .png image as an image input :param blurry_edges: If True, the edges of the alpha channel might be blurry, this causes errors if the alpha channel should only be 0 or 1 Be careful, when you replace the original texture with something else (Segmentation, ...), the necessary texture node gets lost. By copying it into a new material as done in the SegMapRenderer, you can keep the transparency even for those nodes. """ obj_with_mats = [ obj for obj in bpy.context.scene.objects if hasattr(obj.data, 'materials') ] visited_materials = set() # walk over all objects, which have materials for obj in obj_with_mats: for slot in obj.material_slots: material = slot.material if material is None: # this can happen if a material slot was created but no material was assigned continue if material.name in visited_materials: # skip a material if it has been used before continue visited_materials.add(material.name) texture_node = None # check each node of the material for node in material.node_tree.nodes: # if it is a texture image node if 'TexImage' in node.bl_idname: if '.png' in node.image.name: # contains an alpha channel texture_node = node # this material contains an alpha png texture if texture_node is not None: nodes = material.node_tree.nodes links = material.node_tree.links node_connected_to_the_output, material_output = \ Utility.get_node_connected_to_the_output_and_unlink_it(material) if node_connected_to_the_output is not None: mix_node = nodes.new(type='ShaderNodeMixShader') # avoid blurry edges on the edges important for Normal, SegMapRenderer and others if blurry_edges: # add the alpha channel of the image to the mix shader node as a factor links.new(texture_node.outputs['Alpha'], mix_node.inputs['Fac']) else: # Map all alpha values to 0 or 1 by applying the step function: 1 if x > 0.5 else 0 step_function_node = nodes.new("ShaderNodeMath") step_function_node.operation = "GREATER_THAN" links.new(texture_node.outputs['Alpha'], step_function_node.inputs['Value']) links.new(step_function_node.outputs['Value'], mix_node.inputs['Fac']) links.new(node_connected_to_the_output.outputs[0], mix_node.inputs[2]) transparent_node = nodes.new( type='ShaderNodeBsdfTransparent') links.new(transparent_node.outputs['BSDF'], mix_node.inputs[1]) # connect to material output links.new(mix_node.outputs['Shader'], material_output.inputs['Surface']) else: raise Exception( "Could not find shader node, which is connected to the material output " "for: {}".format(slot.name))