From 64d34396670d825f03131903ef6cef4332adf653 Mon Sep 17 00:00:00 2001 From: Julien Duroure Date: Tue, 12 May 2020 18:40:11 +0200 Subject: glTF importer: implement KHR_materials_clearcoat --- io_scene_gltf2/__init__.py | 2 +- .../imp/gltf2_blender_KHR_materials_clearcoat.py | 161 +++++++++++++++++++++ .../imp/gltf2_blender_pbrMetallicRoughness.py | 19 +++ io_scene_gltf2/io/imp/gltf2_io_gltf.py | 3 +- 4 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 io_scene_gltf2/blender/imp/gltf2_blender_KHR_materials_clearcoat.py diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py index 09f5428b..50a313fb 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, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors', - "version": (1, 3, 13), + "version": (1, 3, 14), 'blender': (2, 90, 0), 'location': 'File > Import-Export', 'description': 'Import-Export as glTF 2.0', diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_KHR_materials_clearcoat.py b/io_scene_gltf2/blender/imp/gltf2_blender_KHR_materials_clearcoat.py new file mode 100644 index 00000000..611bffff --- /dev/null +++ b/io_scene_gltf2/blender/imp/gltf2_blender_KHR_materials_clearcoat.py @@ -0,0 +1,161 @@ +# Copyright 2018-2019 The glTF-Blender-IO authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ...io.com.gltf2_io import TextureInfo, MaterialNormalTextureInfoClass +from .gltf2_blender_texture import texture + + +# [Texture] => [Clearcoat Factor] => +def clearcoat(mh, location, clearcoat_socket): + x, y = location + try: + ext = mh.pymat.extensions['KHR_materials_clearcoat'] + except Exception: + return + clearcoat_factor = ext.get('clearcoatFactor', 0) + tex_info = ext.get('clearcoatTexture') + if tex_info is not None: + tex_info = TextureInfo.from_dict(tex_info) + + if clearcoat_socket is None: + return + + if tex_info is None: + clearcoat_socket.default_value = clearcoat_factor + return + + # Mix clearcoat factor + if clearcoat_factor != 1: + node = mh.node_tree.nodes.new('ShaderNodeMath') + node.label = 'Clearcoat Factor' + node.location = x - 140, y + node.operation = 'MULTIPLY' + # Outputs + mh.node_tree.links.new(clearcoat_socket, node.outputs[0]) + # Inputs + clearcoat_socket = node.inputs[0] + node.inputs[1].default_value = clearcoat_factor + + x -= 200 + + # Clearcoat is in the R component; we don't need to separate it out + # since hooking a color socket up to a value socket automatically gets + # the R + + texture( + mh, + tex_info=tex_info, + label='CLEARCOAT', + location=(x, y), + is_data=True, + color_socket=clearcoat_socket, + ) + + +# [Texture] => [Seperate G] => [Roughness Factor] => +def clearcoat_roughness(mh, location, roughness_socket): + x, y = location + try: + ext = mh.pymat.extensions['KHR_materials_clearcoat'] + except Exception: + return + roughness_factor = ext.get('clearcoatRoughnessFactor', 0) + tex_info = ext.get('clearcoatRoughnessTexture') + if tex_info is not None: + tex_info = TextureInfo.from_dict(tex_info) + + if roughness_socket is None: + return + + if tex_info is None: + roughness_socket.default_value = roughness_factor + return + + # Mix roughness factor + if roughness_factor != 1: + node = mh.node_tree.nodes.new('ShaderNodeMath') + node.label = 'Clearcoat Roughness Factor' + node.location = x - 140, y + node.operation = 'MULTIPLY' + # Outputs + mh.node_tree.links.new(roughness_socket, node.outputs[0]) + # Inputs + roughness_socket = node.inputs[0] + node.inputs[1].default_value = roughness_factor + + x -= 200 + + # Separate RGB (roughness is in G) + node = mh.node_tree.nodes.new('ShaderNodeSeparateRGB') + node.location = x - 150, y - 75 + # Outputs + mh.node_tree.links.new(roughness_socket, node.outputs['G']) + # Inputs + color_socket = node.inputs[0] + + x -= 200 + + texture( + mh, + tex_info=tex_info, + label='CLEARCOAT ROUGHNESS', + location=(x, y), + is_data=True, + color_socket=color_socket, + ) + + +# [Texture] => [Normal Map] => +def clearcoat_normal(mh, location, normal_socket): + x,y = location + try: + ext = mh.pymat.extensions['KHR_materials_clearcoat'] + except Exception: + return + tex_info = ext.get('clearcoatNormalTexture') + if tex_info is not None: + tex_info = MaterialNormalTextureInfoClass.from_dict(tex_info) + + if tex_info is None: + return + + # Normal map + node = mh.node_tree.nodes.new('ShaderNodeNormalMap') + node.location = x - 150, y - 40 + # Set UVMap + uv_idx = tex_info.tex_coord or 0 + try: + uv_idx = tex_info.extensions['KHR_texture_transform']['texCoord'] + except Exception: + pass + node.uv_map = 'UVMap' if uv_idx == 0 else 'UVMap.%03d' % uv_idx + # Set strength + scale = tex_info.scale + scale = scale if scale is not None else 1 + node.inputs['Strength'].default_value = scale + # Outputs + mh.node_tree.links.new(normal_socket, node.outputs['Normal']) + # Inputs + color_socket = node.inputs['Color'] + + x -= 200 + + texture( + mh, + tex_info=tex_info, + label='CLEARCOAT NORMAL', + location=(x, y), + is_data=True, + color_socket=color_socket, + ) diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py b/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py index a4910fa0..7e750e52 100755 --- a/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py +++ b/io_scene_gltf2/blender/imp/gltf2_blender_pbrMetallicRoughness.py @@ -16,6 +16,8 @@ import bpy from ...io.com.gltf2_io import TextureInfo, MaterialPBRMetallicRoughness from ..com.gltf2_blender_material_helpers import get_gltf_node_name from .gltf2_blender_texture import texture +from .gltf2_blender_KHR_materials_clearcoat import \ + clearcoat, clearcoat_roughness, clearcoat_normal class MaterialHelper: @@ -88,6 +90,23 @@ def pbr_metallic_roughness(mh: MaterialHelper): occlusion_socket=node.inputs['Occlusion'], ) + clearcoat( + mh, + location=(-200, -1060), + clearcoat_socket=pbr_node.inputs['Clearcoat'], + ) + + clearcoat_roughness( + mh, + location=(-200, -1540), + roughness_socket=pbr_node.inputs['Clearcoat Roughness'], + ) + + clearcoat_normal( + mh, + location=(-200, -2020), + normal_socket=pbr_node.inputs['Clearcoat Normal'], + ) # These functions each create one piece of the node graph, slotting # their outputs into the given socket, or setting its default value. diff --git a/io_scene_gltf2/io/imp/gltf2_io_gltf.py b/io_scene_gltf2/io/imp/gltf2_io_gltf.py index 640e552a..e63f1f55 100755 --- a/io_scene_gltf2/io/imp/gltf2_io_gltf.py +++ b/io_scene_gltf2/io/imp/gltf2_io_gltf.py @@ -45,7 +45,8 @@ class glTFImporter(): 'KHR_materials_pbrSpecularGlossiness', 'KHR_lights_punctual', 'KHR_materials_unlit', - 'KHR_texture_transform' + 'KHR_texture_transform', + 'KHR_materials_clearcoat', ] # TODO : merge with io_constants -- cgit v1.2.3