Material setup for glTF

Moderator: grumpf44

Post Reply
User avatar
coffee
Site Admin
Posts: 6
Joined: Wed Aug 28, 2024 5:00 pm
Location: PA

Material setup for glTF

Post by coffee »

In blender, after importing the glTF file, select a tank part and run this script in a text window.
You will need to create a new text file after opening the window.
This will recreate the materials properly to rendering pretty.


The prefered way:
I also attached the py you can unzip in to documents and load from in side the text window and run it.
materialConverter bpy.zip
(2.15 KiB) Downloaded 12 times
Below is a image of the shader nodes after running the script. Select ONE tank part at a time.
You will need to change this line in the text window for the nation to get the correct color.
armorColor = colors[8] # Index 0 corresponds to 'usa'']

Code: Select all

import bpy

# Get the active object
obj = bpy.context.object

# Define the colors as an array of lists
colors = [
    [82 / 255, 72 / 255, 51 / 255, 0.0],  # usa (0)
    [82 / 255, 72 / 255, 51 / 255, 0.0],  # uk (1)
    [61 / 255, 62 / 255, 42 / 255, 0.0],  # china (2)
    [15 / 255, 36 / 255, 36 / 255, 0.0],  # czech (3)
    [15 / 255, 36 / 255, 36 / 255, 0.0],  # france (4)
    [90 / 255, 103 / 255, 94 / 255, 0.0], # germany (5)
    [15 / 255, 36 / 255, 36 / 255, 0.0],  # japan (6)
    [15 / 255, 36 / 255, 36 / 255, 0.0],  # poland (7)
    [61 / 255, 62 / 255, 42 / 255, 0.0],  # ussr (8)
    [15 / 255, 36 / 255, 36 / 255, 0.0],  # sweden (9)
    [15 / 255, 36 / 255, 36 / 255, 0.0]   # italy (10)
]

# Set the armorColor from the list above if you want it to look like the game. It defaults to 'usa'.
armorColor = colors[8]  # Index 0 corresponds to 'usa'']

