def __gather_base_color_factor(blender_material, export_settings):
    if not blender_material.use_nodes:
        return [*blender_material.diffuse_color[:3], 1.0]

    rgb, alpha = None, None

    alpha_socket = gltf2_blender_get.get_socket(blender_material, "Alpha")
    if isinstance(alpha_socket, bpy.types.NodeSocket):
        if export_settings['gltf_image_format'] != "NONE":
            alpha = gltf2_blender_get.get_factor_from_socket(alpha_socket, kind='VALUE')
        else:
            alpha = gltf2_blender_get.get_const_from_default_value_socket(alpha_socket, kind='VALUE')

    base_color_socket = gltf2_blender_get.get_socket(blender_material, "Base Color")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket(blender_material, "BaseColor")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket_old(blender_material, "BaseColorFactor")
    if isinstance(base_color_socket, bpy.types.NodeSocket):
        if export_settings['gltf_image_format'] != "NONE":
            rgb = gltf2_blender_get.get_factor_from_socket(base_color_socket, kind='RGB')
        else:
            rgb = gltf2_blender_get.get_const_from_default_value_socket(base_color_socket, kind='RGB')

    if rgb is None: rgb = [1.0, 1.0, 1.0]
    if alpha is None: alpha = 1.0

    rgba = [*rgb, alpha]

    if rgba == [1, 1, 1, 1]: return None
    return rgba
def __gather_base_color_factor(blender_material, export_settings):
    rgb, alpha = None, None

    alpha_socket = gltf2_blender_get.get_socket(blender_material, "Alpha")
    if isinstance(alpha_socket, bpy.types.NodeSocket):
        alpha = gltf2_blender_get.get_factor_from_socket(alpha_socket,
                                                         kind='VALUE')

    base_color_socket = gltf2_blender_get.get_socket(blender_material,
                                                     "Base Color")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket(
            blender_material, "BaseColor")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket_old(
            blender_material, "BaseColorFactor")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket(
            blender_material, "Background")
    if isinstance(base_color_socket, bpy.types.NodeSocket):
        rgb = gltf2_blender_get.get_factor_from_socket(base_color_socket,
                                                       kind='RGB')

    if rgb is None: rgb = [1.0, 1.0, 1.0]
    if alpha is None: alpha = 1.0

    rgba = [*rgb, alpha]

    if rgba == [1, 1, 1, 1]: return None
    return rgba
Ejemplo n.º 3
0
def __gather_metallic_roughness_texture(blender_material, orm_texture,
                                        export_settings):
    if orm_texture is not None:
        texture_input = orm_texture
    else:
        metallic_socket = gltf2_blender_get.get_socket(blender_material,
                                                       "Metallic")
        roughness_socket = gltf2_blender_get.get_socket(
            blender_material, "Roughness")

        hasMetal = metallic_socket is not None and __has_image_node_from_socket(
            metallic_socket)
        hasRough = roughness_socket is not None and __has_image_node_from_socket(
            roughness_socket)

        if not hasMetal and not hasRough:
            metallic_roughness = gltf2_blender_get.get_socket_old(
                blender_material, "MetallicRoughness")
            if metallic_roughness is None or not __has_image_node_from_socket(
                    metallic_roughness):
                return None
            texture_input = (metallic_roughness, )
        elif not hasMetal:
            texture_input = (roughness_socket, )
        elif not hasRough:
            texture_input = (metallic_socket, )
        else:
            texture_input = (metallic_socket, roughness_socket)

    return gltf2_blender_gather_texture_info.gather_texture_info(
        texture_input, export_settings)
