diff options
author | Julien Duroure <julien.duroure@gmail.com> | 2018-11-24 18:28:33 +0300 |
---|---|---|
committer | Julien Duroure <julien.duroure@gmail.com> | 2018-11-24 18:28:33 +0300 |
commit | b1f2133fa2849da272e9d8404f371220226ddaf1 (patch) | |
tree | 25db56e0f2211bd1059fe0e04e78430a6156e021 /io_scene_gltf2/blender/imp/gltf2_blender_material.py | |
parent | 8959f1798cfc86924493347304118c61bd5c7f7a (diff) |
Initial commit of glTF 2.0 importer/exporter
Official Khronos Group Blender glTF 2.0 importer and exporter.
glTF specification: https://github.com/KhronosGroup/glTF
The upstream repository can be found here:
https://github.com/KhronosGroup/glTF-Blender-IO
Reviewed By: Bastien, Campbell
Differential Revision: https://developer.blender.org/D3929
Diffstat (limited to 'io_scene_gltf2/blender/imp/gltf2_blender_material.py')
-rwxr-xr-x | io_scene_gltf2/blender/imp/gltf2_blender_material.py | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/io_scene_gltf2/blender/imp/gltf2_blender_material.py b/io_scene_gltf2/blender/imp/gltf2_blender_material.py new file mode 100755 index 00000000..c9fa6927 --- /dev/null +++ b/io_scene_gltf2/blender/imp/gltf2_blender_material.py @@ -0,0 +1,150 @@ +# Copyright 2018 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. + +import bpy +from .gltf2_blender_pbrMetallicRoughness import BlenderPbr +from .gltf2_blender_KHR_materials_pbrSpecularGlossiness import BlenderKHR_materials_pbrSpecularGlossiness +from .gltf2_blender_map_emissive import BlenderEmissiveMap +from .gltf2_blender_map_normal import BlenderNormalMap +from .gltf2_blender_map_occlusion import BlenderOcclusionMap +from ..com.gltf2_blender_material_helpers import get_output_surface_input +from ..com.gltf2_blender_material_helpers import get_preoutput_node_output +from ..com.gltf2_blender_material_helpers import get_base_color_node +from ...io.com.gltf2_io import MaterialPBRMetallicRoughness + + +class BlenderMaterial(): + """Blender Material.""" + def __new__(cls, *args, **kwargs): + raise RuntimeError("%s should not be instantiated" % cls) + + @staticmethod + def create(gltf, material_idx, vertex_color): + """Material creation.""" + pymaterial = gltf.data.materials[material_idx] + + if pymaterial.name is not None: + name = pymaterial.name + else: + name = "Material_" + str(material_idx) + + mat = bpy.data.materials.new(name) + pymaterial.blender_material = mat.name + + if pymaterial.extensions is not None and 'KHR_materials_pbrSpecularGlossiness' in pymaterial.extensions.keys(): + BlenderKHR_materials_pbrSpecularGlossiness.create( + gltf, pymaterial.extensions['KHR_materials_pbrSpecularGlossiness'], mat.name, vertex_color + ) + else: + # create pbr material + if pymaterial.pbr_metallic_roughness is None: + # If no pbr material is set, we need to apply all default of pbr + pbr = {} + pbr["baseColorFactor"] = [1.0, 1.0, 1.0, 1.0] + pbr["metallicFactor"] = 1.0 + pbr["roughnessFactor"] = 1.0 + pymaterial.pbr_metallic_roughness = MaterialPBRMetallicRoughness.from_dict(pbr) + pymaterial.pbr_metallic_roughness.color_type = gltf.SIMPLE + pymaterial.pbr_metallic_roughness.metallic_type = gltf.SIMPLE + + BlenderPbr.create(gltf, pymaterial.pbr_metallic_roughness, mat.name, vertex_color) + + # add emission map if needed + if pymaterial.emissive_texture is not None: + BlenderEmissiveMap.create(gltf, material_idx) + + # add normal map if needed + if pymaterial.normal_texture is not None: + BlenderNormalMap.create(gltf, material_idx) + + # add occlusion map if needed + # will be pack, but not used + if pymaterial.occlusion_texture is not None: + BlenderOcclusionMap.create(gltf, material_idx) + + if pymaterial.alpha_mode is not None and pymaterial.alpha_mode != 'OPAQUE': + BlenderMaterial.blender_alpha(gltf, material_idx) + + @staticmethod + def set_uvmap(gltf, material_idx, prim, obj): + """Set UV Map.""" + pymaterial = gltf.data.materials[material_idx] + + node_tree = bpy.data.materials[pymaterial.blender_material].node_tree + uvmap_nodes = [node for node in node_tree.nodes if node.type in ['UVMAP', 'NORMAL_MAP']] + for uvmap_node in uvmap_nodes: + if uvmap_node["gltf2_texcoord"] in prim.blender_texcoord.keys(): + uvmap_node.uv_map = prim.blender_texcoord[uvmap_node["gltf2_texcoord"]] + + @staticmethod + def blender_alpha(gltf, material_idx): + """Set alpha.""" + pymaterial = gltf.data.materials[material_idx] + material = bpy.data.materials[pymaterial.blender_material] + + node_tree = material.node_tree + # Add nodes for basic transparency + # Add mix shader between output and Principled BSDF + trans = node_tree.nodes.new('ShaderNodeBsdfTransparent') + trans.location = 750, -500 + mix = node_tree.nodes.new('ShaderNodeMixShader') + mix.location = 1000, 0 + + output_surface_input = get_output_surface_input(node_tree) + preoutput_node_output = get_preoutput_node_output(node_tree) + + link = output_surface_input.links[0] + node_tree.links.remove(link) + + # PBR => Mix input 1 + node_tree.links.new(preoutput_node_output, mix.inputs[1]) + + # Trans => Mix input 2 + node_tree.links.new(trans.outputs['BSDF'], mix.inputs[2]) + + # Mix => Output + node_tree.links.new(mix.outputs['Shader'], output_surface_input) + + # alpha blend factor + add = node_tree.nodes.new('ShaderNodeMath') + add.operation = 'ADD' + add.location = 750, -250 + + diffuse_factor = 1.0 + if pymaterial.extensions is not None and 'KHR_materials_pbrSpecularGlossiness' in pymaterial.extensions: + diffuse_factor = pymaterial.extensions['KHR_materials_pbrSpecularGlossiness']['diffuseFactor'][3] + elif pymaterial.pbr_metallic_roughness: + diffuse_factor = pymaterial.pbr_metallic_roughness.base_color_factor[3] + + add.inputs[0].default_value = abs(1.0 - diffuse_factor) + add.inputs[1].default_value = 0.0 + node_tree.links.new(add.outputs['Value'], mix.inputs[0]) + + # Take diffuse texture alpha into account if any + diffuse_texture = get_base_color_node(node_tree) + if diffuse_texture: + inverter = node_tree.nodes.new('ShaderNodeInvert') + inverter.location = 250, -250 + inverter.inputs[1].default_value = (1.0, 1.0, 1.0, 1.0) + node_tree.links.new(diffuse_texture.outputs['Alpha'], inverter.inputs[0]) + + mult = node_tree.nodes.new('ShaderNodeMath') + mult.operation = 'MULTIPLY' if pymaterial.alpha_mode == 'BLEND' else 'GREATER_THAN' + mult.location = 500, -250 + alpha_cutoff = 1.0 if pymaterial.alpha_mode == 'BLEND' else \ + 1.0 - pymaterial.alpha_cutoff if pymaterial.alpha_cutoff is not None else 0.5 + mult.inputs[1].default_value = alpha_cutoff + node_tree.links.new(inverter.outputs['Color'], mult.inputs[0]) + node_tree.links.new(mult.outputs['Value'], add.inputs[0]) + |