def add_parametric_color_ramp() -> bpy.types.NodeGroup: group = bpy.data.node_groups.new(type="ShaderNodeTree", name="Parametric Color Ramp") # Input input_node = group.nodes.new(type="NodeGroupInput") group.inputs.new("NodeSocketFloatFactor", "Fac") group.inputs.new("NodeSocketColor", "Color1") group.inputs.new("NodeSocketColor", "Color2") group.inputs.new("NodeSocketFloatFactor", "Pos1") group.inputs.new("NodeSocketFloatFactor", "Pos2") set_socket_value_range(group.inputs["Fac"], default_value=0.5) set_socket_value_range(group.inputs["Pos1"], default_value=0.0) set_socket_value_range(group.inputs["Pos2"], default_value=1.0) # Math denominator_subtract_node = group.nodes.new(type="ShaderNodeMath") denominator_subtract_node.operation = "SUBTRACT" denominator_subtract_node.use_clamp = True numerator_subtract_node = group.nodes.new(type="ShaderNodeMath") numerator_subtract_node.operation = "SUBTRACT" numerator_subtract_node.use_clamp = True divide_node = group.nodes.new(type="ShaderNodeMath") divide_node.operation = "DIVIDE" divide_node.use_clamp = True group.links.new(input_node.outputs["Pos2"], denominator_subtract_node.inputs[0]) group.links.new(input_node.outputs["Fac"], denominator_subtract_node.inputs[1]) group.links.new(input_node.outputs["Pos2"], numerator_subtract_node.inputs[0]) group.links.new(input_node.outputs["Pos1"], numerator_subtract_node.inputs[1]) group.links.new(denominator_subtract_node.outputs["Value"], divide_node.inputs[0]) group.links.new(numerator_subtract_node.outputs["Value"], divide_node.inputs[1]) # Mixing mix_node = group.nodes.new(type="ShaderNodeMixRGB") group.links.new(divide_node.outputs["Value"], mix_node.inputs["Fac"]) group.links.new(input_node.outputs["Color2"], mix_node.inputs[1]) group.links.new(input_node.outputs["Color1"], mix_node.inputs[2]) # Output output_node = group.nodes.new(type="NodeGroupOutput") group.outputs.new("NodeSocketColor", "Color") group.links.new(mix_node.outputs["Color"], output_node.inputs["Color"]) # Return arrange_nodes(group) return group
def add_peeling_paint_metal_node_group() -> bpy.types.NodeGroup: group = bpy.data.node_groups.new(type="ShaderNodeTree", name="Peeling Paint Metal") input_node = group.nodes.new(type="NodeGroupInput") group.inputs.new("NodeSocketColor", "Paint Color") group.inputs.new("NodeSocketColor", "Metal Color") group.inputs.new("NodeSocketFloat", "Scale") group.inputs.new("NodeSocketFloat", "Detail") group.inputs.new("NodeSocketFloat", "Distortion") group.inputs.new("NodeSocketFloatFactor", "Threshold") set_socket_value_range(group.inputs["Scale"], default_value=4.5, min_value=0.0, max_value=1000.0) set_socket_value_range(group.inputs["Detail"], default_value=8.0, min_value=0.0, max_value=16.0) set_socket_value_range(group.inputs["Distortion"], default_value=0.5, min_value=0.0, max_value=1000.0) set_socket_value_range(group.inputs["Threshold"], default_value=0.42) group.inputs["Paint Color"].default_value = (0.152, 0.524, 0.067, 1.000) group.inputs["Metal Color"].default_value = (0.062, 0.015, 0.011, 1.000) tex_coord_node = group.nodes.new(type="ShaderNodeTexCoord") mapping_node = group.nodes.new(type="ShaderNodeMapping") group.links.new(tex_coord_node.outputs["Object"], mapping_node.inputs["Vector"]) # Peeling region segmentation peeling_noise_node = group.nodes.new(type="ShaderNodeTexNoise") group.links.new(mapping_node.outputs["Vector"], peeling_noise_node.inputs["Vector"]) group.links.new(input_node.outputs["Scale"], peeling_noise_node.inputs["Scale"]) group.links.new(input_node.outputs["Detail"], peeling_noise_node.inputs["Detail"]) group.links.new(input_node.outputs["Distortion"], peeling_noise_node.inputs["Distortion"]) peeling_threshold_node = create_parametric_color_ramp_node(group) peeling_threshold_node.inputs["Color1"].default_value = (0.0, 0.0, 0.0, 1.0) peeling_threshold_node.inputs["Color2"].default_value = (1.0, 1.0, 1.0, 1.0) # Base color epsilon_subtract_node = group.nodes.new(type="ShaderNodeMath") epsilon_subtract_node.operation = "SUBTRACT" epsilon_subtract_node.inputs[1].default_value = 0.001 group.links.new(input_node.outputs["Threshold"], epsilon_subtract_node.inputs[0]) group.links.new(peeling_noise_node.outputs["Fac"], peeling_threshold_node.inputs["Fac"]) group.links.new(epsilon_subtract_node.outputs["Value"], peeling_threshold_node.inputs["Pos1"]) group.links.new(input_node.outputs["Threshold"], peeling_threshold_node.inputs["Pos2"]) color_mix_node = group.nodes.new(type="ShaderNodeMixRGB") group.links.new(peeling_threshold_node.outputs["Color"], color_mix_node.inputs["Fac"]) group.links.new(input_node.outputs["Metal Color"], color_mix_node.inputs[1]) group.links.new(input_node.outputs["Paint Color"], color_mix_node.inputs[2]) # Ambient occulusion epsilon_add_node = group.nodes.new(type="ShaderNodeMath") epsilon_add_node.operation = "ADD" epsilon_add_node.inputs[1].default_value = 0.010 group.links.new(input_node.outputs["Threshold"], epsilon_add_node.inputs[0]) fallout_subtract_node = group.nodes.new(type="ShaderNodeMath") fallout_subtract_node.operation = "SUBTRACT" fallout_subtract_node.inputs[1].default_value = 0.060 group.links.new(input_node.outputs["Threshold"], fallout_subtract_node.inputs[0]) ao_node = create_tri_parametric_color_ramp_node(group) ao_node.inputs["Color1"].default_value = (1.0, 1.0, 1.0, 1.0) ao_node.inputs["Color2"].default_value = (0.0, 0.0, 0.0, 1.0) ao_node.inputs["Color3"].default_value = (1.0, 1.0, 1.0, 1.0) group.links.new(peeling_noise_node.outputs["Fac"], ao_node.inputs["Fac"]) group.links.new(fallout_subtract_node.outputs["Value"], ao_node.inputs["Pos1"]) group.links.new(input_node.outputs["Threshold"], ao_node.inputs["Pos2"]) group.links.new(epsilon_add_node.outputs["Value"], ao_node.inputs["Pos3"]) ao_mix_node = group.nodes.new(type="ShaderNodeMixRGB") ao_mix_node.blend_type = "MULTIPLY" ao_mix_node.inputs["Fac"].default_value = 1.0 group.links.new(color_mix_node.outputs["Color"], ao_mix_node.inputs[1]) group.links.new(ao_node.outputs["Color"], ao_mix_node.inputs[2]) # Metallic metallic_node = group.nodes.new(type="ShaderNodeMixRGB") metallic_node.inputs["Color1"].default_value = (1.0, 1.0, 1.0, 1.0) metallic_node.inputs["Color2"].default_value = (0.0, 0.0, 0.0, 1.0) group.links.new(peeling_threshold_node.outputs["Color"], metallic_node.inputs["Fac"]) # Roughness roughness_node = group.nodes.new(type="ShaderNodeMixRGB") roughness_node.inputs["Color1"].default_value = (0.50, 0.50, 0.50, 1.0) roughness_node.inputs["Color2"].default_value = (0.05, 0.05, 0.05, 1.0) group.links.new(peeling_threshold_node.outputs["Color"], roughness_node.inputs["Fac"]) # Bump height_node = create_tri_parametric_color_ramp_node(group) height_node.inputs["Color1"].default_value = (0.0, 0.0, 0.0, 1.0) height_node.inputs["Color2"].default_value = (1.0, 1.0, 1.0, 1.0) height_node.inputs["Color3"].default_value = (0.5, 0.5, 0.5, 1.0) height_peak_add_node = group.nodes.new(type="ShaderNodeMath") height_peak_add_node.operation = "ADD" height_peak_add_node.inputs[1].default_value = 0.005 height_tail_add_node = group.nodes.new(type="ShaderNodeMath") height_tail_add_node.operation = "ADD" height_tail_add_node.inputs[1].default_value = 0.025 group.links.new(input_node.outputs["Threshold"], height_peak_add_node.inputs[0]) group.links.new(input_node.outputs["Threshold"], height_tail_add_node.inputs[0]) group.links.new(peeling_noise_node.outputs["Fac"], height_node.inputs["Fac"]) group.links.new(input_node.outputs["Threshold"], height_node.inputs["Pos1"]) group.links.new(height_peak_add_node.outputs["Value"], height_node.inputs["Pos2"]) group.links.new(height_tail_add_node.outputs["Value"], height_node.inputs["Pos3"]) bump_node = group.nodes.new(type="ShaderNodeBump") group.links.new(height_node.outputs["Color"], bump_node.inputs["Height"]) # Output output_node = group.nodes.new("NodeGroupOutput") group.outputs.new("NodeSocketColor", "Color") group.outputs.new("NodeSocketColor", "Metallic") group.outputs.new("NodeSocketColor", "Roughness") group.outputs.new("NodeSocketVectorDirection", "Bump") group.links.new(ao_mix_node.outputs["Color"], output_node.inputs["Color"]) group.links.new(metallic_node.outputs["Color"], output_node.inputs["Metallic"]) group.links.new(roughness_node.outputs["Color"], output_node.inputs["Roughness"]) group.links.new(bump_node.outputs["Normal"], output_node.inputs["Bump"]) arrange_nodes(group) return group
def add_split_tone_node_group() -> bpy.types.NodeGroup: group = bpy.data.node_groups.new(type="CompositorNodeTree", name="SplitToneSub") input_node = group.nodes.new("NodeGroupInput") group.inputs.new("NodeSocketColor", "Image") group.inputs.new("NodeSocketFloat", "Hue") group.inputs.new("NodeSocketFloat", "Saturation") solid_node = group.nodes.new(type="CompositorNodeCombHSVA") solid_node.inputs["S"].default_value = 1.0 solid_node.inputs["V"].default_value = 1.0 solid_node.inputs["A"].default_value = 1.0 input_sep_node = group.nodes.new(type="CompositorNodeSepHSVA") overlay_node = group.nodes.new(type="CompositorNodeMixRGB") overlay_node.blend_type = 'OVERLAY' overlay_sep_node = group.nodes.new(type="CompositorNodeSepHSVA") comb_node = group.nodes.new(type="CompositorNodeCombHSVA") output_node = group.nodes.new("NodeGroupOutput") group.outputs.new("NodeSocketColor", "Image") group.links.new(input_node.outputs["Hue"], solid_node.inputs["H"]) group.links.new(input_node.outputs["Saturation"], overlay_node.inputs["Fac"]) group.links.new(input_node.outputs["Image"], overlay_node.inputs[1]) group.links.new(solid_node.outputs["Image"], overlay_node.inputs[2]) group.links.new(overlay_node.outputs["Image"], overlay_sep_node.inputs["Image"]) group.links.new(input_node.outputs["Image"], input_sep_node.inputs["Image"]) group.links.new(overlay_sep_node.outputs["H"], comb_node.inputs["H"]) group.links.new(overlay_sep_node.outputs["S"], comb_node.inputs["S"]) group.links.new(input_sep_node.outputs["V"], comb_node.inputs["V"]) group.links.new(input_sep_node.outputs["A"], comb_node.inputs["A"]) group.links.new(comb_node.outputs["Image"], output_node.inputs["Image"]) arrange_nodes(group) # -------------------------------------------------------------------------- group = bpy.data.node_groups.new(type="CompositorNodeTree", name="SplitTone") input_node = group.nodes.new("NodeGroupInput") group.inputs.new("NodeSocketColor", "Image") group.inputs.new("NodeSocketFloat", "HighlightsHue") group.inputs.new("NodeSocketFloat", "HighlightsSaturation") group.inputs.new("NodeSocketFloat", "ShadowsHue") group.inputs.new("NodeSocketFloat", "ShadowsSaturation") group.inputs.new("NodeSocketFloatFactor", "Balance") set_socket_value_range(group.inputs["HighlightsHue"]) set_socket_value_range(group.inputs["HighlightsSaturation"]) set_socket_value_range(group.inputs["ShadowsHue"]) set_socket_value_range(group.inputs["ShadowsSaturation"]) set_socket_value_range(group.inputs["Balance"], default_value=0.5) input_sep_node = group.nodes.new(type="CompositorNodeSepHSVA") subtract_node = group.nodes.new(type="CompositorNodeMath") subtract_node.inputs[0].default_value = 1.0 subtract_node.operation = 'SUBTRACT' subtract_node.use_clamp = True multiply_node = group.nodes.new(type="CompositorNodeMath") multiply_node.inputs[1].default_value = 2.0 multiply_node.operation = 'MULTIPLY' multiply_node.use_clamp = False power_node = group.nodes.new(type="CompositorNodeMath") power_node.operation = 'POWER' power_node.use_clamp = True shadows_node = group.nodes.new(type='CompositorNodeGroup') shadows_node.name = "Shadows" shadows_node.node_tree = bpy.data.node_groups["SplitToneSub"] highlights_node = group.nodes.new(type='CompositorNodeGroup') highlights_node.name = "Highlights" highlights_node.node_tree = bpy.data.node_groups["SplitToneSub"] comb_node = group.nodes.new(type="CompositorNodeMixRGB") comb_node.use_clamp = False output_node = group.nodes.new("NodeGroupOutput") group.outputs.new("NodeSocketColor", "Image") group.links.new(input_node.outputs["Image"], input_sep_node.inputs["Image"]) group.links.new(input_node.outputs["Image"], shadows_node.inputs["Image"]) group.links.new(input_node.outputs["ShadowsHue"], shadows_node.inputs["Hue"]) group.links.new(input_node.outputs["ShadowsSaturation"], shadows_node.inputs["Saturation"]) group.links.new(input_node.outputs["Image"], highlights_node.inputs["Image"]) group.links.new(input_node.outputs["HighlightsHue"], highlights_node.inputs["Hue"]) group.links.new(input_node.outputs["HighlightsSaturation"], highlights_node.inputs["Saturation"]) group.links.new(input_node.outputs["Balance"], subtract_node.inputs[1]) group.links.new(subtract_node.outputs["Value"], multiply_node.inputs[0]) group.links.new(input_sep_node.outputs["V"], power_node.inputs[0]) group.links.new(multiply_node.outputs["Value"], power_node.inputs[1]) group.links.new(power_node.outputs["Value"], comb_node.inputs["Fac"]) group.links.new(shadows_node.outputs["Image"], comb_node.inputs[1]) group.links.new(highlights_node.outputs["Image"], comb_node.inputs[2]) group.links.new(comb_node.outputs["Image"], output_node.inputs["Image"]) arrange_nodes(group) return group