def __gather_clearcoat_extension(blender_material, export_settings):
    clearcoat_enabled = False
    has_clearcoat_texture = False
    has_clearcoat_roughness_texture = False

    clearcoat_extension = {}
    clearcoat_roughness_slots = ()

    clearcoat_socket = gltf2_blender_get.get_socket(blender_material, 'Clearcoat')
    clearcoat_roughness_socket = gltf2_blender_get.get_socket(blender_material, 'Clearcoat Roughness')
    clearcoat_normal_socket = gltf2_blender_get.get_socket(blender_material, 'Clearcoat Normal')

    if isinstance(clearcoat_socket, bpy.types.NodeSocket) and not clearcoat_socket.is_linked:
        clearcoat_extension['clearcoatFactor'] = clearcoat_socket.default_value
        clearcoat_enabled = clearcoat_extension['clearcoatFactor'] > 0
    elif __has_image_node_from_socket(clearcoat_socket):
        clearcoat_extension['clearcoatFactor'] = 1
        has_clearcoat_texture = True
        clearcoat_enabled = True

    if not clearcoat_enabled:
        return None

    if isinstance(clearcoat_roughness_socket, bpy.types.NodeSocket) and not clearcoat_roughness_socket.is_linked:
        clearcoat_extension['clearcoatRoughnessFactor'] = clearcoat_roughness_socket.default_value
    elif __has_image_node_from_socket(clearcoat_roughness_socket):
        clearcoat_extension['clearcoatRoughnessFactor'] = 1
        has_clearcoat_roughness_texture = True

    # Pack clearcoat (R) and clearcoatRoughness (G) channels.
    if has_clearcoat_texture and has_clearcoat_roughness_texture:
        clearcoat_roughness_slots = (clearcoat_socket, clearcoat_roughness_socket,)
    elif has_clearcoat_texture:
        clearcoat_roughness_slots = (clearcoat_socket,)
    elif has_clearcoat_roughness_texture:
        clearcoat_roughness_slots = (clearcoat_roughness_socket,)

    if len(clearcoat_roughness_slots) > 0:
        if has_clearcoat_texture:
            clearcoat_extension['clearcoatTexture'] = gltf2_blender_gather_texture_info.gather_texture_info(
                clearcoat_socket,
                clearcoat_roughness_slots,
                export_settings,
            )
        if has_clearcoat_roughness_texture:
            clearcoat_extension['clearcoatRoughnessTexture'] = gltf2_blender_gather_texture_info.gather_texture_info(
                clearcoat_roughness_socket,
                clearcoat_roughness_slots,
                export_settings,
            )

    if __has_image_node_from_socket(clearcoat_normal_socket):
        clearcoat_extension['clearcoatNormalTexture'] = gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class(
            clearcoat_normal_socket,
            (clearcoat_normal_socket,),
            export_settings
        )

    return Extension('KHR_materials_clearcoat', clearcoat_extension, False)
Ejemplo n.º 5
0
def __gather_base_color_factor(blender_material, export_settings):
    alpha_socket = gltf2_blender_get.get_socket(blender_material, "Alpha")
    alpha = alpha_socket.default_value if alpha_socket is not None and not alpha_socket.is_linked else 1.0

    base_color_socket = gltf2_blender_get.get_socket(blender_material,
                                                     "Base Color")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket(
            blender_material, "BaseColor")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket_old(
            blender_material, "BaseColorFactor")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket(
            blender_material, "Background")
    if not isinstance(base_color_socket, bpy.types.NodeSocket):
        return None
    if not base_color_socket.is_linked:
        return list(base_color_socket.default_value)[:3] + [alpha]

    texture_node = __get_tex_from_socket(base_color_socket)
    if texture_node is None:
        return None

    def is_valid_multiply_node(node):
        return isinstance(node, bpy.types.ShaderNodeMixRGB) and \
               node.blend_type == "MULTIPLY" and \
               len(node.inputs) == 3

    multiply_node = next((link.from_node for link in texture_node.path
                          if is_valid_multiply_node(link.from_node)), None)
    if multiply_node is None:
        return None

    def is_factor_socket(socket):
        return isinstance(socket, bpy.types.NodeSocketColor) and \
               (not socket.is_linked or socket.links[0] not in texture_node.path)

    factor_socket = next(
        (socket
         for socket in multiply_node.inputs if is_factor_socket(socket)), None)
    if factor_socket is None:
        return None

    if factor_socket.is_linked:
        print_console(
            "WARNING",
            "BaseColorFactor only supports sockets without links (in Node '{}')."
            .format(multiply_node.name))
        return None

    return list(factor_socket.default_value)[:3] + [alpha]
