diff options
author | Julien Duroure <julien.duroure@gmail.com> | 2020-09-05 16:33:18 +0300 |
---|---|---|
committer | Julien Duroure <julien.duroure@gmail.com> | 2020-09-05 16:33:18 +0300 |
commit | 3a5aaa9b9999a0eada72076ba5b5bacc653e4528 (patch) | |
tree | e170b508072974a151c34ea4ea0fba70000a752a | |
parent | 109632093bd5f3c7754cf6d66cfe66579d734cb3 (diff) |
glTF exporter: materials: export factors from MULTIPLY nodes
4 files changed, 87 insertions, 48 deletions
diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index 71bd75d9..df5be122 100755 --- a/io_scene_gltf2/__init__.py +++ b/io_scene_gltf2/__init__.py @@ -15,7 +15,7 @@ bl_info = { 'name': 'glTF 2.0 format', 'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors', - "version": (1, 4, 15), + "version": (1, 4, 16), 'blender': (2, 90, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py index 3ad17fe2..0abe9256 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py @@ -111,12 +111,13 @@ def __gather_emissive_factor(blender_material, export_settings): 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: + 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. - return [1.0, 1.0, 1.0] - else: - return list(emissive_socket.default_value)[0:3] + fac = [1.0, 1.0, 1.0] + if fac == [0, 0, 0]: fac = None + return fac return None diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_pbr_metallic_roughness.py b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_pbr_metallic_roughness.py index 7913d175..05f94202 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_pbr_metallic_roughness.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_pbr_metallic_roughness.py @@ -47,8 +47,11 @@ def __filter_pbr_material(blender_material, export_settings): def __gather_base_color_factor(blender_material, export_settings): + rgb, alpha = None, None + 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 + 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: @@ -57,38 +60,16 @@ def __gather_base_color_factor(blender_material, export_settings): 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) + if isinstance(base_color_socket, bpy.types.NodeSocket): + rgb = gltf2_blender_get.get_factor_from_socket(base_color_socket, kind='RGB') - factor_socket = next((socket for socket in multiply_node.inputs if is_factor_socket(socket)), None) - if factor_socket is None: - return None + if rgb is None: rgb = [1.0, 1.0, 1.0] + if alpha is None: alpha = 1.0 - if factor_socket.is_linked: - print_console("WARNING", "BaseColorFactor only supports sockets without links (in Node '{}')." - .format(multiply_node.name)) - return None + rgba = [*rgb, alpha] - return list(factor_socket.default_value)[:3] + [alpha] + if rgba == [1, 1, 1, 1]: return None + return rgba def __gather_base_color_texture(blender_material, export_settings): @@ -109,15 +90,6 @@ def __gather_base_color_texture(blender_material, export_settings): return gltf2_blender_gather_texture_info.gather_texture_info(inputs, export_settings) -def __get_tex_from_socket(blender_shader_socket: bpy.types.NodeSocket): - result = gltf2_blender_search_node_tree.from_socket( - blender_shader_socket, - gltf2_blender_search_node_tree.FilterByType(bpy.types.ShaderNodeTexImage)) - if not result: - return None - return result[0] - - def __gather_extensions(blender_material, export_settings): return None @@ -130,8 +102,9 @@ 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 + 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 @@ -164,8 +137,9 @@ 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 + 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 __has_image_node_from_socket(socket): diff --git a/io_scene_gltf2/blender/exp/gltf2_blender_get.py b/io_scene_gltf2/blender/exp/gltf2_blender_get.py index 4f66aa6a..27f4ae18 100755 --- a/io_scene_gltf2/blender/exp/gltf2_blender_get.py +++ b/io_scene_gltf2/blender/exp/gltf2_blender_get.py @@ -218,3 +218,67 @@ def get_node(data_path): return None return node_name[:(index)] + + +def get_factor_from_socket(socket, kind): + """ + For baseColorFactor, metallicFactor, etc. + Get a constant value from a socket, or a constant value + from a MULTIPLY node just before the socket. + kind is either 'RGB' or 'VALUE'. + """ + fac = __get_const_from_socket(socket, kind) + if fac is not None: + return fac + + node = __previous_node(socket) + if node is not None: + x1, x2 = None, None + if kind == 'RGB': + if node.type == 'MIX_RGB' and node.blend_type == 'MULTIPLY': + # TODO: handle factor in inputs[0]? + x1 = __get_const_from_socket(node.inputs[1], kind) + x2 = __get_const_from_socket(node.inputs[2], kind) + if kind == 'VALUE': + if node.type == 'MATH' and node.operation == 'MULTIPLY': + x1 = __get_const_from_socket(node.inputs[0], kind) + x2 = __get_const_from_socket(node.inputs[1], kind) + if x1 is not None and x2 is None: return x1 + if x2 is not None and x1 is None: return x2 + + return None + + +def __get_const_from_socket(socket, kind): + if not socket.is_linked: + if kind == 'RGB': + if socket.type != 'RGBA': return None + return list(socket.default_value)[:3] + if kind == 'VALUE': + if socket.type != 'VALUE': return None + return socket.default_value + + # Handle connection to a constant RGB/Value node + prev_node = __previous_node(socket) + if prev_node is not None: + if kind == 'RGB' and prev_node.type == 'RGB': + return list(prev_node.outputs[0].default_value)[:3] + if kind == 'VALUE' and prev_node.type == 'VALUE': + return prev_node.outputs[0].default_value + + return None + + +def __previous_node(socket): + while True: + if not socket.is_linked: + return None + + node = socket.links[0].from_node + + # Skip over reroute nodes + if node.type == 'REROUTE': + socket = node.inputs[0] + continue + + return node |