1 # SPDX-FileCopyrightText: 2018-2022 The glTF-Blender-IO authors
3 # SPDX-License-Identifier: Apache-2.0
5 from ....io
.com
.gltf2_io_extensions
import Extension
6 from ...exp
import gltf2_blender_get
7 from . import gltf2_blender_gather_texture_info
9 def detect_shadeless_material(blender_material
, export_settings
):
10 """Detect if this material is "shadeless" ie. should be exported
11 with KHR_materials_unlit. Returns None if not. Otherwise, returns
12 a dict with info from parsing the node tree.
14 if not blender_material
.use_nodes
: return None
16 # Old Background node detection (unlikely to happen)
17 bg_socket
= gltf2_blender_get
.get_socket(blender_material
, "Background")
18 if bg_socket
is not None:
19 return {'rgb_socket': bg_socket
}
22 # * any color socket, connected to...
23 # * optionally, the lightpath trick, connected to...
24 # * optionally, a mix-with-transparent (for alpha), connected to...
29 for node
in blender_material
.node_tree
.nodes
:
30 if node
.type == 'OUTPUT_MATERIAL' and node
.is_active_output
:
31 socket
= node
.inputs
[0]
36 # Be careful not to misidentify a lightpath trick as mix-alpha.
37 result
= __detect_lightpath_trick(socket
)
38 if result
is not None:
39 socket
= result
['next_socket']
41 result
= __detect_mix_alpha(socket
)
42 if result
is not None:
43 socket
= result
['next_socket']
44 info
['alpha_socket'] = result
['alpha_socket']
46 result
= __detect_lightpath_trick(socket
)
47 if result
is not None:
48 socket
= result
['next_socket']
50 # Check if a color socket, or connected to a color socket
51 if socket
.type != 'RGBA':
52 from_socket
= gltf2_blender_get
.previous_socket(socket
)
53 if from_socket
is None: return None
54 if from_socket
.type != 'RGBA': return None
56 info
['rgb_socket'] = socket
60 def __detect_mix_alpha(socket
):
61 # Detects this (used for an alpha hookup)
64 # alpha_socket => [Factor ] => socket
65 # [Transparent] => [Shader ]
66 # next_socket => [Shader ]
68 # Returns None if not detected. Otherwise, a dict containing alpha_socket
70 prev
= gltf2_blender_get
.previous_node(socket
)
71 if prev
is None or prev
.type != 'MIX_SHADER': return None
72 in1
= gltf2_blender_get
.previous_node(prev
.inputs
[1])
73 if in1
is None or in1
.type != 'BSDF_TRANSPARENT': return None
75 'alpha_socket': prev
.inputs
[0],
76 'next_socket': prev
.inputs
[2],
80 def __detect_lightpath_trick(socket
):
81 # Detects this (used to prevent casting light on other objects) See ex.
82 # https://blender.stackexchange.com/a/21535/88681
84 # [ Lightpath ] [ Mix ]
85 # [ Is Camera Ray] => [Factor ] => socket
86 # (don't care) => [Shader ]
87 # next_socket => [ Emission ] => [Shader ]
89 # The Emission node can be omitted.
90 # Returns None if not detected. Otherwise, a dict containing
92 prev
= gltf2_blender_get
.previous_node(socket
)
93 if prev
is None or prev
.type != 'MIX_SHADER': return None
94 in0
= gltf2_blender_get
.previous_socket(prev
.inputs
[0])
95 if in0
is None or in0
.node
.type != 'LIGHT_PATH': return None
96 if in0
.name
!= 'Is Camera Ray': return None
97 next_socket
= prev
.inputs
[2]
100 prev
= gltf2_blender_get
.previous_node(next_socket
)
101 if prev
is not None and prev
.type == 'EMISSION':
102 next_socket
= prev
.inputs
[0]
104 return {'next_socket': next_socket
}
107 def gather_base_color_factor(info
, export_settings
):
108 rgb
, alpha
= None, None
110 if 'rgb_socket' in info
:
111 rgb
= gltf2_blender_get
.get_factor_from_socket(info
['rgb_socket'], kind
='RGB')
112 if 'alpha_socket' in info
:
113 alpha
= gltf2_blender_get
.get_factor_from_socket(info
['alpha_socket'], kind
='VALUE')
115 if rgb
is None: rgb
= [1.0, 1.0, 1.0]
116 if alpha
is None: alpha
= 1.0
119 if rgba
== [1, 1, 1, 1]: return None
123 def gather_base_color_texture(info
, export_settings
):
124 sockets
= (info
.get('rgb_socket'), info
.get('alpha_socket'))
125 sockets
= tuple(s
for s
in sockets
if s
is not None)
127 # NOTE: separate RGB and Alpha textures will not get combined
128 # because gather_image determines how to pack images based on the
129 # names of sockets, and the names are hard-coded to a Principled
131 unlit_texture
, unlit_use_active_uvmap
, _
= gltf2_blender_gather_texture_info
.gather_texture_info(
137 return unlit_texture
, ["unlitTexture"] if unlit_use_active_uvmap
else None