def __gather_orm_texture(blender_material, export_settings):
    # Check for the presence of Occlusion, Roughness, Metallic sharing a single image.
    # If not fully shared, return None, so the images will be cached and processed separately.

    occlusion = gltf2_blender_get.get_socket(blender_material, "Occlusion")
    if occlusion is None or not __has_image_node_from_socket(occlusion):
        occlusion = gltf2_blender_get.get_socket_old(blender_material,
                                                     "Occlusion")
        if occlusion is None or not __has_image_node_from_socket(occlusion):
            return None

    metallic_socket = gltf2_blender_get.get_socket(blender_material,
                                                   "Metallic")
    roughness_socket = gltf2_blender_get.get_socket(blender_material,
                                                    "Roughness")

    hasMetal = metallic_socket is not None and __has_image_node_from_socket(
        metallic_socket)
    hasRough = roughness_socket is not None and __has_image_node_from_socket(
        roughness_socket)

    if not hasMetal and not hasRough:
        metallic_roughness = gltf2_blender_get.get_socket_old(
            blender_material, "MetallicRoughness")
        if metallic_roughness is None or not __has_image_node_from_socket(
                metallic_roughness):
            return None
        result = (occlusion, metallic_roughness)
    elif not hasMetal:
        result = (occlusion, roughness_socket)
    elif not hasRough:
        result = (occlusion, metallic_socket)
    else:
        result = (occlusion, roughness_socket, metallic_socket)

    if not gltf2_blender_gather_texture_info.check_same_size_images(result):
        print_console(
            "INFO",
            "Occlusion and metal-roughness texture will be exported separately "
            "(use same-sized images if you want them combined)")
        return None

    # Double-check this will past the filter in texture_info
    info = gltf2_blender_gather_texture_info.gather_texture_info(
        result[0], result, export_settings)
    if info is None:
        return None

    return result
Ejemplo n.º 7
0
def __gather_metallic_factor(blender_material, export_settings):
    metallic_socket = gltf2_blender_get.get_socket(blender_material, "Metallic")
    if metallic_socket is None:
        metallic_socket = gltf2_blender_get.get_socket_old(blender_material, "MetallicFactor")
    if isinstance(metallic_socket, bpy.types.NodeSocket) and not metallic_socket.is_linked:
        return metallic_socket.default_value
    return None
def __gather_emissive_texture(blender_material, export_settings):
    emissive = gltf2_blender_get.get_socket(blender_material, "Emissive")
    if emissive is None:
        emissive = gltf2_blender_get.get_socket_old(blender_material,
                                                    "Emissive")
    return gltf2_blender_gather_texture_info.gather_texture_info(
        emissive, (emissive, ), export_settings)
Ejemplo n.º 9
0
def __gather_base_color_texture(blender_material, export_settings):
    base_color_socket = gltf2_blender_get.get_socket(blender_material, "Base Color")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket(blender_material, "BaseColor")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket_old(blender_material, "BaseColor")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket(blender_material, "Background")

    alpha_socket = gltf2_blender_get.get_socket(blender_material, "Alpha")
    if alpha_socket is not None and alpha_socket.is_linked:
        inputs = (base_color_socket, alpha_socket, )
    else:
        inputs = (base_color_socket,)

    return gltf2_blender_gather_texture_info.gather_texture_info(inputs, export_settings)
