[Bf-extensions-cvs] [3a5aaa9b] master: glTF exporter: materials: export factors from MULTIPLY nodes

Julien Duroure noreply at git.blender.org
Sat Sep 5 15:33:28 CEST 2020


Commit: 3a5aaa9b9999a0eada72076ba5b5bacc653e4528
Author: Julien Duroure
Date:   Sat Sep 5 15:33:18 2020 +0200
Branches: master
https://developer.blender.org/rBA3a5aaa9b9999a0eada72076ba5b5bacc653e4528

glTF exporter: materials: export factors from MULTIPLY nodes

===================================================================

M	io_scene_gltf2/__init__.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_materials.py
M	io_scene_gltf2/blender/exp/gltf2_blender_gather_materials_pbr_metallic_roughness.py
M	io_scene_gltf2/blender/exp/gltf2_blender_get.py

===================================================================

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



More information about the Bf-extensions-cvs mailing list