glTF exporter: fix PBR values when emission node is used

This commit is contained in:
Julien Duroure 2022-03-02 22:12:31 +01:00
parent 782f8585f4
commit fbb5111e15
4 changed files with 38 additions and 13 deletions

View File

@ -4,7 +4,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": (3, 2, 8),
"version": (3, 2, 9),
'blender': (3, 1, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',

View File

@ -55,6 +55,12 @@ def gather_material(blender_material, export_settings):
pbr_metallic_roughness=__gather_pbr_metallic_roughness(blender_material, orm_texture, export_settings)
)
# If emissive is set, from an emissive node (not PBR)
# We need to set manually default values for
# pbr_metallic_roughness.baseColor
if material.emissive_factor is not None and gltf2_blender_get.get_node_socket(blender_material, bpy.types.ShaderNodeBsdfPrincipled, "Base Color") is None:
material.pbr_metallic_roughness = gltf2_blender_gather_materials_pbr_metallic_roughness.get_default_pbr_for_emissive_node()
export_user_extensions('gather_material_hook', export_settings, material, blender_material)
return material

View File

@ -153,3 +153,14 @@ def __has_image_node_from_socket(socket):
if not result:
return False
return True
def get_default_pbr_for_emissive_node():
return gltf2_io.MaterialPBRMetallicRoughness(
base_color_factor=[0.0,0.0,0.0,1.0],
base_color_texture=None,
extensions=None,
extras=None,
metallic_factor=None,
metallic_roughness_texture=None,
roughness_factor=None
)

View File

@ -32,6 +32,21 @@ def get_object_from_datapath(blender_object, data_path: str):
return prop
def get_node_socket(blender_material, type, name):
"""
For a given material input name, retrieve the corresponding node tree socket for a given node type.
:param blender_material: a blender material for which to get the socket
:return: a blender NodeSocket for a given type
"""
nodes = [n for n in blender_material.node_tree.nodes if isinstance(n, type) and not n.mute]
nodes = [node for node in nodes if check_if_is_linked_to_active_output(node.outputs[0])]
inputs = sum([[input for input in node.inputs if input.name == name] for node in nodes], [])
if inputs:
return inputs[0]
return None
def get_socket(blender_material: bpy.types.Material, name: str):
"""
For a given material input name, retrieve the corresponding node tree socket.
@ -46,13 +61,9 @@ def get_socket(blender_material: bpy.types.Material, name: str):
if name == "Emissive":
# Check for a dedicated Emission node first, it must supersede the newer built-in one
# because the newer one is always present in all Principled BSDF materials.
type = bpy.types.ShaderNodeEmission
name = "Color"
nodes = [n for n in blender_material.node_tree.nodes if isinstance(n, type) and not n.mute]
nodes = [node for node in nodes if check_if_is_linked_to_active_output(node.outputs[0])]
inputs = sum([[input for input in node.inputs if input.name == name] for node in nodes], [])
if inputs:
return inputs[0]
emissive_socket = get_node_socket(blender_material, bpy.types.ShaderNodeEmission, "Color")
if emissive_socket:
return emissive_socket
# If a dedicated Emission node was not found, fall back to the Principled BSDF Emission socket.
name = "Emission"
type = bpy.types.ShaderNodeBsdfPrincipled
@ -61,11 +72,8 @@ def get_socket(blender_material: bpy.types.Material, name: str):
name = "Color"
else:
type = bpy.types.ShaderNodeBsdfPrincipled
nodes = [n for n in blender_material.node_tree.nodes if isinstance(n, type) and not n.mute]
nodes = [node for node in nodes if check_if_is_linked_to_active_output(node.outputs[0])]
inputs = sum([[input for input in node.inputs if input.name == name] for node in nodes], [])
if inputs:
return inputs[0]
return get_node_socket(blender_material, type, name)
return None