# 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_texture import BlenderTextureInfo class BlenderKHR_materials_pbrSpecularGlossiness(): """Blender KHR_materials_pbrSpecularGlossiness extension.""" def __new__(cls, *args, **kwargs): raise RuntimeError("%s should not be instantiated" % cls) @staticmethod def create(gltf, pbrSG, mat_name, vertex_color): """KHR_materials_pbrSpecularGlossiness creation.""" engine = bpy.context.scene.render.engine if engine in ['CYCLES', 'BLENDER_EEVEE']: BlenderKHR_materials_pbrSpecularGlossiness.create_nodetree(gltf, pbrSG, mat_name, vertex_color) @staticmethod def create_nodetree(gltf, pbrSG, mat_name, vertex_color): """Node tree creation.""" material = bpy.data.materials[mat_name] material.use_nodes = True node_tree = material.node_tree # delete all nodes except output for node in list(node_tree.nodes): if not node.type == 'OUTPUT_MATERIAL': node_tree.nodes.remove(node) output_node = node_tree.nodes[0] output_node.location = 1000, 0 # create PBR node diffuse = node_tree.nodes.new('ShaderNodeBsdfDiffuse') diffuse.location = 0, 0 glossy = node_tree.nodes.new('ShaderNodeBsdfGlossy') glossy.location = 0, 100 mix = node_tree.nodes.new('ShaderNodeMixShader') mix.location = 500, 0 glossy.inputs[1].default_value = 1 - pbrSG['glossinessFactor'] if pbrSG['diffuse_type'] == gltf.SIMPLE: if not vertex_color: # change input values diffuse.inputs[0].default_value = pbrSG['diffuseFactor'] else: # Create attribute node to get COLOR_0 data attribute_node = node_tree.nodes.new('ShaderNodeAttribute') attribute_node.attribute_name = 'COLOR_0' attribute_node.location = -500, 0 # links node_tree.links.new(diffuse.inputs[0], attribute_node.outputs[0]) elif pbrSG['diffuse_type'] == gltf.TEXTURE_FACTOR: # TODO alpha ? if vertex_color: # TODO tree locations # Create attribute / separate / math nodes attribute_node = node_tree.nodes.new('ShaderNodeAttribute') attribute_node.attribute_name = 'COLOR_0' separate_vertex_color = node_tree.nodes.new('ShaderNodeSeparateRGB') math_vc_R = node_tree.nodes.new('ShaderNodeMath') math_vc_R.operation = 'MULTIPLY' math_vc_G = node_tree.nodes.new('ShaderNodeMath') math_vc_G.operation = 'MULTIPLY' math_vc_B = node_tree.nodes.new('ShaderNodeMath') math_vc_B.operation = 'MULTIPLY' BlenderTextureInfo.create(gltf, pbrSG['diffuseTexture']['index']) # create UV Map / Mapping / Texture nodes / separate & math and combine text_node = node_tree.nodes.new('ShaderNodeTexImage') text_node.image = \ bpy.data.images[ gltf.data.images[gltf.data.textures[pbrSG['diffuseTexture']['index']].source].blender_image_name ] text_node.location = -1000, 500 combine = node_tree.nodes.new('ShaderNodeCombineRGB') combine.location = -250, 500 math_R = node_tree.nodes.new('ShaderNodeMath') math_R.location = -500, 750 math_R.operation = 'MULTIPLY' math_R.inputs[1].default_value = pbrSG['diffuseFactor'][0] math_G = node_tree.nodes.new('ShaderNodeMath') math_G.location = -500, 500 math_G.operation = 'MULTIPLY' math_G.inputs[1].default_value = pbrSG['diffuseFactor'][1] math_B = node_tree.nodes.new('ShaderNodeMath') math_B.location = -500, 250 math_B.operation = 'MULTIPLY' math_B.inputs[1].default_value = pbrSG['diffuseFactor'][2] separate = node_tree.nodes.new('ShaderNodeSeparateRGB') separate.location = -750, 500 mapping = node_tree.nodes.new('ShaderNodeMapping') mapping.location = -1500, 500 uvmap = node_tree.nodes.new('ShaderNodeUVMap') uvmap.location = -2000, 500 if 'texCoord' in pbrSG['diffuseTexture'].keys(): uvmap["gltf2_texcoord"] = pbrSG['diffuseTexture']['texCoord'] # Set custom flag to retrieve TexCoord else: uvmap["gltf2_texcoord"] = 0 # TODO: set in precompute instead of here? # UV Map will be set after object/UVMap creation # Create links if vertex_color: node_tree.links.new(separate_vertex_color.inputs[0], attribute_node.outputs[0]) node_tree.links.new(math_vc_R.inputs[1], separate_vertex_color.outputs[0]) node_tree.links.new(math_vc_G.inputs[1], separate_vertex_color.outputs[1]) node_tree.links.new(math_vc_B.inputs[1], separate_vertex_color.outputs[2]) node_tree.links.new(math_vc_R.inputs[0], math_R.outputs[0]) node_tree.links.new(math_vc_G.inputs[0], math_G.outputs[0]) node_tree.links.new(math_vc_B.inputs[0], math_B.outputs[0]) node_tree.links.new(combine.inputs[0], math_vc_R.outputs[0]) node_tree.links.new(combine.inputs[1], math_vc_G.outputs[0]) node_tree.links.new(combine.inputs[2], math_vc_B.outputs[0]) else: node_tree.links.new(combine.inputs[0], math_R.outputs[0]) node_tree.links.new(combine.inputs[1], math_G.outputs[0]) node_tree.links.new(combine.inputs[2], math_B.outputs[0]) # Common for both mode (non vertex color / vertex color) node_tree.links.new(math_R.inputs[0], separate.outputs[0]) node_tree.links.new(math_G.inputs[0], separate.outputs[1]) node_tree.links.new(math_B.inputs[0], separate.outputs[2]) node_tree.links.new(mapping.inputs[0], uvmap.outputs[0]) node_tree.links.new(text_node.inputs[0], mapping.outputs[0]) node_tree.links.new(separate.inputs[0], text_node.outputs[0]) node_tree.links.new(diffuse.inputs[0], combine.outputs[0]) elif pbrSG['diffuse_type'] == gltf.TEXTURE: BlenderTextureInfo.create(gltf, pbrSG['diffuseTexture']['index']) # TODO alpha ? if vertex_color: # Create attribute / separate / math nodes attribute_node = node_tree.nodes.new('ShaderNodeAttribute') attribute_node.attribute_name = 'COLOR_0' attribute_node.location = -2000, 250 separate_vertex_color = node_tree.nodes.new('ShaderNodeSeparateRGB') separate_vertex_color.location = -1500, 250 math_vc_R = node_tree.nodes.new('ShaderNodeMath') math_vc_R.operation = 'MULTIPLY' math_vc_R.location = -1000, 750 math_vc_G = node_tree.nodes.new('ShaderNodeMath') math_vc_G.operation = 'MULTIPLY' math_vc_G.location = -1000, 500 math_vc_B = node_tree.nodes.new('ShaderNodeMath') math_vc_B.operation = 'MULTIPLY' math_vc_B.location = -1000, 250 combine = node_tree.nodes.new('ShaderNodeCombineRGB') combine.location = -500, 500 separate = node_tree.nodes.new('ShaderNodeSeparateRGB') separate.location = -1500, 500 # create UV Map / Mapping / Texture nodes / separate & math and combine text_node = node_tree.nodes.new('ShaderNodeTexImage') text_node.image = bpy.data.images[ gltf.data.images[gltf.data.textures[pbrSG['diffuseTexture']['index']].source].blender_image_name ] if vertex_color: text_node.location = -2000, 500 else: text_node.location = -500, 500 mapping = node_tree.nodes.new('ShaderNodeMapping') if vertex_color: mapping.location = -2500, 500 else: mapping.location = -1500, 500 uvmap = node_tree.nodes.new('ShaderNodeUVMap') if vertex_color: uvmap.location = -3000, 500 else: uvmap.location = -2000, 500 if 'texCoord' in pbrSG['diffuseTexture'].keys(): uvmap["gltf2_texcoord"] = pbrSG['diffuseTexture']['texCoord'] # Set custom flag to retrieve TexCoord else: uvmap["gltf2_texcoord"] = 0 # TODO: set in precompute instead of here? # UV Map will be set after object/UVMap creation # Create links if vertex_color: node_tree.links.new(separate_vertex_color.inputs[0], attribute_node.outputs[0]) node_tree.links.new(math_vc_R.inputs[1], separate_vertex_color.outputs[0]) node_tree.links.new(math_vc_G.inputs[1], separate_vertex_color.outputs[1]) node_tree.links.new(math_vc_B.inputs[1], separate_vertex_color.outputs[2]) node_tree.links.new(combine.inputs[0], math_vc_R.outputs[0]) node_tree.links.new(combine.inputs[1], math_vc_G.outputs[0]) node_tree.links.new(combine.inputs[2], math_vc_B.outputs[0]) node_tree.links.new(separate.inputs[0], text_node.outputs[0]) node_tree.links.new(diffuse.inputs[0], combine.outputs[0]) node_tree.links.new(math_vc_R.inputs[0], separate.outputs[0]) node_tree.links.new(math_vc_G.inputs[0], separate.outputs[1]) node_tree.links.new(math_vc_B.inputs[0], separate.outputs[2]) else: node_tree.links.new(diffuse.inputs[0], text_node.outputs[0]) # Common for both mode (non vertex color / vertex color) node_tree.links.new(mapping.inputs[0], uvmap.outputs[0]) node_tree.links.new(text_node.inputs[0], mapping.outputs[0]) if pbrSG['specgloss_type'] == gltf.SIMPLE: combine = node_tree.nodes.new('ShaderNodeCombineRGB') combine.inputs[0].default_value = pbrSG['specularFactor'][0] combine.inputs[1].default_value = pbrSG['specularFactor'][1] combine.inputs[2].default_value = pbrSG['specularFactor'][2] # links node_tree.links.new(glossy.inputs[0], combine.outputs[0]) elif pbrSG['specgloss_type'] == gltf.TEXTURE: BlenderTextureInfo.create(gltf, pbrSG['specularGlossinessTexture']['index']) spec_text = node_tree.nodes.new('ShaderNodeTexImage') spec_text.image = bpy.data.images[ gltf.data.images[ gltf.data.textures[pbrSG['specularGlossinessTexture']['index']].source ].blender_image_name ] spec_text.color_space = 'NONE' spec_text.location = -500, 0 spec_mapping = node_tree.nodes.new('ShaderNodeMapping') spec_mapping.location = -1000, 0 spec_uvmap = node_tree.nodes.new('ShaderNodeUVMap') spec_uvmap.location = -1500, 0 if 'texCoord' in pbrSG['specularGlossinessTexture'].keys(): # Set custom flag to retrieve TexCoord spec_uvmap["gltf2_texcoord"] = pbrSG['specularGlossinessTexture']['texCoord'] else: spec_uvmap["gltf2_texcoord"] = 0 # TODO: set in precompute instead of here? # links node_tree.links.new(glossy.inputs[0], spec_text.outputs[0]) node_tree.links.new(mix.inputs[0], spec_text.outputs[1]) node_tree.links.new(spec_mapping.inputs[0], spec_uvmap.outputs[0]) node_tree.links.new(spec_text.inputs[0], spec_mapping.outputs[0]) elif pbrSG['specgloss_type'] == gltf.TEXTURE_FACTOR: BlenderTextureInfo.create(gltf, pbrSG['specularGlossinessTexture']['index']) spec_text = node_tree.nodes.new('ShaderNodeTexImage') spec_text.image = bpy.data.images[gltf.data.images[ gltf.data.textures[pbrSG['specularGlossinessTexture']['index']].source ].blender_image_name] spec_text.color_space = 'NONE' spec_text.location = -1000, 0 spec_math = node_tree.nodes.new('ShaderNodeMath') spec_math.operation = 'MULTIPLY' spec_math.inputs[0].default_value = pbrSG['glossinessFactor'] spec_math.location = -250, 100 spec_mapping = node_tree.nodes.new('ShaderNodeMapping') spec_mapping.location = -1000, 0 spec_uvmap = node_tree.nodes.new('ShaderNodeUVMap') spec_uvmap.location = -1500, 0 if 'texCoord' in pbrSG['specularGlossinessTexture'].keys(): # Set custom flag to retrieve TexCoord spec_uvmap["gltf2_texcoord"] = pbrSG['specularGlossinessTexture']['texCoord'] else: spec_uvmap["gltf2_texcoord"] = 0 # TODO: set in precompute instead of here? # links node_tree.links.new(spec_math.inputs[1], spec_text.outputs[0]) node_tree.links.new(mix.inputs[0], spec_text.outputs[1]) node_tree.links.new(glossy.inputs[1], spec_math.outputs[0]) node_tree.links.new(glossy.inputs[0], spec_text.outputs[0]) node_tree.links.new(spec_mapping.inputs[0], spec_uvmap.outputs[0]) node_tree.links.new(spec_text.inputs[0], spec_mapping.outputs[0]) # link node to output node_tree.links.new(mix.inputs[2], diffuse.outputs[0]) node_tree.links.new(mix.inputs[1], glossy.outputs[0]) node_tree.links.new(output_node.inputs[0], mix.outputs[0])