diff options
Diffstat (limited to 'io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py')
-rwxr-xr-x | io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py | 218 |
1 files changed, 201 insertions, 17 deletions
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py b/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py index 4c32c35d..b6b8e19f 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py @@ -1,13 +1,19 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2018-2021 The glTF-Blender-IO authors. +from re import M import bpy from ...io.com.gltf2_io import TextureInfo, MaterialPBRMetallicRoughness from ..com.gltf2_blender_material_helpers import get_gltf_node_name, create_settings_group from .gltf2_blender_texture import texture from .gltf2_blender_KHR_materials_clearcoat import \ clearcoat, clearcoat_roughness, clearcoat_normal - +from .gltf2_blender_KHR_materials_transmission import transmission +from .gltf2_blender_KHR_materials_ior import ior +from .gltf2_blender_KHR_materials_volume import volume +from .gltf2_blender_KHR_materials_specular import specular +from .gltf2_blender_KHR_materials_sheen import sheen +from ...io.com.gltf2_io_constants import GLTF_IOR class MaterialHelper: """Helper class. Stores material stuff to be passed around everywhere.""" @@ -20,6 +26,7 @@ class MaterialHelper: if pymat.pbr_metallic_roughness is None: pymat.pbr_metallic_roughness = \ MaterialPBRMetallicRoughness.from_dict({}) + self.settings_node = None def is_opaque(self): alpha_mode = self.pymat.alpha_mode @@ -36,15 +43,52 @@ def pbr_metallic_roughness(mh: MaterialHelper): """Creates node tree for pbrMetallicRoughness materials.""" pbr_node = mh.node_tree.nodes.new('ShaderNodeBsdfPrincipled') pbr_node.location = 10, 300 - - make_output_nodes( + additional_location = 40, -370 # For occlusion and/or volume / original PBR extensions + + # Set IOR to 1.5, this is the default in glTF + # This value may be overridden later if IOR extension is set on file + pbr_node.inputs['IOR'].default_value = GLTF_IOR + + if mh.pymat.occlusion_texture is not None or (mh.pymat.extensions and 'KHR_materials_specular' in mh.pymat.extensions): + if mh.settings_node is None: + mh.settings_node = make_settings_node(mh) + mh.settings_node.location = additional_location + mh.settings_node.width = 180 + additional_location = additional_location[0], additional_location[1] - 150 + + need_volume_node = False + if mh.pymat.extensions and 'KHR_materials_volume' in mh.pymat.extensions: + if 'thicknessFactor' in mh.pymat.extensions['KHR_materials_volume'] \ + and mh.pymat.extensions['KHR_materials_volume']['thicknessFactor'] != 0.0: + + need_volume_node = True + + # We also need glTF Material Output Node, to set thicknessFactor and thicknessTexture + mh.settings_node = make_settings_node(mh) + mh.settings_node.location = additional_location + mh.settings_node.width = 180 + volume_location = additional_location + additional_location = additional_location[0], additional_location[1] - 150 + + need_velvet_node = False + if mh.pymat.extensions and 'KHR_materials_sheen' in mh.pymat.extensions: + need_velvet_node = True + + _, _, volume_socket, velvet_node = make_output_nodes( mh, location=(250, 260), + additional_location=additional_location, shader_socket=pbr_node.outputs[0], - make_emission_socket=False, - make_alpha_socket=False, + make_emission_socket=False, # is managed by Principled shader node + make_alpha_socket=False, # is managed by Principled shader node + make_volume_socket=need_volume_node, + make_velvet_socket=need_velvet_node ) + + if mh.pymat.extensions and 'KHR_materials_sheen': + pass #TOTOEXT + locs = calc_locations(mh) emission( @@ -75,13 +119,10 @@ def pbr_metallic_roughness(mh: MaterialHelper): ) if mh.pymat.occlusion_texture is not None: - node = make_settings_node(mh) - node.location = 40, -370 - node.width = 180 occlusion( mh, location=locs['occlusion'], - occlusion_socket=node.inputs['Occlusion'], + occlusion_socket=mh.settings_node.inputs['Occlusion'], ) clearcoat( @@ -102,6 +143,46 @@ def pbr_metallic_roughness(mh: MaterialHelper): normal_socket=pbr_node.inputs['Clearcoat Normal'], ) + transmission( + mh, + location=locs['transmission'], + transmission_socket=pbr_node.inputs['Transmission'] + ) + + if need_volume_node: + volume( + mh, + location=locs['volume_thickness'], + volume_socket=volume_socket, + thickness_socket=mh.settings_node.inputs[1] if mh.settings_node else None + ) + + specular( + mh, + location_specular=locs['specularTexture'], + location_specular_tint=locs['specularColorTexture'], + specular_socket=pbr_node.inputs['Specular'], + specular_tint_socket=pbr_node.inputs['Specular Tint'], + original_specular_socket=mh.settings_node.inputs[2] if mh.settings_node else None, + original_specularcolor_socket=mh.settings_node.inputs[3] if mh.settings_node else None, + location_original_specular=locs['original_specularTexture'], + location_original_specularcolor=locs['original_specularColorTexture'] + ) + + if need_velvet_node: + sheen( + mh, + location_sheenColor=locs['sheenColorTexture'], + location_sheenRoughness=locs['sheenRoughnessTexture'], + sheenColor_socket=velvet_node.inputs[0], + sheenRoughness_socket=velvet_node.inputs[1] + ) + + ior( + mh, + ior_socket=pbr_node.inputs['IOR'] + ) + def calc_locations(mh): """Calculate locations to place each bit of the node graph at.""" @@ -116,18 +197,53 @@ def calc_locations(mh): except Exception: clearcoat_ext = {} + try: + transmission_ext = mh.pymat.exntesions['KHR_materials_transmission'] + except: + transmission_ext = {} + + try: + volume_ext = mh.pymat.extensions['KHR_materials_volume'] + except Exception: + volume_ext = {} + + try: + specular_ext = mh.pymat.extensions['KHR_materials_specular'] + except: + specular_ext = {} + + try: + sheen_ext = mh.pymat.extensions['KHR_materials_sheen'] + except: + sheen_ext = {} + + locs['sheenColorTexture'] = (x, y) + if 'sheenColorTexture' in sheen_ext: + y -= height + locs['sheenRoughnessTexture'] = (x, y) + if 'sheenRoughnessTexture' in sheen_ext: + y -= height locs['base_color'] = (x, y) if mh.pymat.pbr_metallic_roughness.base_color_texture is not None or mh.vertex_color: y -= height locs['metallic_roughness'] = (x, y) if mh.pymat.pbr_metallic_roughness.metallic_roughness_texture is not None: y -= height + locs['specularTexture'] = (x, y) + if 'specularTexture' in specular_ext: + y -= height + locs['specularColorTexture'] = (x, y) + if 'specularColorTexture' in specular_ext: + y -= height locs['clearcoat'] = (x, y) if 'clearcoatTexture' in clearcoat_ext: y -= height locs['clearcoat_roughness'] = (x, y) if 'clearcoatRoughnessTexture' in clearcoat_ext: y -= height + locs['transmission'] = (x, y) + if 'transmissionTexture' in transmission_ext: + y -= height locs['emission'] = (x, y) if mh.pymat.emissive_texture is not None: y -= height @@ -140,6 +256,22 @@ def calc_locations(mh): locs['occlusion'] = (x, y) if mh.pymat.occlusion_texture is not None: y -= height + locs['volume_thickness'] = (x, y) + if 'thicknessTexture' in volume_ext: + y -= height + locs['original_specularTexture'] = (x, y) + if 'specularTexture' in specular_ext: + y -= height + locs['original_specularColorTexture'] = (x, y) + if 'specularColorTexture' in specular_ext: + y -= height + locs['original_sheenColorTexture'] = (x, y) + if 'sheenColorTexture' in sheen_ext: + y -= height + locs['original_sheenRoughnessTexture'] = (x, y) + if 'sheenRoughnessTexture' in sheen_ext: + y -= height + # Center things total_height = -y @@ -157,21 +289,29 @@ def calc_locations(mh): # [Texture] => [Emissive Factor] => -def emission(mh: MaterialHelper, location, color_socket, strength_socket=None): +def emission(mh: MaterialHelper, location, color_socket, strength_socket): x, y = location emissive_factor = mh.pymat.emissive_factor or [0, 0, 0] + strength = 1 + try: + # Get strength from KHR_materials_emissive_strength if exists + strength = mh.pymat.extensions['KHR_materials_emissive_strength']['emissiveStrength'] + except Exception: + pass + if color_socket is None: return if mh.pymat.emissive_texture is None: color_socket.default_value = emissive_factor + [1] + strength_socket.default_value = strength return # Put grayscale emissive factors into the Emission Strength e0, e1, e2 = emissive_factor if strength_socket and e0 == e1 == e2: - strength_socket.default_value = e0 + strength_socket.default_value = e0 * strength # Otherwise, use a multiply node for it else: @@ -189,6 +329,8 @@ def emission(mh: MaterialHelper, location, color_socket, strength_socket=None): x -= 200 + strength_socket.default_value = strength + texture( mh, tex_info=mh.pymat.emissive_texture, @@ -466,17 +608,22 @@ def occlusion(mh: MaterialHelper, location, occlusion_socket): ) -# => [Add Emission] => [Mix Alpha] => [Material Output] +# => [Add Emission] => [Mix Alpha] => [Material Output] if needed, only for SpecGlossiness +# => [Volume] => [Add Shader] => [Material Output] if needed +# => [Velvet] => [Add Shader] => [Material Output] if needed def make_output_nodes( mh: MaterialHelper, location, + additional_location, shader_socket, make_emission_socket, make_alpha_socket, + make_volume_socket, + make_velvet_socket, # For sheen ): """ Creates the Material Output node and connects shader_socket to it. - If requested, it can also create places to hookup the emission/alpha + If requested, it can also create places to hookup the emission/alpha.sheen in between shader_socket and the Output node too. :return: a pair containing the sockets you should put emission and alpha @@ -484,6 +631,7 @@ def make_output_nodes( """ x, y = location emission_socket = None + velvet_node = None alpha_socket = None # Create an Emission node and add it to the shader. @@ -512,6 +660,31 @@ def make_output_nodes( x += 380 y += 125 + # Create an Velvet node add add it to the shader + # Note that you can not have Emission & Velvet at the same time + if make_velvet_socket: + # Velvet + node = mh.node_tree.nodes.new("ShaderNodeBsdfVelvet") + node.location = x + 50, y + 250 + # Node + velvet_node = node + # Outputs + velvet_output = node.outputs[0] + + # Add + node = mh.node_tree.nodes.new('ShaderNodeAddShader') + node.location = x + 250, y + 160 + # Inputs + mh.node_tree.links.new(node.inputs[0], velvet_output) + mh.node_tree.links.new(node.inputs[1], shader_socket) + # Outputs + shader_socket = node.outputs[0] + + + x += 380 + y += 125 + + # Mix with a Transparent BSDF. Mixing factor is the alpha value. if make_alpha_socket: # Transparent BSDF @@ -535,12 +708,23 @@ def make_output_nodes( y -= 210 # Material output - node = mh.node_tree.nodes.new('ShaderNodeOutputMaterial') - node.location = x + 70, y + 10 + node_output = mh.node_tree.nodes.new('ShaderNodeOutputMaterial') + node_output.location = x + 70, y + 10 + # Outputs - mh.node_tree.links.new(node.inputs[0], shader_socket) + mh.node_tree.links.new(node_output.inputs[0], shader_socket) + + # Volume Node + volume_socket = None + if make_volume_socket: + node = mh.node_tree.nodes.new('ShaderNodeVolumeAbsorption') + node.location = additional_location + # Outputs + mh.node_tree.links.new(node_output.inputs[1], node.outputs[0]) + volume_socket = node.outputs[0] + - return emission_socket, alpha_socket + return emission_socket, alpha_socket, volume_socket, velvet_node def make_settings_node(mh): |