Ejemplo n.º 10
0
def __gather_transmission_extension(blender_material, export_settings):
    transmission_enabled = False
    has_transmission_texture = False

    transmission_extension = {}
    transmission_slots = ()

    transmission_socket = gltf2_blender_get.get_socket(blender_material, 'Transmission')

    if isinstance(transmission_socket, bpy.types.NodeSocket) and not transmission_socket.is_linked:
        transmission_extension['transmissionFactor'] = transmission_socket.default_value
        transmission_enabled = transmission_extension['transmissionFactor'] > 0
    elif __has_image_node_from_socket(transmission_socket):
        transmission_extension['transmissionFactor'] = 1
        has_transmission_texture = True
        transmission_enabled = True

    if not transmission_enabled:
        return None

    # Pack transmission channel (R).
    if has_transmission_texture:
        transmission_slots = (transmission_socket,)

    if len(transmission_slots) > 0:
        combined_texture = gltf2_blender_gather_texture_info.gather_texture_info(transmission_slots, export_settings)
        if has_transmission_texture:
            transmission_extension['transmissionTexture'] = combined_texture

    return Extension('KHR_materials_transmission', transmission_extension, False)
def __gather_extensions(blender_material, export_settings):
    extensions = {}

    # KHR_materials_unlit

    if gltf2_blender_get.get_socket(blender_material,
                                    "Background") is not None:
        extensions["KHR_materials_unlit"] = Extension("KHR_materials_unlit",
                                                      {}, False)

    # KHR_materials_clearcoat

    clearcoat_extension = __gather_clearcoat_extension(blender_material,
                                                       export_settings)
    if clearcoat_extension:
        extensions["KHR_materials_clearcoat"] = clearcoat_extension

    # KHR_materials_transmission

    transmission_extension = __gather_transmission_extension(
        blender_material, export_settings)
    if transmission_extension:
        extensions["KHR_materials_transmission"] = transmission_extension

    return extensions if extensions else None
def __gather_occlusion_texture(blender_material, orm_texture, export_settings):
    occlusion = gltf2_blender_get.get_socket(blender_material, "Occlusion")
    if occlusion is None:
        occlusion = gltf2_blender_get.get_socket_old(blender_material,
                                                     "Occlusion")
    return gltf2_blender_gather_texture_info.gather_material_occlusion_texture_info_class(
        occlusion, orm_texture or (occlusion, ), export_settings)
Ejemplo n.º 13
0
def __gather_normal_texture(blender_material, export_settings):
    normal = gltf2_blender_get.get_socket(blender_material, "Normal")
    if normal is None:
        normal = gltf2_blender_get.get_socket_old(blender_material, "Normal")
    return gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class(
        (normal,),
        export_settings)
Ejemplo n.º 14
0
def __gather_roughness_factor(blender_material, export_settings):
    roughness_socket = gltf2_blender_get.get_socket(blender_material, "Roughness")
    if roughness_socket is None:
        roughness_socket = gltf2_blender_get.get_socket_old(blender_material, "RoughnessFactor")
    if isinstance(roughness_socket, bpy.types.NodeSocket) and not roughness_socket.is_linked:
        return roughness_socket.default_value
    return None
def __gather_normal_texture(blender_material, export_settings):
    normal = gltf2_blender_get.get_socket(blender_material, "Normal")
    if normal is None:
        normal = gltf2_blender_get.get_socket_old(blender_material, "Normal")
    normal_texture, use_active_uvmap_normal = gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class(
        normal, (normal, ), export_settings)
    return normal_texture, ["normalTexture"
                            ] if use_active_uvmap_normal else None
def __gather_base_color_texture(blender_material, export_settings):
    base_color_socket = gltf2_blender_get.get_socket(blender_material, "Base Color")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket(blender_material, "BaseColor")
    if base_color_socket is None:
        base_color_socket = gltf2_blender_get.get_socket_old(blender_material, "BaseColor")

    alpha_socket = gltf2_blender_get.get_socket(blender_material, "Alpha")

    # keep sockets that have some texture : color and/or alpha
    inputs = tuple(
        socket for socket in [base_color_socket, alpha_socket]
        if socket is not None and __has_image_node_from_socket(socket)
    )
    if not inputs:
        return None, None

    return gltf2_blender_gather_texture_info.gather_texture_info(inputs[0], inputs, export_settings)