# Ensure the object has a material
if obj and obj.active_material:
    material = obj.active_material
    material.use_nodes = True
    
    # Turn off backface culling
    material.use_backface_culling = False

    # Get the material's node tree
    nodes = material.node_tree.nodes
    links = material.node_tree.links

    # Store existing textures
    existing_textures = {node.label.upper(): node.image for node in nodes if node.type == 'TEX_IMAGE'}

    # Clear all nodes to start fresh
    nodes.clear()

    # Create a new Principled BSDF node
    bsdf_node = nodes.new(type='ShaderNodeBsdfPrincipled')
    bsdf_node.name = "Principled BSDF"
    # Set the IOR value to 0.75
    bsdf_node.inputs['IOR'].default_value = 0.75    
    bsdf_node.location = (800, 0)

    # Create a Material Output node
    output_node = nodes.new(type='ShaderNodeOutputMaterial')
    output_node.name = "Material Output"
    output_node.location = (1075, 25)

    # Create a Base Color texture node
    base_color_texture_node = nodes.new(type='ShaderNodeTexImage')
    base_color_texture_node.name = "Base Color Texture"
    base_color_texture_node.label = "BASE COLOR"
    base_color_texture_node.location = (-400, 200)
    base_color_texture_node.image = existing_textures.get("BASE COLOR")

    # Create an RGB node and set the saved emissive color
    rgb_node = nodes.new(type='ShaderNodeRGB')
    rgb_node.name = "Armor Color"
    rgb_node.location = (-150, 100)
    rgb_node.outputs['Color'].default_value = armorColor

    # Create a new Color Mix node (Multiplier)
    new_color_mix_node = nodes.new(type='ShaderNodeMixRGB')
    new_color_mix_node.name = "Color Mix 1"
    new_color_mix_node.blend_type = 'MULTIPLY'
    new_color_mix_node.location = (100, 200)
    new_color_mix_node.inputs['Fac'].default_value = 1.0  # Set the mix factor to 100%

    # Create a Color Mix node
    color_mix_node = nodes.new(type='ShaderNodeMixRGB')
    color_mix_node.name = "Color Mix 2"
    color_mix_node.blend_type = 'MULTIPLY'
    color_mix_node.location = (300, 200)
    color_mix_node.inputs['Fac'].default_value = 1.0  # Set the mix factor to 100%
    
    # Create a MixRGB node set to Multiply
    mix_node = nodes.new(type='ShaderNodeMixRGB')
    mix_node.name = "Final Color Mix"
    mix_node.blend_type = 'MULTIPLY'
    mix_node.location = (500, 200)
    mix_node.inputs['Fac'].default_value = 1.0  # Set the mix factor to 100%

    # Check if Occlusion texture exists
    if "OCCLUSION" in existing_textures:

        # Create an Occlusion texture node
        occlusion_node = nodes.new(type='ShaderNodeTexImage')
        occlusion_node.name = "Occlusion Texture"
        occlusion_node.label = "OCCLUSION"
        occlusion_node.location = (-400, -100)
        occlusion_node.image = existing_textures.get("OCCLUSION")

        # Create a Separate RGB node for Occlusion
        separate_rgb_node_occlusion = nodes.new(type='ShaderNodeSeparateRGB')
        separate_rgb_node_occlusion.name = "Separate RGB Occlusion"
        separate_rgb_node_occlusion.location = (-100, -100)

    # Create a Metallic Roughness texture node
    metallic_roughness_node = nodes.new(type='ShaderNodeTexImage')
    metallic_roughness_node.name = "Metallic Roughness Texture"
    metallic_roughness_node.label = "METALLIC ROUGHNESS"
    metallic_roughness_node.location = (-400, -400)
    metallic_roughness_node.image = existing_textures.get("METALLIC ROUGHNESS")

    # Create a Separate RGB node for Metallic Roughness
    separate_rgb_node_mr = nodes.new(type='ShaderNodeSeparateRGB')
    separate_rgb_node_mr.name = "Separate RGB Metallic Roughness"
    separate_rgb_node_mr.location = (-100, -250)

    # Create Math nodes for Logarithm operation
    log_math_node_r = nodes.new(type='ShaderNodeMath')
    log_math_node_r.name = "Logarithm Roughness"
    log_math_node_r.operation = 'LOGARITHM'
    log_math_node_r.inputs[1].default_value = 0.45
    log_math_node_r.location = (400, -230)

    log_math_node_g = nodes.new(type='ShaderNodeMath')
    log_math_node_g.name = "Logarithm Metallic"
    log_math_node_g.operation = 'LOGARITHM'
    log_math_node_g.inputs[1].default_value = 0.550
    log_math_node_g.location = (400, -50)

    # Create a Normal Map texture node
    normal_map_texture_node = nodes.new(type='ShaderNodeTexImage')
    normal_map_texture_node.name = "Normal Map Texture"
    normal_map_texture_node.label = "NORMAL MAP"
    normal_map_texture_node.location = (0, -400)
    normal_map_texture_node.image = existing_textures.get("NORMAL MAP")

    # Create a Normal Map node
    normal_map_node = nodes.new(type='ShaderNodeNormalMap')
    normal_map_node.name = "Normal Map"
    normal_map_node.location = (400, -400)

    # Create a new Color Mix node (Multiplier) for the B channel
    new_color_mix_node_b = nodes.new(type='ShaderNodeMixRGB')
    new_color_mix_node_b.name = "Color Mix B Channel"
    new_color_mix_node_b.blend_type = 'MULTIPLY'
    new_color_mix_node_b.location = (100, -200)
    new_color_mix_node_b.inputs['Fac'].default_value = 0.5  # Set the mix factor to 50%
    new_color_mix_node_b.inputs['Color1'].default_value = (0.0, 0.0, 0.0, 1.0)  # Set Color2 to black

    # Link the nodes
    links.new(base_color_texture_node.outputs['Color'], new_color_mix_node.inputs['Color1'])
    links.new(rgb_node.outputs['Color'], new_color_mix_node.inputs['Color2'])
    links.new(new_color_mix_node.outputs['Color'], color_mix_node.inputs['Color2'])
    links.new(base_color_texture_node.outputs['Color'], color_mix_node.inputs['Color1'])
    

    if "OCCLUSION" in existing_textures:
        # Link the nodes for Occlusion
        links.new(occlusion_node.outputs['Color'], separate_rgb_node_occlusion.inputs['Image'])
        links.new(separate_rgb_node_occlusion.outputs['G'], mix_node.inputs['Fac'])  # Connect B to RGB's multiplier fac

    links.new(color_mix_node.outputs['Color'], mix_node.inputs['Color1'])
    links.new(mix_node.outputs['Color'], bsdf_node.inputs['Base Color'])

    # Link the nodes for Metallic Roughness and Normal Map
    links.new(metallic_roughness_node.outputs['Color'], separate_rgb_node_mr.inputs['Image'])
    links.new(separate_rgb_node_mr.outputs['R'], log_math_node_r.inputs[0])
    links.new(log_math_node_r.outputs['Value'], bsdf_node.inputs['Roughness'])

    links.new(separate_rgb_node_mr.outputs['G'], log_math_node_g.inputs[0])
    links.new(log_math_node_g.outputs['Value'], bsdf_node.inputs['Metallic'])

    # Link the new multiplier node for the B channel
    links.new(separate_rgb_node_mr.outputs['B'], new_color_mix_node_b.inputs['Color2'])
    links.new(new_color_mix_node_b.outputs['Color'], color_mix_node.inputs['Fac'])

    links.new(normal_map_texture_node.outputs['Color'], normal_map_node.inputs['Color'])
    links.new(normal_map_node.outputs['Normal'], bsdf_node.inputs['Normal'])
    links.new(normal_map_texture_node.outputs['Alpha'], bsdf_node.inputs['Alpha'])

    # Connect the BSDF to the Material Output
    links.new(bsdf_node.outputs['BSDF'], output_node.inputs['Surface'])

    # Remove the link to the BSDF coat tint
    for link in links:
        if link.from_node == new_color_mix_node and link.to_node == bsdf_node and link.to_socket.name == 'Coat Tint':
            links.remove(link)

else:
    print("No active object with a material found.")

Some of the values you can play with are the logarithms. Small changes have big affects.
also. If you want to see the vertex colors, add a vertex color node and run it's output in to the BSDF"s Base Color.
Attachments
blenderNodes.jpg
blenderNodes.jpg (226.66 KiB) Viewed 38 times
I'd love to change the world but I can't get it to compile.
Post Reply