def __gather_base_color_texture(blender_material, export_settings): base_color_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot_old( blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Background") alpha_socket = gltf2_blender_get.get_socket_or_texture_slot( 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)
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_or_texture_slot( blender_material, "Metallic") roughness_socket = gltf2_blender_get.get_socket_or_texture_slot( 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_or_texture_slot_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_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_or_texture_slot( blender_material, "Occlusion") if occlusion is None or not __has_image_node_from_socket(occlusion): occlusion = gltf2_blender_get.get_socket_or_texture_slot_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_or_texture_slot( blender_material, "Metallic") roughness_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Roughness") if metallic_socket is None or roughness_socket is None\ or not __has_image_node_from_socket(metallic_socket)\ or not __has_image_node_from_socket(roughness_socket): metallic_roughness = gltf2_blender_get.get_socket_or_texture_slot_old( blender_material, "MetallicRoughness") if metallic_roughness is None or not __has_image_node_from_socket( metallic_roughness): return None return (occlusion, metallic_roughness, metallic_roughness) return (occlusion, roughness_socket, metallic_socket)
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_or_texture_slot(blender_material, "Occlusion") if occlusion is None or not __has_image_node_from_socket(occlusion): occlusion = gltf2_blender_get.get_socket_or_texture_slot_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_or_texture_slot(blender_material, "Metallic") roughness_socket = gltf2_blender_get.get_socket_or_texture_slot(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_or_texture_slot_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) # Double-check this will past the filter in texture_info (otherwise there are different resolutions or other problems). info = gltf2_blender_gather_texture_info.gather_texture_info(result, export_settings) if info is None: return None return result
def __gather_base_color_texture(blender_material, export_settings): base_color_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "BaseColor") return gltf2_blender_gather_texture_info.gather_texture_info( (base_color_socket, ), export_settings)
def __gather_base_color_texture(blender_material, export_settings): base_color_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot_old(blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Background") return gltf2_blender_gather_texture_info.gather_texture_info((base_color_socket,), export_settings)
def __gather_base_color_factor(blender_material, export_settings): base_color_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "BaseColor") if isinstance(base_color_socket, bpy.types.NodeSocket) and not base_color_socket.is_linked: return list(base_color_socket.default_value) return None
def __gather_metallic_roughness_texture(blender_material, export_settings): metallic_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Metallic") roughness_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Roughness") if metallic_socket is None and roughness_socket is None: metallic_roughness = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "MetallicRoughness") texture_input = (metallic_roughness,) else: texture_input = (metallic_socket, roughness_socket) return gltf2_blender_gather_texture_info.gather_texture_info(texture_input, export_settings)
def __gather_base_color_factor(blender_material, export_settings): base_color_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot_old( blender_material, "BaseColorFactor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot( 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) for link in base_color_socket.links: if link.from_node.name == "albedo_tint": return list(link.from_node.outputs["Color"].default_value) 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)
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_or_texture_slot(blender_material, 'Clearcoat') clearcoat_roughness_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, 'Clearcoat Roughness') clearcoat_normal_socket = gltf2_blender_get.get_socket_or_texture_slot(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: combined_texture = gltf2_blender_gather_texture_info.gather_texture_info(clearcoat_roughness_slots, export_settings) if has_clearcoat_texture: clearcoat_extension['clearcoatTexture'] = combined_texture if has_clearcoat_roughness_texture: clearcoat_extension['clearcoatRoughnessTexture'] = combined_texture if __has_image_node_from_socket(clearcoat_normal_socket): clearcoat_extension['clearcoatNormalTexture'] = gltf2_blender_gather_material_normal_texture_info_class.gather_material_normal_texture_info_class( (clearcoat_normal_socket,), export_settings ) return Extension('KHR_materials_clearcoat', clearcoat_extension, False)
def __gather_metallic_factor(blender_material, export_settings): metallic_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Metallic") if metallic_socket is None: metallic_socket = gltf2_blender_get.get_socket_or_texture_slot_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_roughness_factor(blender_material, export_settings): roughness_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Roughness") if roughness_socket is None: roughness_socket = gltf2_blender_get.get_socket_or_texture_slot_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_roughness_factor(blender_material, export_settings): roughness_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Roughness") if roughness_socket is None: roughness_socket = gltf2_blender_get.get_socket_or_texture_slot_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_metallic_factor(blender_material, export_settings): metallic_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Metallic") if metallic_socket is None: metallic_socket = gltf2_blender_get.get_socket_or_texture_slot_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_normal_texture(blender_material, export_settings): normal = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Normal") if normal is None: normal = gltf2_blender_get.get_socket_or_texture_slot_old(blender_material, "Normal") return gltf2_blender_gather_material_normal_texture_info_class.gather_material_normal_texture_info_class( (normal,), export_settings)
def __gather_emissive_factor(blender_material, export_settings): emissive_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Emissive") if emissive_socket is None: emissive_socket = gltf2_blender_get.get_socket_or_texture_slot_old(blender_material, "EmissiveFactor") if isinstance(emissive_socket, bpy.types.NodeSocket) and not emissive_socket.is_linked: return list(emissive_socket.default_value)[0:3] return None
def __gather_occlusion_texture(blender_material, export_settings): occlusion = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Occlusion") if occlusion is None: occlusion = gltf2_blender_get.get_socket_or_texture_slot_old(blender_material, "Occlusion") return gltf2_blender_gather_material_occlusion_texture_info_class.gather_material_occlusion_texture_info_class( (occlusion,), export_settings)
def __gather_normal_texture(blender_material, export_settings): normal = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Normal") if normal is None: normal = gltf2_blender_get.get_socket_or_texture_slot_old(blender_material, "Normal") return gltf2_blender_gather_material_normal_texture_info_class.gather_material_normal_texture_info_class( (normal,), export_settings)
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_or_texture_slot(blender_material, "Metallic") roughness_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Roughness") if metallic_socket is None and roughness_socket is None: metallic_roughness = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "MetallicRoughness") if metallic_roughness is None: metallic_roughness = gltf2_blender_get.get_socket_or_texture_slot_old(blender_material, "MetallicRoughness") texture_input = (metallic_roughness,) else: texture_input = (metallic_socket, roughness_socket) return gltf2_blender_gather_texture_info.gather_texture_info(texture_input, export_settings)
def __gather_emissive_texture(blender_material, export_settings): emissive = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Emissive") if emissive is None: emissive = gltf2_blender_get.get_socket_or_texture_slot_old( blender_material, "Emissive") return gltf2_blender_gather_texture_info.gather_texture_info( (emissive, ), export_settings)
def __gather_extensions(blender_material, export_settings): extensions = {} if gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Background") is not None: extensions["KHR_materials_unlit"] = Extension("KHR_materials_unlit", {}, False) # TODO specular glossiness extension return extensions if extensions else None
def __gather_extensions(blender_material, export_settings): extensions = {} if gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Background") is not None: extensions["KHR_materials_unlit"] = Extension("KHR_materials_unlit", {}, False) # TODO specular glossiness extension return extensions if extensions else None
def __gather_occlusion_texture(blender_material, orm_texture, export_settings): if orm_texture is not None: return gltf2_blender_gather_material_occlusion_texture_info_class.gather_material_occlusion_texture_info_class( orm_texture, export_settings) occlusion = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Occlusion") if occlusion is None: occlusion = gltf2_blender_get.get_socket_or_texture_slot_old(blender_material, "Occlusion") return gltf2_blender_gather_material_occlusion_texture_info_class.gather_material_occlusion_texture_info_class( (occlusion,), export_settings)
def __gather_emissive_factor(blender_material, export_settings): emissive_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Emissive") if emissive_socket is None: emissive_socket = gltf2_blender_get.get_socket_or_texture_slot_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
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_or_texture_slot(blender_material, "Occlusion") if occlusion is None or not __has_image_node_from_socket(occlusion): occlusion = gltf2_blender_get.get_socket_or_texture_slot_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_or_texture_slot(blender_material, "Metallic") roughness_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Roughness") if metallic_socket is None or roughness_socket is None\ or not __has_image_node_from_socket(metallic_socket)\ or not __has_image_node_from_socket(roughness_socket): metallic_roughness = gltf2_blender_get.get_socket_or_texture_slot_old(blender_material, "MetallicRoughness") if metallic_roughness is None or not __has_image_node_from_socket(metallic_roughness): return None return (occlusion, metallic_roughness, metallic_roughness) return (occlusion, roughness_socket, metallic_socket)
def __gather_emissive_factor(blender_material, export_settings): emissive_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Emissive") if emissive_socket is None: emissive_socket = gltf2_blender_get.get_socket_or_texture_slot_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
def __gather_base_color_factor(blender_material, export_settings): base_color_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Base Color") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "BaseColor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot_old(blender_material, "BaseColorFactor") if base_color_socket is None: base_color_socket = gltf2_blender_get.get_socket_or_texture_slot(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) 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)
def __gather_metallic_factor(blender_material, export_settings): metallic_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Metallic") if metallic_socket is None: metallic_socket = gltf2_blender_get.get_socket_or_texture_slot_old( blender_material, "MetallicFactor") if isinstance(metallic_socket, bpy.types.NodeSocket): if len(metallic_socket.links) == 0: return metallic_socket.default_value for link in metallic_socket.links: if link.from_node.name == "metallic_scale": return link.from_node.outputs["Value"].default_value return None
def __gather_roughness_factor(blender_material, export_settings): roughness_socket = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Roughness") if roughness_socket is None: roughness_socket = gltf2_blender_get.get_socket_or_texture_slot_old( blender_material, "RoughnessFactor") if isinstance(roughness_socket, bpy.types.NodeSocket): if len(roughness_socket.links) == 0: return roughness_socket.default_value for link in roughness_socket.links: if link.from_node.name == "roughness_scale": return link.from_node.outputs["Value"].default_value return None
def __gather_extensions(blender_material, export_settings): extensions = {} if bpy.app.version < (2, 80, 0): if blender_material.use_shadeless: extensions["KHR_materials_unlit"] = Extension( "KHR_materials_unlit", {}, False) else: if gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Background") is not None: extensions["KHR_materials_unlit"] = Extension( "KHR_materials_unlit", {}, False) if blender_material.get("useVideoTextureExtension", False) == "True": image_name = blender_material.get( "videoTextureExtension_DiffuseImageName") if image_name is not None: image = bpy.data.images[image_name] if image is not None and image.source == "MOVIE": data = tmp_encode_movie(image) mime_type = __gather_mimetype(image) image_base_name, _extension = path.splitext(image_name) if mime_type is not None: # Create an image, either in a buffer view or in a separate file source = gltf2_io.Image(buffer_view=__gather_buffer_view( data, export_settings), extensions=None, extras=None, mime_type=mime_type, name=image_base_name, uri=__gather_uri( data, image_base_name, mime_type, export_settings)) # Create a texture to use the previous video image texture = gltf2_io.Texture(extensions=None, extras=None, name=None, sampler=None, source=source) extension = dict(diffuse=texture) extensions["SVRF_video_texture"] = Extension( "SVRF_video_texture", extension, False) # TODO specular glossiness extension return extensions if extensions else None
def __gather_extensions(blender_material, export_settings): extensions = {} # KHR_materials_unlit if gltf2_blender_get.get_socket_or_texture_slot(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_texture(blender_material, export_settings): emissive = gltf2_blender_get.get_socket_or_texture_slot(blender_material, "Emissive") if emissive is None: emissive = gltf2_blender_get.get_socket_or_texture_slot_old(blender_material, "Emissive") return gltf2_blender_gather_texture_info.gather_texture_info((emissive,), export_settings)
def __gather_occlusion_texture(blender_material, export_settings): emissive = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Occlusion") return gltf2_blender_gather_material_occlusion_texture_info_class.gather_material_occlusion_texture_info_class( (emissive, ), export_settings)