def __gather_emissive_texture(blender_material, export_settings):
    emissive = gltf2_blender_get.get_socket(blender_material, "Emissive")
    if emissive is None:
        emissive = gltf2_blender_get.get_socket_old(blender_material,
                                                    "Emissive")
    emissive_texture, use_actives_uvmap_emissive = gltf2_blender_gather_texture_info.gather_texture_info(
        emissive, (emissive, ), export_settings)
    return emissive_texture, ["emissiveTexture"
                              ] if use_actives_uvmap_emissive else None
def __gather_occlusion_texture(blender_material, orm_texture, export_settings):
    occlusion = gltf2_blender_get.get_socket(blender_material, "Occlusion")
    if occlusion is None:
        occlusion = gltf2_blender_get.get_socket_old(blender_material,
                                                     "Occlusion")
    occlusion_texture, use_active_uvmap_occlusion = gltf2_blender_gather_texture_info.gather_material_occlusion_texture_info_class(
        occlusion, orm_texture or (occlusion, ), export_settings)
    return occlusion_texture, ["occlusionTexture"
                               ] if use_active_uvmap_occlusion else None
def __gather_roughness_factor(blender_material, export_settings):
    if not blender_material.use_nodes:
        return blender_material.roughness

    roughness_socket = gltf2_blender_get.get_socket(blender_material, "Roughness")
    if roughness_socket is None:
        roughness_socket = gltf2_blender_get.get_socket_old(blender_material, "RoughnessFactor")
    if isinstance(roughness_socket, bpy.types.NodeSocket):
        fac = gltf2_blender_get.get_factor_from_socket(roughness_socket, kind='VALUE')
        return fac if fac != 1 else None
    return None
def __gather_metallic_factor(blender_material, export_settings):
    if not blender_material.use_nodes:
        return blender_material.metallic

    metallic_socket = gltf2_blender_get.get_socket(blender_material, "Metallic")
    if metallic_socket is None:
        metallic_socket = gltf2_blender_get.get_socket_old(blender_material, "MetallicFactor")
    if isinstance(metallic_socket, bpy.types.NodeSocket):
        fac = gltf2_blender_get.get_factor_from_socket(metallic_socket, kind='VALUE')
        return fac if fac != 1 else None
    return None
Ejemplo n.º 21
0
def __gather_emissive_factor(blender_material, export_settings):
    emissive_socket = gltf2_blender_get.get_socket(blender_material, "Emissive")
    if emissive_socket is None:
        emissive_socket = gltf2_blender_get.get_socket_old(blender_material, "EmissiveFactor")
    if isinstance(emissive_socket, bpy.types.NodeSocket):
        if emissive_socket.is_linked:
            # In glTF, the default emissiveFactor is all zeros, so if an emission texture is connected,
            # we have to manually set it to all ones.
            return [1.0, 1.0, 1.0]
        else:
            return list(emissive_socket.default_value)[0:3]
    return None
Ejemplo n.º 22
0
def __gather_emissive_factor(blender_material, export_settings):
    emissive_socket = gltf2_blender_get.get_socket(blender_material, "Emissive")
    if emissive_socket is None:
        emissive_socket = gltf2_blender_get.get_socket_old(blender_material, "EmissiveFactor")
    if isinstance(emissive_socket, bpy.types.NodeSocket):
        fac = gltf2_blender_get.get_factor_from_socket(emissive_socket, kind='RGB')
        if fac is None and emissive_socket.is_linked:
            # In glTF, the default emissiveFactor is all zeros, so if an emission texture is connected,
            # we have to manually set it to all ones.
            fac = [1.0, 1.0, 1.0]
        if fac == [0, 0, 0]: fac = None
        return fac
    return None
