From 0c80147dd843833e280e66bdab9c3666fcf0ad6a Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Sat, 16 Sep 2023 17:23:26 +0200 Subject: [PATCH 01/11] WIP - manage Vertex Color at export - when used in node tree --- addons/io_scene_gltf2/__init__.py | 6 +- ...gltf2_blender_gather_primitives_extract.py | 181 ++++++++++++------ .../blender/exp/gltf2_blender_get.py | 40 ++++ .../gltf2_blender_gather_materials.py | 5 +- ...gather_materials_pbr_metallic_roughness.py | 24 +-- .../gltf2_blender_gather_materials_unlit.py | 3 +- .../gltf2_blender_search_node_tree.py | 3 +- 7 files changed, 186 insertions(+), 76 deletions(-) diff --git a/addons/io_scene_gltf2/__init__.py b/addons/io_scene_gltf2/__init__.py index 0c9aa968b..6b9cf0518 100644 --- a/addons/io_scene_gltf2/__init__.py +++ b/addons/io_scene_gltf2/__init__.py @@ -316,8 +316,8 @@ def __init__(self): ) export_colors: BoolProperty( - name='Vertex Colors', - description='Export vertex colors with meshes', + name='dummy', + description='Keep for compatibility only', default=True ) @@ -748,7 +748,6 @@ def execute(self, context): export_settings['gltf_draco_mesh_compression'] = False export_settings['gltf_materials'] = self.export_materials - export_settings['gltf_colors'] = self.export_colors export_settings['gltf_attributes'] = self.export_attributes export_settings['gltf_cameras'] = self.export_cameras @@ -1004,7 +1003,6 @@ def draw(self, context): col = layout.column() col.active = operator.export_normals col.prop(operator, 'export_tangents') - layout.prop(operator, 'export_colors') layout.prop(operator, 'export_attributes') col = layout.column() diff --git a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py index d722e15e2..d6cea83e4 100644 --- a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py +++ b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py @@ -20,7 +20,7 @@ from ...io.exp.gltf2_io_user_extensions import export_user_extensions from ...io.com import gltf2_io_constants from ..com import gltf2_blender_conversion -from .material.gltf2_blender_gather_materials import get_base_material +from .material.gltf2_blender_gather_materials import get_base_material, get_material_from_idx from . import gltf2_blender_gather_skins @@ -34,7 +34,7 @@ def extract_primitives(materials, blender_mesh, uuid_for_skined_data, blender_ve primitive_creator.create_dots_data_structure() primitive_creator.populate_dots_data() primitive_creator.primitive_split() - primitive_creator.material_uvmap_attribute_add() + primitive_creator.manage_material_info() # UVMap & Vertex Color return primitive_creator.primitive_creation() class PrimitiveCreator: @@ -154,7 +154,7 @@ def __init__(self, attr_name): self.attr_name = attr_name self.keep = attr_name.startswith("_") - # Manage attributes + COLOR_0 + # Manage attributes for blender_attribute_index, blender_attribute in enumerate(self.blender_mesh.attributes): attr = {} @@ -174,42 +174,27 @@ def __init__(self, attr_name): continue - if self.blender_mesh.color_attributes.find(blender_attribute.name) == self.blender_mesh.color_attributes.render_color_index \ - and self.blender_mesh.color_attributes.render_color_index != -1: - - if self.export_settings['gltf_colors'] is False: - continue - attr['gltf_attribute_name'] = 'COLOR_0' - attr['get'] = self.get_function() - - # Seems we sometime can have name collision about attributes - # Avoid crash and ignoring one of duplicated attribute name - if 'COLOR_0' in [a['gltf_attribute_name'] for a in self.blender_attributes]: - print_console('WARNING', 'Attribute (vertex color) collision name: ' + blender_attribute.name + ", ignoring one of them") - continue - - else: - # Custom attributes - # Keep only attributes that starts with _ - # As Blender create lots of attributes that are internal / not needed are as duplicated of standard glTF accessors (position, uv, material_index...) - if self.export_settings['gltf_attributes'] is False: - continue - # Check if there is an extension that want to keep this attribute, or change the exported name - keep_attribute = KeepAttribute(blender_attribute.name) + # Custom attributes + # Keep only attributes that starts with _ + # As Blender create lots of attributes that are internal / not needed are as duplicated of standard glTF accessors (position, uv, material_index...) + if self.export_settings['gltf_attributes'] is False: + continue + # Check if there is an extension that want to keep this attribute, or change the exported name + keep_attribute = KeepAttribute(blender_attribute.name) - export_user_extensions('gather_attribute_keep', self.export_settings, keep_attribute) + export_user_extensions('gather_attribute_keep', self.export_settings, keep_attribute) - if keep_attribute.keep is False: - continue + if keep_attribute.keep is False: + continue - attr['gltf_attribute_name'] = keep_attribute.attr_name.upper() - attr['get'] = self.get_function() + attr['gltf_attribute_name'] = keep_attribute.attr_name.upper() + attr['get'] = self.get_function() - # Seems we sometime can have name collision about attributes - # Avoid crash and ignoring one of duplicated attribute name - if attr['gltf_attribute_name'] in [a['gltf_attribute_name'] for a in self.blender_attributes]: - print_console('WARNING', 'Attribute collision name: ' + blender_attribute.name + ", ignoring one of them") - continue + # Seems we sometime can have name collision about attributes + # Avoid crash and ignoring one of duplicated attribute name + if attr['gltf_attribute_name'] in [a['gltf_attribute_name'] for a in self.blender_attributes]: + print_console('WARNING', 'Attribute collision name: ' + blender_attribute.name + ", ignoring one of them") + continue self.blender_attributes.append(attr) @@ -400,12 +385,19 @@ def primitive_split(self): for material_idx in unique_material_idxs: self.prim_indices[material_idx] = loop_indices[loop_material_idxs == material_idx] - def material_uvmap_attribute_add(self): + def manage_material_info(self): # If user defined UVMap as a custom attribute, we need to add it/them in the dots structure and populate data # So we need to get, for each material, what are these custom attribute # No choice : We need to retrieve materials here. Anyway, this will be baked, and next call will be quick + # We also need to shuffle Vertex Color data if needed + for material_idx in self.prim_indices.keys(): _, material_info = get_base_material(material_idx, self.materials, self.export_settings) + + # TODOVC if different materials use diffrent attribute, add warning + + # UVMaps + self.uvmap_attribute_list = list(set([i['value'] for i in material_info["uv_info"].values() if 'type' in i.keys() and i['type'] == "Attribute" ])) additional_fields = [] @@ -438,6 +430,26 @@ def material_uvmap_attribute_add(self): self.dots = dots + # Vertex Color + # There are multiple case to take into account + + # The simplier test is when no vertex color are used + if material_info['vc_info']['color'] is None and material_info['vc_info']['alpha'] is None: + # Nothing to do + return + + if material_info['vc_info']['color'] is None and material_info['vc_info']['alpha'] is not None: + print("TODOVC add warning, we are not going to manage this case") + return + + if material_info['vc_info']['color'] is not None: + # We need to check if we need to add alpha + add_alpha = material_info['vc_info']['alpha'] is not None + mat = get_material_from_idx(material_idx, self.materials, self.export_settings) + add_alpha = add_alpha and not (mat.blend_method is None or mat.blend_method == 'OPAQUE') + # Manage Vertex Color (RGB and Alpha if needed) + self.__manage_color_attribute(material_info['vc_info']['color'], material_info['vc_info']['alpha'] if add_alpha else None) + def primitive_creation(self): primitives = [] @@ -640,9 +652,7 @@ def __get_positions(self): def get_function(self): def getting_function(attr): - if attr['gltf_attribute_name'] == "COLOR_0": - self.__get_color_attribute(attr) - elif attr['gltf_attribute_name'].startswith("_"): + if attr['gltf_attribute_name'].startswith("_"): self.__get_layer_attribute(attr) elif attr['gltf_attribute_name'].startswith("TEXCOORD_"): self.__get_uvs_attribute(int(attr['gltf_attribute_name'].split("_")[-1]), attr) @@ -654,15 +664,77 @@ def getting_function(attr): return getting_function - def __get_color_attribute(self, attr): - blender_color_idx = self.blender_mesh.color_attributes.render_color_index + def __manage_color_attribute(self, attr_name, attr_name_alpha): + blender_color_idx = self.blender_mesh.color_attributes.find(attr_name) + if blender_color_idx < 0: + return None + + # Add COLOR_0 in dots data + + attr = self.blender_mesh.color_attributes[blender_color_idx] + + # Get data + data_dots, data_dots_edges, data_dots_points = self.__get_color_attribute_data(attr) + + # Get data for alpha if needed + if attr_name_alpha is not None and attr_name_alpha != attr_name: + blender_alpha_idx = self.blender_mesh.color_attributes.find(attr_name_alpha) + if blender_alpha_idx >= 0: + attr_alpha = self.blender_mesh.color_attributes[blender_alpha_idx] + data_dots_alpha, data_dots_edges_alpha, data_dots_points_alpha = self.__get_color_attribute_data(attr_alpha) + # Merging data + data_dots[:, 3] = data_dots_alpha[:, 3] + if data_dots_edges is not None: + data_dots_edges[:, 3] = data_dots_edges_alpha[:, 3] + if data_dots_points is not None: + data_dots_points[:, 3] = data_dots_points_alpha[:, 3] - if attr['blender_domain'] == "POINT": + # Check if we need to get alpha (the 4th channel) here + max_index = 4 if attr_name_alpha is not None else 3 + + # Add this data to dots structure + additional_fields = [] + for i in range(max_index): + # Must calculate the type of the field : FLOAT_COLOR or BYTE_COLOR + additional_fields.append(('COLOR_0' + str(i), gltf2_blender_conversion.get_numpy_type('FLOAT_COLOR' if max_index == 3 else 'BYTE_COLOR'))) + + new_dt = np.dtype(self.dots.dtype.descr + additional_fields) + dots = np.zeros(self.dots.shape, dtype=new_dt) + for f in self.dots.dtype.names: + dots[f] = self.dots[f] + + self.dots = dots + + # colors are already linear, no need to switch color space + for i in range(max_index): + self.dots['COLOR_0' +str(i)] = data_dots[:, i] + if self.export_settings['gltf_loose_edges'] and attr.domain == "POINT": + self.dots_edges['COLOR_0' + str(i)] = data_dots_edges[:, i] + if self.export_settings['gltf_loose_points'] and attr['blender_domain'] == "POINT": + self.dots_points['COLOR_0' + str(i)] = data_dots_points[:, i] + + # Add COLOR_0 in attribute list + attr_color_0 = {} + attr_color_0['blender_data_type'] = 'FLOAT_COLOR' if max_index == 3 else 'BYTE_COLOR' + attr_color_0['blender_domain'] = attr.domain + attr_color_0['gltf_attribute_name'] = 'COLOR_0' + attr_color_0['len'] = max_index # 3 or 4, depending if we have alpha + attr_color_0['type'] = gltf2_blender_conversion.get_numpy_type(attr_color_0['blender_data_type']) + attr_color_0['component_type'] = gltf2_blender_conversion.get_component_type(attr_color_0['blender_data_type']) + attr_color_0['data_type'] = gltf2_io_constants.DataType.Vec3 if max_index == 3 else gltf2_io_constants.DataType.Vec4 + + self.blender_attributes.append(attr_color_0) + + def __get_color_attribute_data(self, attr): + data_dots_edges = None + data_dots_points = None + + if attr.domain == "POINT": colors = np.empty(len(self.blender_mesh.vertices) * 4, dtype=np.float32) - elif attr['blender_domain'] == "CORNER": + elif attr.domain == "CORNER": colors = np.empty(len(self.blender_mesh.loops) * 4, dtype=np.float32) - self.blender_mesh.color_attributes[blender_color_idx].data.foreach_get('color', colors) - if attr['blender_domain'] == "POINT": + attr.data.foreach_get('color', colors) + if attr.domain == "POINT": colors = colors.reshape(-1, 4) data_dots = colors[self.dots['vertex_index']] if self.export_settings['gltf_loose_edges']: @@ -670,18 +742,13 @@ def __get_color_attribute(self, attr): if self.export_settings['gltf_loose_points']: data_dots_points = colors[self.dots_points['vertex_index']] - elif attr['blender_domain'] == "CORNER": + elif attr.domain == "CORNER": colors = colors.reshape(-1, 4) data_dots = colors del colors - # colors are already linear, no need to switch color space - for i in range(4): - self.dots[attr['gltf_attribute_name'] + str(i)] = data_dots[:, i] - if self.export_settings['gltf_loose_edges'] and attr['blender_domain'] == "POINT": - self.dots_edges[attr['gltf_attribute_name'] + str(i)] = data_dots_edges[:, i] - if self.export_settings['gltf_loose_points'] and attr['blender_domain'] == "POINT": - self.dots_points[attr['gltf_attribute_name'] + str(i)] = data_dots_points[:, i] + + return data_dots, data_dots_edges, data_dots_points def __get_layer_attribute(self, attr): if attr['blender_domain'] in ['CORNER']: @@ -982,15 +1049,19 @@ def __set_regular_attribute(self, attr): res[:, i] = self.prim_dots[attr['gltf_attribute_name'] + str(i)] self.attributes[attr['gltf_attribute_name']] = {} self.attributes[attr['gltf_attribute_name']]["data"] = res - if 'gltf_attribute_name' == "NORMAL": + if attr['gltf_attribute_name'] == "NORMAL": self.attributes[attr['gltf_attribute_name']]["component_type"] = gltf2_io_constants.ComponentType.Float self.attributes[attr['gltf_attribute_name']]["data_type"] = gltf2_io_constants.DataType.Vec3 - elif 'gltf_attribute_name' == "TANGENT": + elif attr['gltf_attribute_name'] == "TANGENT": self.attributes[attr['gltf_attribute_name']]["component_type"] = gltf2_io_constants.ComponentType.Float self.attributes[attr['gltf_attribute_name']]["data_type"] = gltf2_io_constants.DataType.Vec4 elif attr['gltf_attribute_name'].startswith('TEXCOORD_'): self.attributes[attr['gltf_attribute_name']]["component_type"] = gltf2_io_constants.ComponentType.Float self.attributes[attr['gltf_attribute_name']]["data_type"] = gltf2_io_constants.DataType.Vec2 + elif attr['gltf_attribute_name'].startswith('COLOR_'): + # This is already managed, we only have to copy + self.attributes[attr['gltf_attribute_name']]["component_type"] = attr['component_type'] + self.attributes[attr['gltf_attribute_name']]["data_type"] = attr['data_type'] else: self.attributes[attr['gltf_attribute_name']]["component_type"] = gltf2_blender_conversion.get_component_type(attr['blender_data_type']) self.attributes[attr['gltf_attribute_name']]["data_type"] = gltf2_blender_conversion.get_data_type(attr['blender_data_type']) diff --git a/addons/io_scene_gltf2/blender/exp/gltf2_blender_get.py b/addons/io_scene_gltf2/blender/exp/gltf2_blender_get.py index 14cc523a0..bfaf4a8d3 100644 --- a/addons/io_scene_gltf2/blender/exp/gltf2_blender_get.py +++ b/addons/io_scene_gltf2/blender/exp/gltf2_blender_get.py @@ -334,3 +334,43 @@ def has_image_node_from_socket(socket): def image_tex_is_valid_from_socket(socket): res = get_tex_from_socket(socket) return res is not None and res.shader_node.image is not None and res.shader_node.image.channels != 0 + +def get_vertex_color_info(color_socket, alpha_socket, export_settings): + + attribute_color = None + attribute_alpha = None + + # Retrieve Attribute used as vertex color for Color + if color_socket is not None: + node = previous_node(color_socket) + if node is not None: + if node.type == 'MIX' and node.data_type == "RGBA" and node.blend_type == 'MULTIPLY': + attribute_color = get_attribute_name(node.inputs[6], export_settings) + if attribute_color is None: + attribute_color = get_attribute_name(node.inputs[7], export_settings) + + if alpha_socket is not None: + node = previous_node(alpha_socket) + if node is not None: + if node.type == 'MIX' and node.data_type == "FLOAT" and node.blend_type == 'MULTIPLY': + attribute_alpha = get_attribute_name(node.inputs[2], export_settings) + if attribute_alpha is None: + attribute_alpha = get_attribute_name(node.inputs[3], export_settings) + + return {"color": attribute_color, "alpha": attribute_alpha} + + +def get_attribute_name(socket, export_settings): + node = previous_node(socket) + if node is not None and node.type == "ATTRIBUTE" \ + and node.attribute_type == "GEOMETRY" \ + and node.attribute_name is not None \ + and node.attribute_name != "": + return node.attribute_name + + if node is not None and node.type == "VERTEX_COLOR" \ + and node.layer_name is not None \ + and node.layer_name != "": + return node.layer_name + + return None diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py index c693bdf5d..79d4c43a1 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py @@ -53,7 +53,7 @@ def gather_material(blender_material, export_settings): :return: a glTF material """ if not __filter_material(blender_material, export_settings): - return None, {} + return None, {"uv_info": {}, "vc_info": {'color': None, 'alpha': None}} mat_unlit, uvmap_info, vc_info = __export_unlit(blender_material, export_settings) if mat_unlit is not None: @@ -313,6 +313,7 @@ def __export_unlit(blender_material, export_settings): if info is None: return None, {}, {"color": None, "alpha": None} + #TODOVC base_color_texture, uvmap_info, vc_info = gltf2_unlit.gather_base_color_texture(info, export_settings) material = gltf2_io.Material( @@ -459,7 +460,7 @@ def get_material_from_idx(material_idx, materials, export_settings): def get_base_material(material_idx, materials, export_settings): material = None - material_info = {"uv_info": {}, "vc_info": {}} + material_info = {"uv_info": {}, "vc_info": {"color": None, "alpha": None}} mat = get_material_from_idx(material_idx, materials, export_settings) if mat is not None: diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_pbr_metallic_roughness.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_pbr_metallic_roughness.py index bb8083d7f..d5be2951a 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_pbr_metallic_roughness.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_pbr_metallic_roughness.py @@ -18,24 +18,25 @@ from ....io.exp.gltf2_io_user_extensions import export_user_extensions from ...exp import gltf2_blender_get from ..gltf2_blender_gather_cache import cached -from ..gltf2_blender_get import image_tex_is_valid_from_socket -from .gltf2_blender_search_node_tree import get_vertex_color_info +from ..gltf2_blender_get import image_tex_is_valid_from_socket, get_vertex_color_info from .gltf2_blender_gather_texture_info import gather_texture_info @cached def gather_material_pbr_metallic_roughness(blender_material, orm_texture, export_settings): if not __filter_pbr_material(blender_material, export_settings): - return None, {} + return None, {}, {'color': None, 'alpha': None} uvmap_infos = {} - base_color_texture, uvmap_info, vc_info, _ = __gather_base_color_texture(blender_material, export_settings) + base_color_texture, uvmap_info, _ = __gather_base_color_texture(blender_material, export_settings) uvmap_infos.update(uvmap_info) metallic_roughness_texture, uvmap_info, _ = __gather_metallic_roughness_texture(blender_material, orm_texture, export_settings) uvmap_infos.update(uvmap_info) + base_color_factor, vc_info = __gather_base_color_factor(blender_material, export_settings) + material = gltf2_io.MaterialPBRMetallicRoughness( - base_color_factor=__gather_base_color_factor(blender_material, export_settings), + base_color_factor=base_color_factor, base_color_texture=base_color_texture, extensions=__gather_extensions(blender_material, export_settings), extras=__gather_extras(blender_material, export_settings), @@ -55,7 +56,7 @@ def __filter_pbr_material(blender_material, export_settings): def __gather_base_color_factor(blender_material, export_settings): if not blender_material.use_nodes: - return [*blender_material.diffuse_color[:3], 1.0] + return [*blender_material.diffuse_color[:3], 1.0], {"color": None, "alpha": None} rgb, alpha = None, None @@ -85,8 +86,10 @@ def __gather_base_color_factor(blender_material, export_settings): rgba = [*rgb, alpha] - if rgba == [1, 1, 1, 1]: return None - return rgba + vc_info = get_vertex_color_info(base_color_socket, alpha_socket, export_settings) + + if rgba == [1, 1, 1, 1]: return None, vc_info + return rgba, vc_info def __gather_base_color_texture(blender_material, export_settings): @@ -104,11 +107,10 @@ def __gather_base_color_texture(blender_material, export_settings): if socket is not None and image_tex_is_valid_from_socket(socket) ) if not inputs: - return None, {}, {"uv_info": {}, "vc_info": {}}, None + return None, {}, None tex, uvmap_info, factor = gather_texture_info(inputs[0], inputs, (), export_settings) - vc_info = get_vertex_color_info(inputs[0], inputs, export_settings) - return tex, {'baseColorTexture': uvmap_info}, vc_info, factor + return tex, {'baseColorTexture': uvmap_info}, factor def __gather_extensions(blender_material, export_settings): diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_unlit.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_unlit.py index 212de5569..f474ff04c 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_unlit.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_unlit.py @@ -15,7 +15,6 @@ from ....io.com.gltf2_io_extensions import Extension from ...exp import gltf2_blender_get from . import gltf2_blender_gather_texture_info -from .gltf2_blender_search_node_tree import get_vertex_color_info def detect_shadeless_material(blender_material, export_settings): """Detect if this material is "shadeless" ie. should be exported @@ -146,7 +145,7 @@ def gather_base_color_texture(info, export_settings): export_settings, ) - vc_info = get_vertex_color_info(sockets[0], sockets, export_settings) + vc_info = gltf2_blender_get.get_vertex_color_info(info.get('rgb_socket'), info.get('alpha_socket'), export_settings) return unlit_texture, {'baseColorTexture': uvmap_info}, vc_info return None, {}, {"color": None, "alpha": None} diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py index a70267d4c..3a59dcc1a 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py @@ -100,5 +100,4 @@ def __search_from_socket(start_socket: bpy.types.NodeSocket, return __search_from_socket(start_socket, shader_node_filter, []) -def get_vertex_color_info(primary_socket, sockets, export_settings): - return {"color": None, "alpha": None} #TODO, placeholder for now + From 6a5ba49d4cfe85323952983c172d8c68c30d437c Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Sat, 16 Sep 2023 17:24:39 +0200 Subject: [PATCH 02/11] add TODO --- .../blender/exp/gltf2_blender_gather_primitives_extract.py | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py index d6cea83e4..04d082a92 100644 --- a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py +++ b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py @@ -698,6 +698,7 @@ def __manage_color_attribute(self, attr_name, attr_name_alpha): # Must calculate the type of the field : FLOAT_COLOR or BYTE_COLOR additional_fields.append(('COLOR_0' + str(i), gltf2_blender_conversion.get_numpy_type('FLOAT_COLOR' if max_index == 3 else 'BYTE_COLOR'))) + #TODOVC : remove corresponding custum attribute if we export them ? new_dt = np.dtype(self.dots.dtype.descr + additional_fields) dots = np.zeros(self.dots.shape, dtype=new_dt) for f in self.dots.dtype.names: From 14e92ee8e37b7cb7fd1d3e307cc3545d98b453a4 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Sat, 16 Sep 2023 17:32:12 +0200 Subject: [PATCH 03/11] Fix unlit --- .../blender/exp/material/gltf2_blender_gather_materials.py | 5 +++-- .../exp/material/gltf2_blender_gather_materials_unlit.py | 6 ++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py index 79d4c43a1..05c961d54 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py @@ -313,8 +313,9 @@ def __export_unlit(blender_material, export_settings): if info is None: return None, {}, {"color": None, "alpha": None} - #TODOVC - base_color_texture, uvmap_info, vc_info = gltf2_unlit.gather_base_color_texture(info, export_settings) + base_color_texture, uvmap_info = gltf2_unlit.gather_base_color_texture(info, export_settings) + + vc_info = gltf2_blender_get.get_vertex_color_info(info.get('rgb_socket'), info.get('alpha_socket'), export_settings) material = gltf2_io.Material( alpha_cutoff=__gather_alpha_cutoff(blender_material, export_settings), diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_unlit.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_unlit.py index f474ff04c..ff027f7ba 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_unlit.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_unlit.py @@ -145,7 +145,5 @@ def gather_base_color_texture(info, export_settings): export_settings, ) - vc_info = gltf2_blender_get.get_vertex_color_info(info.get('rgb_socket'), info.get('alpha_socket'), export_settings) - - return unlit_texture, {'baseColorTexture': uvmap_info}, vc_info - return None, {}, {"color": None, "alpha": None} + return unlit_texture, {'baseColorTexture': uvmap_info} + return None, {} From d1f26c32697576096ad302de9d8b9631b02f9077 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Mon, 25 Sep 2023 15:20:49 +0200 Subject: [PATCH 04/11] Add warning for not manage case --- .../blender/exp/gltf2_blender_gather_primitives_extract.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py index 04d082a92..d054916df 100644 --- a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py +++ b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py @@ -439,7 +439,7 @@ def manage_material_info(self): return if material_info['vc_info']['color'] is None and material_info['vc_info']['alpha'] is not None: - print("TODOVC add warning, we are not going to manage this case") + print_console('WARNING', 'We are not managing this case (Vertex Color alpha without color)') return if material_info['vc_info']['color'] is not None: From 3943f127565a1cd71b382ec2f63ab05b7038be82 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Mon, 25 Sep 2023 16:33:02 +0200 Subject: [PATCH 05/11] Add warning, fix corner cases --- ...gltf2_blender_gather_primitives_extract.py | 58 ++++++++++++++----- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py index d054916df..04567580d 100644 --- a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py +++ b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py @@ -391,13 +391,14 @@ def manage_material_info(self): # No choice : We need to retrieve materials here. Anyway, this will be baked, and next call will be quick # We also need to shuffle Vertex Color data if needed + materials_use_vc = None + warning_already_displayed = False for material_idx in self.prim_indices.keys(): _, material_info = get_base_material(material_idx, self.materials, self.export_settings) - # TODOVC if different materials use diffrent attribute, add warning + print("!!!!!!!!!!!!!!!!!!!!!!!!!") # UVMaps - self.uvmap_attribute_list = list(set([i['value'] for i in material_info["uv_info"].values() if 'type' in i.keys() and i['type'] == "Attribute" ])) additional_fields = [] @@ -406,10 +407,11 @@ def manage_material_info(self): additional_fields.append((attr + str(0), gltf2_blender_conversion.get_numpy_type('FLOAT2'))) additional_fields.append((attr + str(1), gltf2_blender_conversion.get_numpy_type('FLOAT2'))) - new_dt = np.dtype(self.dots.dtype.descr + additional_fields) - dots = np.zeros(self.dots.shape, dtype=new_dt) - for f in self.dots.dtype.names: - dots[f] = self.dots[f] + if len(additional_fields) > 0: + new_dt = np.dtype(self.dots.dtype.descr + additional_fields) + dots = np.zeros(self.dots.shape, dtype=new_dt) + for f in self.dots.dtype.names: + dots[f] = self.dots[f] # Now we need to get data and populate for attr in self.uvmap_attribute_list: @@ -428,27 +430,51 @@ def manage_material_info(self): dots[attr + '1'] = data[:, 1] del data - self.dots = dots + if len(additional_fields) > 0: + self.dots = dots - # Vertex Color # There are multiple case to take into account # The simplier test is when no vertex color are used if material_info['vc_info']['color'] is None and material_info['vc_info']['alpha'] is None: # Nothing to do - return + continue if material_info['vc_info']['color'] is None and material_info['vc_info']['alpha'] is not None: print_console('WARNING', 'We are not managing this case (Vertex Color alpha without color)') - return + continue + if material_info['vc_info']['color'] is not None: - # We need to check if we need to add alpha - add_alpha = material_info['vc_info']['alpha'] is not None - mat = get_material_from_idx(material_idx, self.materials, self.export_settings) - add_alpha = add_alpha and not (mat.blend_method is None or mat.blend_method == 'OPAQUE') - # Manage Vertex Color (RGB and Alpha if needed) - self.__manage_color_attribute(material_info['vc_info']['color'], material_info['vc_info']['alpha'] if add_alpha else None) + + print(">1") + + vc_key = "" + vc_key += material_info['vc_info']['color'] if material_info['vc_info']['color'] is not None else "" + vc_key += material_info['vc_info']['alpha'] if material_info['vc_info']['alpha'] is not None else "" + + print(">2", vc_key, materials_use_vc) + + if materials_use_vc is not None and materials_use_vc != vc_key: + print(">3") + if warning_already_displayed is False: + print(">4") + print_console('WARNING', 'glTF specification does not allow this case (multiple materials with different Vertex Color)') + warning_already_displayed = True + materials_use_vc = vc_key + continue + elif materials_use_vc is None: + print(">5") + materials_use_vc = vc_key + + # We need to check if we need to add alpha + add_alpha = material_info['vc_info']['alpha'] is not None + mat = get_material_from_idx(material_idx, self.materials, self.export_settings) + add_alpha = add_alpha and not (mat.blend_method is None or mat.blend_method == 'OPAQUE') + # Manage Vertex Color (RGB and Alpha if needed) + self.__manage_color_attribute(material_info['vc_info']['color'], material_info['vc_info']['alpha'] if add_alpha else None) + else: + pass # Using the same Vertex Color def primitive_creation(self): primitives = [] From 58e47b11ae0059f063551c59296c366a8deccd34 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Mon, 25 Sep 2023 16:33:40 +0200 Subject: [PATCH 06/11] remove debug prints --- .../exp/gltf2_blender_gather_primitives_extract.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py index 04567580d..96443ec89 100644 --- a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py +++ b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py @@ -396,8 +396,6 @@ def manage_material_info(self): for material_idx in self.prim_indices.keys(): _, material_info = get_base_material(material_idx, self.materials, self.export_settings) - print("!!!!!!!!!!!!!!!!!!!!!!!!!") - # UVMaps self.uvmap_attribute_list = list(set([i['value'] for i in material_info["uv_info"].values() if 'type' in i.keys() and i['type'] == "Attribute" ])) @@ -447,24 +445,17 @@ def manage_material_info(self): if material_info['vc_info']['color'] is not None: - print(">1") - vc_key = "" vc_key += material_info['vc_info']['color'] if material_info['vc_info']['color'] is not None else "" vc_key += material_info['vc_info']['alpha'] if material_info['vc_info']['alpha'] is not None else "" - print(">2", vc_key, materials_use_vc) - if materials_use_vc is not None and materials_use_vc != vc_key: - print(">3") if warning_already_displayed is False: - print(">4") print_console('WARNING', 'glTF specification does not allow this case (multiple materials with different Vertex Color)') warning_already_displayed = True materials_use_vc = vc_key continue elif materials_use_vc is None: - print(">5") materials_use_vc = vc_key # We need to check if we need to add alpha From d2d64aa717a85805e2c85cc76000aad0a6edcd42 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Sat, 30 Sep 2023 12:00:15 +0200 Subject: [PATCH 07/11] Update comment --- .../blender/exp/gltf2_blender_gather_primitives_extract.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py index 96443ec89..f0db6f3e4 100644 --- a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py +++ b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py @@ -715,7 +715,8 @@ def __manage_color_attribute(self, attr_name, attr_name_alpha): # Must calculate the type of the field : FLOAT_COLOR or BYTE_COLOR additional_fields.append(('COLOR_0' + str(i), gltf2_blender_conversion.get_numpy_type('FLOAT_COLOR' if max_index == 3 else 'BYTE_COLOR'))) - #TODOVC : remove corresponding custum attribute if we export them ? + # Keep the existing custom attribute + # Data will be exported twice, one for COLOR_O, one for the custom attribute new_dt = np.dtype(self.dots.dtype.descr + additional_fields) dots = np.zeros(self.dots.shape, dtype=new_dt) for f in self.dots.dtype.names: From 5b347755a3350d24a90943002ca92fa03ac0f233 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Mon, 9 Oct 2023 17:15:24 +0200 Subject: [PATCH 08/11] Fix after merge --- .../gltf2_blender_search_node_tree.py | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py index 9b4acface..aa0919d82 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py @@ -453,35 +453,35 @@ def get_vertex_color_info(color_socket, alpha_socket, export_settings): attribute_alpha = None # Retrieve Attribute used as vertex color for Color - if color_socket is not None: + if color_socket.socket is not None: node = previous_node(color_socket) - if node is not None: - if node.type == 'MIX' and node.data_type == "RGBA" and node.blend_type == 'MULTIPLY': - attribute_color = get_attribute_name(node.inputs[6], export_settings) + if node.node is not None: + if node.node.type == 'MIX' and node.node.data_type == "RGBA" and node.node.blend_type == 'MULTIPLY': + attribute_color = get_attribute_name(node.node.inputs[6], export_settings) if attribute_color is None: - attribute_color = get_attribute_name(node.inputs[7], export_settings) + attribute_color = get_attribute_name(node.node.inputs[7], export_settings) - if alpha_socket is not None: + if alpha_socket.socket is not None: node = previous_node(alpha_socket) - if node is not None: - if node.type == 'MIX' and node.data_type == "FLOAT" and node.blend_type == 'MULTIPLY': - attribute_alpha = get_attribute_name(node.inputs[2], export_settings) + if node.node is not None: + if node.node.type == 'MIX' and node.node.data_type == "FLOAT" and node.node.blend_type == 'MULTIPLY': + attribute_alpha = get_attribute_name(node.node.inputs[2], export_settings) if attribute_alpha is None: - attribute_alpha = get_attribute_name(node.inputs[3], export_settings) + attribute_alpha = get_attribute_name(node.node.inputs[3], export_settings) return {"color": attribute_color, "alpha": attribute_alpha} def get_attribute_name(socket, export_settings): node = previous_node(socket) - if node is not None and node.type == "ATTRIBUTE" \ - and node.attribute_type == "GEOMETRY" \ - and node.attribute_name is not None \ - and node.attribute_name != "": - return node.attribute_name - - if node is not None and node.type == "VERTEX_COLOR" \ - and node.layer_name is not None \ - and node.layer_name != "": - return node.layer_name + if node.node is not None and node.node.type == "ATTRIBUTE" \ + and node.node.attribute_type == "GEOMETRY" \ + and node.node.attribute_name is not None \ + and node.node.attribute_name != "": + return node.node.attribute_name + + if node.node is not None and node.node.type == "VERTEX_COLOR" \ + and node.node.layer_name is not None \ + and node.node.layer_name != "": + return node.node.layer_name return None From 11dcdf3986f599db7b6c463453c206e7e939f78a Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Mon, 9 Oct 2023 17:28:21 +0200 Subject: [PATCH 09/11] More fix after merge --- .../exp/material/gltf2_blender_gather_materials.py | 5 +++-- .../exp/material/gltf2_blender_search_node_tree.py | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py index c7ca6740c..d4fb3bb52 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py @@ -36,7 +36,8 @@ has_image_node_from_socket, \ get_socket_from_gltf_material_node, \ get_socket, \ - get_node_socket + get_node_socket, \ + get_vertex_color_info @cached def get_material_cache_key(blender_material, export_settings): @@ -313,7 +314,7 @@ def __export_unlit(blender_material, export_settings): base_color_texture, uvmap_info = gltf2_unlit.gather_base_color_texture(info, export_settings) - vc_info = gltf2_blender_get.get_vertex_color_info(info.get('rgb_socket'), info.get('alpha_socket'), export_settings) + vc_info = get_vertex_color_info(info.get('rgb_socket'), info.get('alpha_socket'), export_settings) material = gltf2_io.Material( alpha_cutoff=__gather_alpha_cutoff(blender_material, export_settings), diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py index aa0919d82..449ce9b3e 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py @@ -453,21 +453,21 @@ def get_vertex_color_info(color_socket, alpha_socket, export_settings): attribute_alpha = None # Retrieve Attribute used as vertex color for Color - if color_socket.socket is not None: + if color_socket is not None and color_socket.socket is not None: node = previous_node(color_socket) if node.node is not None: if node.node.type == 'MIX' and node.node.data_type == "RGBA" and node.node.blend_type == 'MULTIPLY': - attribute_color = get_attribute_name(node.node.inputs[6], export_settings) + attribute_color = get_attribute_name(NodeSocket(node.node.inputs[6], node.group_path), export_settings) if attribute_color is None: - attribute_color = get_attribute_name(node.node.inputs[7], export_settings) + attribute_color = get_attribute_name(NodeSocket(node.node.inputs[7], node.group_path), export_settings) - if alpha_socket.socket is not None: + if alpha_socket is not None and alpha_socket.socket is not None: node = previous_node(alpha_socket) if node.node is not None: if node.node.type == 'MIX' and node.node.data_type == "FLOAT" and node.node.blend_type == 'MULTIPLY': - attribute_alpha = get_attribute_name(node.node.inputs[2], export_settings) + attribute_alpha = get_attribute_name(NodeSocket(node.node.inputs[2], node.group_path), export_settings) if attribute_alpha is None: - attribute_alpha = get_attribute_name(node.node.inputs[3], export_settings) + attribute_alpha = get_attribute_name(NodeSocket(node.node.inputs[3], node.group_path), export_settings) return {"color": attribute_color, "alpha": attribute_alpha} From 4954fb3a26effd047c8c6cb89fa414109aa18a7d Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Wed, 18 Oct 2023 12:07:50 +0200 Subject: [PATCH 10/11] Manage active Vertex Color layer --- ...gltf2_blender_gather_primitives_extract.py | 29 ++++++++++++++----- .../gltf2_blender_search_node_tree.py | 6 +++- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py index f0db6f3e4..523f1b412 100644 --- a/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py +++ b/addons/io_scene_gltf2/blender/exp/gltf2_blender_gather_primitives_extract.py @@ -431,23 +431,36 @@ def manage_material_info(self): if len(additional_fields) > 0: self.dots = dots - # There are multiple case to take into account + # There are multiple case to take into account for VC # The simplier test is when no vertex color are used - if material_info['vc_info']['color'] is None and material_info['vc_info']['alpha'] is None: + if material_info['vc_info']['color_type'] is None and material_info['vc_info']['alpha_type'] is None: # Nothing to do continue - if material_info['vc_info']['color'] is None and material_info['vc_info']['alpha'] is not None: + if material_info['vc_info']['color_type'] is None and material_info['vc_info']['alpha_type'] is not None: print_console('WARNING', 'We are not managing this case (Vertex Color alpha without color)') continue + vc_color_name = None + vc_alpha_name = None + if material_info['vc_info']['color_type'] == "name": + vc_color_name = material_info['vc_info']['color'] + elif material_info['vc_info']['color_type'] == "active": + # Get active (render) Vertex Color + vc_color_name = self.blender_mesh.color_attributes[self.blender_mesh.color_attributes.render_color_index].name - if material_info['vc_info']['color'] is not None: + if material_info['vc_info']['alpha_type'] == "name": + vc_alpha_name = material_info['vc_info']['alpha'] + elif material_info['vc_info']['alpha_type'] == "active": + # Get active (render) Vertex Color + vc_alpha_name = self.blender_mesh.color_attributes[self.blender_mesh.color_attributes.render_color_index].name + + if vc_color_name is not None: vc_key = "" - vc_key += material_info['vc_info']['color'] if material_info['vc_info']['color'] is not None else "" - vc_key += material_info['vc_info']['alpha'] if material_info['vc_info']['alpha'] is not None else "" + vc_key += vc_color_name if vc_color_name is not None else "" + vc_key += vc_alpha_name if vc_alpha_name is not None else "" if materials_use_vc is not None and materials_use_vc != vc_key: if warning_already_displayed is False: @@ -459,11 +472,11 @@ def manage_material_info(self): materials_use_vc = vc_key # We need to check if we need to add alpha - add_alpha = material_info['vc_info']['alpha'] is not None + add_alpha = vc_alpha_name is not None mat = get_material_from_idx(material_idx, self.materials, self.export_settings) add_alpha = add_alpha and not (mat.blend_method is None or mat.blend_method == 'OPAQUE') # Manage Vertex Color (RGB and Alpha if needed) - self.__manage_color_attribute(material_info['vc_info']['color'], material_info['vc_info']['alpha'] if add_alpha else None) + self.__manage_color_attribute(vc_color_name, vc_alpha_name if add_alpha else None) else: pass # Using the same Vertex Color diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py index 449ce9b3e..e5f8830da 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py @@ -451,6 +451,8 @@ def get_vertex_color_info(color_socket, alpha_socket, export_settings): attribute_color = None attribute_alpha = None + attribute_color_type = None + attribute_alpha_type = None # Retrieve Attribute used as vertex color for Color if color_socket is not None and color_socket.socket is not None: @@ -460,6 +462,7 @@ def get_vertex_color_info(color_socket, alpha_socket, export_settings): attribute_color = get_attribute_name(NodeSocket(node.node.inputs[6], node.group_path), export_settings) if attribute_color is None: attribute_color = get_attribute_name(NodeSocket(node.node.inputs[7], node.group_path), export_settings) + attribute_color_type = "name" if attribute_color is not None else "active" if alpha_socket is not None and alpha_socket.socket is not None: node = previous_node(alpha_socket) @@ -468,8 +471,9 @@ def get_vertex_color_info(color_socket, alpha_socket, export_settings): attribute_alpha = get_attribute_name(NodeSocket(node.node.inputs[2], node.group_path), export_settings) if attribute_alpha is None: attribute_alpha = get_attribute_name(NodeSocket(node.node.inputs[3], node.group_path), export_settings) + attribute_alpha_type = "name" if attribute_alpha is not None else "active" - return {"color": attribute_color, "alpha": attribute_alpha} + return {"color": attribute_color, "alpha": attribute_alpha, "color_type": attribute_color_type, "alpha_type": attribute_alpha_type} def get_attribute_name(socket, export_settings): node = previous_node(socket) From 7b44bf560a22fa7bb9d513395f3a075ac3eeac28 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Wed, 18 Oct 2023 15:49:57 +0200 Subject: [PATCH 11/11] Fix non regression --- .../gltf2_blender_gather_materials.py | 6 ++-- ...gather_materials_pbr_metallic_roughness.py | 4 +-- .../gltf2_blender_search_node_tree.py | 35 +++++++++++++------ 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py index d4fb3bb52..77148f5da 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials.py @@ -58,7 +58,7 @@ def gather_material(blender_material, export_settings): :return: a glTF material """ if not __filter_material(blender_material, export_settings): - return None, {"uv_info": {}, "vc_info": {'color': None, 'alpha': None}} + return None, {"uv_info": {}, "vc_info": {'color': None, 'alpha': None, 'color_type': None, 'alpha_type': None}} mat_unlit, uvmap_info, vc_info = __export_unlit(blender_material, export_settings) if mat_unlit is not None: @@ -310,7 +310,7 @@ def __export_unlit(blender_material, export_settings): info = gltf2_unlit.detect_shadeless_material(blender_material, export_settings) if info is None: - return None, {}, {"color": None, "alpha": None} + return None, {}, {"color": None, "alpha": None, "color_type": None, "alpha_type": None} base_color_texture, uvmap_info = gltf2_unlit.gather_base_color_texture(info, export_settings) @@ -460,7 +460,7 @@ def get_material_from_idx(material_idx, materials, export_settings): def get_base_material(material_idx, materials, export_settings): material = None - material_info = {"uv_info": {}, "vc_info": {"color": None, "alpha": None}} + material_info = {"uv_info": {}, "vc_info": {"color": None, "alpha": None, "color_type": None, "alpha_type": None}} mat = get_material_from_idx(material_idx, materials, export_settings) if mat is not None: diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_pbr_metallic_roughness.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_pbr_metallic_roughness.py index ba8381704..df47a33fc 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_pbr_metallic_roughness.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_gather_materials_pbr_metallic_roughness.py @@ -30,7 +30,7 @@ @cached def gather_material_pbr_metallic_roughness(blender_material, orm_texture, export_settings): if not __filter_pbr_material(blender_material, export_settings): - return None, {}, {'color': None, 'alpha': None} + return None, {}, {'color': None, 'alpha': None, 'color_type': None, 'alpha_type': None} uvmap_infos = {} @@ -62,7 +62,7 @@ def __filter_pbr_material(blender_material, export_settings): def __gather_base_color_factor(blender_material, export_settings): if not blender_material.use_nodes: - return [*blender_material.diffuse_color[:3], 1.0], {"color": None, "alpha": None} + return [*blender_material.diffuse_color[:3], 1.0], {"color": None, "alpha": None, "color_type": None, "alpha_type": None} rgb, alpha = None, None diff --git a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py index e5f8830da..fd6ee5069 100644 --- a/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py +++ b/addons/io_scene_gltf2/blender/exp/material/gltf2_blender_search_node_tree.py @@ -459,19 +459,25 @@ def get_vertex_color_info(color_socket, alpha_socket, export_settings): node = previous_node(color_socket) if node.node is not None: if node.node.type == 'MIX' and node.node.data_type == "RGBA" and node.node.blend_type == 'MULTIPLY': - attribute_color = get_attribute_name(NodeSocket(node.node.inputs[6], node.group_path), export_settings) - if attribute_color is None: - attribute_color = get_attribute_name(NodeSocket(node.node.inputs[7], node.group_path), export_settings) - attribute_color_type = "name" if attribute_color is not None else "active" + use_vc, attribute_color, use_active = get_attribute_name(NodeSocket(node.node.inputs[6], node.group_path), export_settings) + if use_vc is False: + use_vc, attribute_color, use_active = get_attribute_name(NodeSocket(node.node.inputs[7], node.group_path), export_settings) + if use_vc is True and use_active is True: + attribute_color_type = "active" + elif use_vc is True and use_active is None and attribute_color is not None: + attribute_color_type = "name" if alpha_socket is not None and alpha_socket.socket is not None: node = previous_node(alpha_socket) if node.node is not None: if node.node.type == 'MIX' and node.node.data_type == "FLOAT" and node.node.blend_type == 'MULTIPLY': - attribute_alpha = get_attribute_name(NodeSocket(node.node.inputs[2], node.group_path), export_settings) - if attribute_alpha is None: - attribute_alpha = get_attribute_name(NodeSocket(node.node.inputs[3], node.group_path), export_settings) - attribute_alpha_type = "name" if attribute_alpha is not None else "active" + use_vc, attribute_alpha, use_active = get_attribute_name(NodeSocket(node.node.inputs[2], node.group_path), export_settings) + if use_vc is False: + use_vc, attribute_alpha, use_active = get_attribute_name(NodeSocket(node.node.inputs[3], node.group_path), export_settings) + if use_vc is True and use_active is True: + attribute_alpha_type = "active" + elif use_vc is True and use_active is None and attribute_alpha is not None: + attribute_alpha_type = "name" return {"color": attribute_color, "alpha": attribute_alpha, "color_type": attribute_color_type, "alpha_type": attribute_alpha_type} @@ -481,11 +487,18 @@ def get_attribute_name(socket, export_settings): and node.node.attribute_type == "GEOMETRY" \ and node.node.attribute_name is not None \ and node.node.attribute_name != "": - return node.node.attribute_name + return True, node.node.attribute_name, None + elif node.node is not None and node.node.type == "ATTRIBUTE" \ + and node.node.attribute_type == "GEOMETRY" \ + and node.node.attribute_name == "": + return True, None, True if node.node is not None and node.node.type == "VERTEX_COLOR" \ and node.node.layer_name is not None \ and node.node.layer_name != "": - return node.node.layer_name + return True, node.node.layer_name, None + elif node.node is not None and node.node.type == "VERTEX_COLOR" \ + and node.node.layer_name == "": + return True, None, True - return None + return False, None, None