Exemple #1
0
def __get_image_data(sockets_or_slots, export_settings) -> ExportImage:
    # For shared resources, such as images, we just store the portion of data that is needed in the glTF property
    # in a helper class. During generation of the glTF in the exporter these will then be combined to actual binary
    # resources.
    if __is_socket(sockets_or_slots):
        results = [__get_tex_from_socket(socket, export_settings) for socket in sockets_or_slots]
        composed_image = ExportImage()
        for result, socket in zip(results, sockets_or_slots):
            if result.shader_node.image.channels == 0:
                gltf2_io_debug.print_console("WARNING",
                                             "Image '{}' has no color channels and cannot be exported.".format(
                                                 result.shader_node.image))
                continue

            # rudimentarily try follow the node tree to find the correct image data.
            src_chan = Channel.R
            for elem in result.path:
                if isinstance(elem.from_node, bpy.types.ShaderNodeSeparateRGB):
                   src_chan = {
                        'R': Channel.R,
                        'G': Channel.G,
                        'B': Channel.B,
                    }[elem.from_socket.name]
                if elem.from_socket.name == 'Alpha':
                    src_chan = Channel.A

            dst_chan = None

            # some sockets need channel rewriting (gltf pbr defines fixed channels for some attributes)
            if socket.name == 'Metallic':
                dst_chan = Channel.B
            elif socket.name == 'Roughness':
                dst_chan = Channel.G
            elif socket.name == 'Occlusion' and len(sockets_or_slots) > 1 and sockets_or_slots[1] is not None:
                dst_chan = Channel.R
            elif socket.name == 'Alpha' and len(sockets_or_slots) > 1 and sockets_or_slots[1] is not None:
                dst_chan = Channel.A

            if dst_chan is not None:
                composed_image.fill_image(result.shader_node.image, dst_chan, src_chan)

                # Since metal/roughness are always used together, make sure
                # the other channel is filled.
                if socket.name == 'Metallic' and not composed_image.is_filled(Channel.G):
                    composed_image.fill_white(Channel.G)
                elif socket.name == 'Roughness' and not composed_image.is_filled(Channel.B):
                    composed_image.fill_white(Channel.B)
            else:
                # copy full image...eventually following sockets might overwrite things
                composed_image = ExportImage.from_blender_image(result.shader_node.image)

        return composed_image

    elif __is_slot(sockets_or_slots):
        texture = __get_tex_from_slot(sockets_or_slots[0])
        image = ExportImage.from_blender_image(texture.image)
        return image
    else:
        raise NotImplementedError()
def __get_image_data(sockets, export_settings) -> ExportImage:
    # For shared resources, such as images, we just store the portion of data that is needed in the glTF property
    # in a helper class. During generation of the glTF in the exporter these will then be combined to actual binary
    # resources.
    results = [
        __get_tex_from_socket(socket, export_settings) for socket in sockets
    ]
    composed_image = ExportImage()
    for result, socket in zip(results, sockets):
        if result.shader_node.image.channels == 0:
            gltf2_io_debug.print_console(
                "WARNING",
                "Image '{}' has no color channels and cannot be exported.".
                format(result.shader_node.image))
            continue

        # Assume that user know what he does, and that channels/images are already combined correctly for pbr
        # If not, we are going to keep only the first texture found
        # Example : If user set up 2 or 3 different textures for Metallic / Roughness / Occlusion
        # Only 1 will be used at export
        # This Warning is displayed in UI of this option
        if export_settings['gltf_keep_original_textures']:
            composed_image = ExportImage.from_original(
                result.shader_node.image)

        else:
            # rudimentarily try follow the node tree to find the correct image data.
            src_chan = Channel.R
            for elem in result.path:
                if isinstance(elem.from_node, bpy.types.ShaderNodeSeparateRGB):
                    src_chan = {
                        'R': Channel.R,
                        'G': Channel.G,
                        'B': Channel.B,
                    }[elem.from_socket.name]
                if elem.from_socket.name == 'Alpha':
                    src_chan = Channel.A

            dst_chan = None

            # some sockets need channel rewriting (gltf pbr defines fixed channels for some attributes)
            if socket.name == 'Metallic':
                dst_chan = Channel.B
            elif socket.name == 'Roughness':
                dst_chan = Channel.G
            elif socket.name == 'Occlusion':
                dst_chan = Channel.R
            elif socket.name == 'Alpha':
                dst_chan = Channel.A
            elif socket.name == 'Clearcoat':
                dst_chan = Channel.R
            elif socket.name == 'Clearcoat Roughness':
                dst_chan = Channel.G

            if dst_chan is not None:
                composed_image.fill_image(result.shader_node.image, dst_chan,
                                          src_chan)

                # Since metal/roughness are always used together, make sure
                # the other channel is filled.
                if socket.name == 'Metallic' and not composed_image.is_filled(
                        Channel.G):
                    composed_image.fill_white(Channel.G)
                elif socket.name == 'Roughness' and not composed_image.is_filled(
                        Channel.B):
                    composed_image.fill_white(Channel.B)
            else:
                # copy full image...eventually following sockets might overwrite things
                composed_image = ExportImage.from_blender_image(
                    result.shader_node.image)

    return composed_image