Ejemplo n.º 23
0
def detect_shadeless_material(blender_material, export_settings):
    """Detect if this material is "shadeless" ie. should be exported
    with KHR_materials_unlit. Returns None if not. Otherwise, returns
    a dict with info from parsing the node tree.
    """
    if not blender_material.use_nodes: return None

    # Old Background node detection (unlikely to happen)
    bg_socket = gltf2_blender_get.get_socket(blender_material, "Background")
    if bg_socket is not None:
        return {'rgb_socket': bg_socket}

    # Look for
    # * any color socket, connected to...
    # * optionally, the lightpath trick, connected to...
    # * optionally, a mix-with-transparent (for alpha), connected to...
    # * the output node

    info = {}

    for node in blender_material.node_tree.nodes:
        if node.type == 'OUTPUT_MATERIAL':
            socket = node.inputs[0]
            break
    else:
        return None

    # Be careful not to misidentify a lightpath trick as mix-alpha.
    result = __detect_lightpath_trick(socket)
    if result is not None:
        socket = result['next_socket']
    else:
        result = __detect_mix_alpha(socket)
        if result is not None:
            socket = result['next_socket']
            info['alpha_socket'] = result['alpha_socket']

        result = __detect_lightpath_trick(socket)
        if result is not None:
            socket = result['next_socket']

    # Check if a color socket, or connected to a color socket
    if socket.type != 'RGBA':
        from_socket = gltf2_blender_get.previous_socket(socket)
        if from_socket is None: return None
        if from_socket.type != 'RGBA': return None

    info['rgb_socket'] = socket
    return info
Ejemplo n.º 24
0
def __gather_extensions(blender_material, export_settings):
    extensions = {}

    # KHR_materials_unlit

    if gltf2_blender_get.get_socket(blender_material,
                                    "Background") is not None:
        extensions["KHR_materials_unlit"] = Extension("KHR_materials_unlit",
                                                      {}, False)

    # KHR_materials_clearcoat

    clearcoat_extension = __gather_clearcoat_extension(blender_material,
                                                       export_settings)
    if clearcoat_extension:
        extensions["KHR_materials_clearcoat"] = clearcoat_extension

    # TODO KHR_materials_pbrSpecularGlossiness

    return extensions if extensions else None
def __gather_emissive_factor(blender_material, export_settings):
    emissive_socket = gltf2_blender_get.get_socket(blender_material,
                                                   "Emissive")
    if emissive_socket is None:
        emissive_socket = gltf2_blender_get.get_socket_old(
            blender_material, "EmissiveFactor")
    if isinstance(emissive_socket, bpy.types.NodeSocket):
        if export_settings['gltf_image_format'] != "NONE":
            factor = gltf2_blender_get.get_factor_from_socket(emissive_socket,
                                                              kind='RGB')
        else:
            factor = gltf2_blender_get.get_const_from_default_value_socket(
                emissive_socket, kind='RGB')

        if factor is None and emissive_socket.is_linked:
            # In glTF, the default emissiveFactor is all zeros, so if an emission texture is connected,
            # we have to manually set it to all ones.
            factor = [1.0, 1.0, 1.0]

        if factor is None: factor = [0.0, 0.0, 0.0]

        # Handle Emission Strength
        strength_socket = None
        if emissive_socket.node.type == 'EMISSION':
            strength_socket = emissive_socket.node.inputs['Strength']
        elif 'Emission Strength' in emissive_socket.node.inputs:
            strength_socket = emissive_socket.node.inputs['Emission Strength']
        strength = (gltf2_blender_get.get_const_from_socket(strength_socket,
                                                            kind='VALUE')
                    if strength_socket is not None else None)
        if strength is not None:
            factor = [f * strength for f in factor]

        # Clamp to range [0,1]
        factor = [min(1.0, f) for f in factor]

        if factor == [0, 0, 0]: factor = None

        return factor

    return None
