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)
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_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_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)
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_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_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_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_texture(info, export_settings): sockets = (info.get('rgb_socket'), info.get('alpha_socket')) sockets = tuple(s for s in sockets if s is not None) if sockets: # NOTE: separate RGB and Alpha textures will not get combined # because gather_image determines how to pack images based on the # names of sockets, and the names are hard-coded to a Principled # style graph. return gltf2_blender_gather_texture_info.gather_texture_info( sockets[0], sockets, export_settings, ) 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(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
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_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_lightmap_texture_info(blender_material, export_settings): nodes = blender_material.node_tree.nodes lightmap_node = next((n for n in nodes if isinstance(n, MozLightmapNode)), None) if not lightmap_node: return texture_socket = lightmap_node.inputs.get("Lightmap") intensity = lightmap_node.intensity texture_info = gather_texture_info(texture_socket, (texture_socket,), export_settings) if not texture_info: return return { "intensity": intensity, 'extensions': texture_info.extensions, 'extras': texture_info.extras, "index": texture_info.index, "texCoord": texture_info.tex_coord }
def __gather_extensions(blender_material, export_settings): extensions = {} if blender_material.msfs_material_type == "msfs_anisotropic": extensions["ASOBO_material_anisotropic"] = {} elif blender_material.msfs_material_type == "msfs_sss" or blender_material.msfs_material_type == "msfs_hair": # sss and hair are basically the same extensions["ASOBO_material_SSS"] = { "SSSColor": [blender_material.msfs_color_sss[0],blender_material.msfs_color_sss[1],blender_material.msfs_color_sss[2],blender_material.msfs_color_sss[3]] } elif blender_material.msfs_material_type == "msfs_glass": if blender_material.msfs_glass_reflection_mask_factor != 0.0 or blender_material.msfs_glass_deformation_factor != 0.0: extensions["ASOBO_material_kitty_glass"] = { "glassReflectionMaskFactor": blender_material.msfs_glass_reflection_mask_factor, "glassDeformationFactor": blender_material.msfs_glass_deformation_factor } else: extensions["ASOBO_material_glass"] = {} elif blender_material.msfs_material_type == "msfs_clearcoat": extensions["ASOBO_material_clear_coat"] = {"dirtTexture" : blender_material.msfs_clearcoat_texture} elif blender_material.msfs_material_type == "msfs_env_occluder": extensions["ASOBO_material_environment_occluder"] = {} elif blender_material.msfs_material_type == "msfs_fake_terrain": extensions["ASOBO_material_fake_terrain"] = {} elif blender_material.msfs_material_type == "msfs_fresnel": extensions["ASOBO_material_fresnel_fade"] = { "fresnelFactor": blender_material.msfs_fresnel_factor, "fresnelOpacityOffset": blender_material.msfs_fresnel_opacity_bias } elif blender_material.msfs_material_type == "msfs_parallax": extension = { "parallaxScale": blender_material.msfs_parallax_scale, "roomSizeXScale": blender_material.msfs_parallax_room_size_x, "roomSizeYScale": blender_material.msfs_parallax_room_size_y, "roomNumberXY": blender_material.msfs_parallax_room_number, "corridor": blender_material.msfs_parallax_corridor } if blender_material.msfs_behind_glass_texture != None: node = nodes.get("albedo_detail_mix") if node != None: inputs = (node.inputs["Color2"],) behind_glass_texture = gather_texture_info(inputs, export_settings) if behind_glass_texture != None: extension["behindWindowMapTexture"] = behind_glass_texture extensions["ASOBO_material_parallax_window"] = extension elif blender_material.msfs_material_type == "msfs_invisible": extensions["ASOBO_material_invisible"] = {} # other extensions if blender_material.msfs_show_blend_mode == True: if blender_material.msfs_blend_mode == 'DITHER': extensions["ASOBO_material_alphamode_dither"] = {} if (blender_material.msfs_show_road_material == True or blender_material.msfs_show_collision_material == True): if (blender_material.msfs_road_material == True or blender_material.msfs_collision_material == True): tags = [] if blender_material.msfs_road_material == True: tags.append("Road") if blender_material.msfs_collision_material == True: tags.append("Collision") extensions["ASOBO_tags"] = {"tags" : tags} if blender_material.msfs_show_day_night_cycle == True: if blender_material.msfs_day_night_cycle == True: extensions["ASOBO_material_day_night_switch"] = {} if blender_material.msfs_show_draworder == True: if blender_material.msfs_draw_order > 0: extensions["ASOBO_material_draw_order"] = {"drawOrderOffset": blender_material.msfs_draw_order} if blender_material.msfs_show_no_cast_shadow == True: if blender_material.msfs_no_cast_shadow == True: extensions["ASOBO_material_shadow_options"] = {"noCastShadow": blender_material.msfs_no_cast_shadow} if (blender_material.msfs_show_ao_use_uv2 == True or blender_material.msfs_show_uv_clamp == True): if (blender_material.msfs_ao_use_uv2 == True or blender_material.msfs_uv_clamp_x == True or blender_material.msfs_uv_clamp_y == True): extensions["ASOBO_material_UV_options"] = { "AOUseUV2": blender_material.msfs_ao_use_uv2, "clampUVX": blender_material.msfs_uv_clamp_x, "clampUVY": blender_material.msfs_uv_clamp_y } if (blender_material.msfs_show_detail_albedo == True or blender_material.msfs_show_detail_metallic == True or blender_material.msfs_show_detail_normal == True): nodes = blender_material.node_tree.nodes detail_extension = {} if blender_material.msfs_detail_albedo_texture != None: node = nodes.get("albedo_detail_mix") if node != None: inputs = (node.inputs["Color2"],) albedo_detail_texture = gather_texture_info(inputs, export_settings) if albedo_detail_texture != None: detail_extension["detailColorTexture"] = albedo_detail_texture if blender_material.msfs_detail_metallic_texture != None: node = nodes.get("metallic_detail_mix") if node != None: inputs = (node.inputs["Color2"],) metallic_detail_texture = gather_texture_info(inputs, export_settings) if metallic_detail_texture != None: detail_extension["detailMetalRoughAOTexture"] = metallic_detail_texture if blender_material.msfs_detail_normal_texture != None: node = nodes.get("normal_detail_mix") if node != None: inputs = (node.inputs["Color2"],) normal_detail_texture = gather_texture_info(inputs, export_settings) if normal_detail_texture != None: detail_extension["detailNormalTexture"] = normal_detail_texture if len(detail_extension) > 0: detail_extension["UVScale"] = blender_material.msfs_detail_uv_scale detail_extension["UVOffset"] = (blender_material.msfs_detail_uv_offset_x,blender_material.msfs_detail_uv_offset_y) detail_extension["blendTreshold"] = blender_material.msfs_blend_threshold extensions["ASOBO_material_detail_map"] = detail_extension if blender_material.msfs_material_type == "msfs_decal": extensions["ASOBO_material_blend_gbuffer"] = { "baseColorBlendFactor": blender_material.msfs_decal_blend_factor_color, "metallicBlendFactor": blender_material.msfs_decal_blend_factor_metal, "roughnessBlendFactor": blender_material.msfs_decal_blend_factor_roughness, "normalBlendFactor": blender_material.msfs_decal_blend_factor_normal, "emissiveBlendFactor": blender_material.msfs_decal_blend_factor_emissive, "occlusionBlendFactor": blender_material.msfs_decal_blend_factor_occlusion } if blender_material.msfs_material_type == "msfs_geo_decal": extensions["ASOBO_material_blend_gbuffer"] = { "baseColorBlendFactor": blender_material.msfs_decal_blend_factor_color, "metallicBlendFactor": blender_material.msfs_decal_blend_factor_metal, "roughnessBlendFactor": blender_material.msfs_decal_blend_factor_roughness, "normalBlendFactor": blender_material.msfs_decal_blend_factor_normal, "emissiveBlendFactor": blender_material.msfs_decal_blend_factor_emissive, "occlusionBlendFactor": blender_material.msfs_decal_blend_factor_occlusion } return extensions
def __gather_emissive_texture(blender_material, export_settings): emissive = gltf2_blender_get.get_socket_or_texture_slot( blender_material, "Emissive") return gltf2_blender_gather_texture_info.gather_texture_info( (emissive, ), 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_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