def __gather_clearcoat_extension(blender_material, export_settings):
    clearcoat_enabled = False
    has_clearcoat_texture = False
    has_clearcoat_roughness_texture = False

    clearcoat_extension = {}
    clearcoat_roughness_slots = ()

    clearcoat_socket = gltf2_blender_get.get_socket(blender_material,
                                                    'Clearcoat')
    clearcoat_roughness_socket = gltf2_blender_get.get_socket(
        blender_material, 'Clearcoat Roughness')
    clearcoat_normal_socket = gltf2_blender_get.get_socket(
        blender_material, 'Clearcoat Normal')

    if isinstance(clearcoat_socket,
                  bpy.types.NodeSocket) and not clearcoat_socket.is_linked:
        clearcoat_extension['clearcoatFactor'] = clearcoat_socket.default_value
        clearcoat_enabled = clearcoat_extension['clearcoatFactor'] > 0
    elif __has_image_node_from_socket(clearcoat_socket):
        fac = gltf2_blender_get.get_factor_from_socket(clearcoat_socket,
                                                       kind='VALUE')
        # default value in glTF is 0.0, but if there is a texture without factor, use 1
        clearcoat_extension['clearcoatFactor'] = fac if fac != None else 1.0
        has_clearcoat_texture = True
        clearcoat_enabled = True

    if not clearcoat_enabled:
        return None, None

    if isinstance(
            clearcoat_roughness_socket,
            bpy.types.NodeSocket) and not clearcoat_roughness_socket.is_linked:
        clearcoat_extension[
            'clearcoatRoughnessFactor'] = clearcoat_roughness_socket.default_value
    elif __has_image_node_from_socket(clearcoat_roughness_socket):
        fac = gltf2_blender_get.get_factor_from_socket(
            clearcoat_roughness_socket, kind='VALUE')
        # default value in glTF is 0.0, but if there is a texture without factor, use 1
        clearcoat_extension[
            'clearcoatRoughnessFactor'] = fac if fac != None else 1.0
        has_clearcoat_roughness_texture = True

    # Pack clearcoat (R) and clearcoatRoughness (G) channels.
    if has_clearcoat_texture and has_clearcoat_roughness_texture:
        clearcoat_roughness_slots = (
            clearcoat_socket,
            clearcoat_roughness_socket,
        )
    elif has_clearcoat_texture:
        clearcoat_roughness_slots = (clearcoat_socket, )
    elif has_clearcoat_roughness_texture:
        clearcoat_roughness_slots = (clearcoat_roughness_socket, )

    use_actives_uvmaps = []

    if len(clearcoat_roughness_slots) > 0:
        if has_clearcoat_texture:
            clearcoat_texture, clearcoat_texture_use_active_uvmap = gltf2_blender_gather_texture_info.gather_texture_info(
                clearcoat_socket,
                clearcoat_roughness_slots,
                export_settings,
            )
            clearcoat_extension['clearcoatTexture'] = clearcoat_texture
            if clearcoat_texture_use_active_uvmap:
                use_actives_uvmaps.append("clearcoatTexture")
        if has_clearcoat_roughness_texture:
            clearcoat_roughness_texture, clearcoat_roughness_texture_use_active_uvmap = gltf2_blender_gather_texture_info.gather_texture_info(
                clearcoat_roughness_socket,
                clearcoat_roughness_slots,
                export_settings,
            )
            clearcoat_extension[
                'clearcoatRoughnessTexture'] = clearcoat_roughness_texture
            if clearcoat_roughness_texture_use_active_uvmap:
                use_actives_uvmaps.append("clearcoatRoughnessTexture")
    if __has_image_node_from_socket(clearcoat_normal_socket):
        clearcoat_normal_texture, clearcoat_normal_texture_use_active_uvmap = gltf2_blender_gather_texture_info.gather_material_normal_texture_info_class(
            clearcoat_normal_socket, (clearcoat_normal_socket, ),
            export_settings)
        clearcoat_extension[
            'clearcoatNormalTexture'] = clearcoat_normal_texture
        if clearcoat_normal_texture_use_active_uvmap:
            use_actives_uvmaps.append("clearcoatNormalTexture")

    return Extension('KHR_materials_clearcoat', clearcoat_extension,
                     False), use_actives_uvmaps