def is_transluc(material): nodes = material.node_tree.nodes output_node = cycles.node_by_type(nodes, 'OUTPUT_MATERIAL') if output_node == None or output_node.inputs[0].is_linked == False: return False surface_node = output_node.inputs[0].links[0].from_node return is_transluc_traverse(surface_node)
def get_sorted(mat): nodes = mat.node_tree.nodes output_node = cycles.node_by_type(nodes, 'OUTPUT_MATERIAL') if output_node != None: ar = [] traverse_tree2(output_node, ar) return ar
def parse_objectinfo(node: bpy.types.ShaderNodeObjectInfo, out_socket: bpy.types.NodeSocket, state: ParserState) -> Union[floatstr, vec3str]: # Location if out_socket == node.outputs[0]: if state.context == ParserContext.WORLD: return c.to_vec3((0.0, 0.0, 0.0)) return 'wposition' # Color elif out_socket == node.outputs[1]: if state.context == ParserContext.WORLD: # Use world strength like Blender background_node = c.node_by_type(state.world.node_tree.nodes, 'BACKGROUND') if background_node is None: return c.to_vec3((0.0, 0.0, 0.0)) return c.to_vec3([background_node.inputs[1].default_value] * 3) # TODO: Implement object color in Iron # state.curshader.add_uniform('vec3 objectInfoColor', link='_objectInfoColor') # return 'objectInfoColor' return c.to_vec3((1.0, 1.0, 1.0)) # Object Index elif out_socket == node.outputs[2]: if state.context == ParserContext.WORLD: return '0.0' state.curshader.add_uniform('float objectInfoIndex', link='_objectInfoIndex') return 'objectInfoIndex' # Material Index elif out_socket == node.outputs[3]: if state.context == ParserContext.WORLD: return '0.0' state.curshader.add_uniform('float objectInfoMaterialIndex', link='_objectInfoMaterialIndex') return 'objectInfoMaterialIndex' # Random elif out_socket == node.outputs[4]: if state.context == ParserContext.WORLD: return '0.0' # Use random value per instance if mat_state.uses_instancing: state.vert.add_out(f'flat float irand') state.frag.add_in(f'flat float irand') state.vert.write( f'irand = fract(sin(gl_InstanceID) * 43758.5453);') return 'irand' state.curshader.add_uniform('float objectInfoRandom', link='_objectInfoRandom') return 'objectInfoRandom'
def get_signature(mat): nodes = mat.node_tree.nodes output_node = cycles.node_by_type(nodes, 'OUTPUT_MATERIAL') if output_node != None: sign = traverse_tree(output_node, '') # Append flags sign += '1' if mat.arm_cast_shadow else '0' sign += '1' if mat.arm_overlay else '0' sign += '1' if mat.arm_cull_mode == 'Clockwise' else '0' return sign
def build(material, mat_users, mat_armusers): mat_state.mat_users = mat_users mat_state.mat_armusers = mat_armusers mat_state.material = material mat_state.nodes = material.node_tree.nodes mat_state.data = ShaderData(material) mat_state.output_node = cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL') if mat_state.output_node == None: # Place empty material output to keep compiler happy.. mat_state.output_node = mat_state.nodes.new('ShaderNodeOutputMaterial') wrd = bpy.data.worlds['Arm'] rpdat = arm.utils.get_rp() rpasses = mat_utils.get_rpasses(material) matname = arm.utils.safesrc(arm.utils.asset_name(material)) rel_path = arm.utils.build_dir() + '/compiled/Shaders/' full_path = arm.utils.get_fp() + '/' + rel_path if not os.path.exists(full_path): os.makedirs(full_path) global_elems = [] if mat_users != None and material in mat_users: for bo in mat_users[material]: # GPU Skinning if arm.utils.export_bone_data(bo): global_elems.append({'name': 'bone', 'size': 4}) global_elems.append({'name': 'weight', 'size': 4}) # Instancing if bo.arm_instanced or material.arm_particle_flag: global_elems.append({'name': 'off', 'size': 3}) mat_state.data.global_elems = global_elems bind_constants = dict() bind_textures = dict() for rp in rpasses: car = [] bind_constants[rp] = car mat_state.bind_constants = car tar = [] bind_textures[rp] = tar mat_state.bind_textures = tar con = None if rpdat.rp_driver != 'Armory' and arm.api.drivers[rpdat.rp_driver]['make_rpass'] != None: con = arm.api.drivers[rpdat.rp_driver]['make_rpass'](rp) if con != None: pass elif rp == 'mesh': con = make_mesh.make(rp) elif rp == 'rect': con = make_rect.make(rp) elif rp == 'shadowmap': con = make_depth.make(rp, rpasses, shadowmap=True) elif rp == 'translucent': con = make_transluc.make(rp) elif rp == 'overlay': con = make_overlay.make(rp) elif rp == 'decal': con = make_decal.make(rp) elif rp == 'depth': con = make_depth.make(rp, rpasses) elif rp == 'voxel': con = make_voxel.make(rp) elif rpass_hook != None: con = rpass_hook(rp) write_shaders(rel_path, con, rp, matname) arm.utils.write_arm(full_path + '/' + matname + '_data.arm', mat_state.data.get()) shader_data_name = matname + '_data' shader_data_path = arm.utils.get_fp_build() + '/compiled/Shaders/' + shader_data_name + '.arm' assets.add_shader_data(shader_data_path) return rpasses, mat_state.data, shader_data_name, bind_constants, bind_textures
def build(material: Material, mat_users: Dict[Material, List[Object]], mat_armusers) -> Tuple: mat_state.mat_users = mat_users mat_state.mat_armusers = mat_armusers mat_state.material = material mat_state.nodes = material.node_tree.nodes mat_state.data = ShaderData(material) mat_state.output_node = cycles.node_by_type(mat_state.nodes, 'OUTPUT_MATERIAL') if mat_state.output_node is None: # Place empty material output to keep compiler happy.. mat_state.output_node = mat_state.nodes.new('ShaderNodeOutputMaterial') wrd = bpy.data.worlds['Arm'] rpdat = arm.utils.get_rp() rpasses = mat_utils.get_rpasses(material) is_emissive = mat_utils.is_emmisive(material) if is_emissive and '_Emission' not in wrd.world_defs: wrd.world_defs += '_Emission' matname = arm.utils.safesrc(arm.utils.asset_name(material)) rel_path = arm.utils.build_dir() + '/compiled/Shaders/' full_path = arm.utils.get_fp() + '/' + rel_path if not os.path.exists(full_path): os.makedirs(full_path) make_instancing_and_skinning(material, mat_users) bind_constants = dict() bind_textures = dict() for rp in rpasses: car = [] bind_constants[rp] = car mat_state.bind_constants = car tar = [] bind_textures[rp] = tar mat_state.bind_textures = tar con = None if rpdat.rp_driver != 'Armory' and arm.api.drivers[ rpdat.rp_driver]['make_rpass'] is not None: con = arm.api.drivers[rpdat.rp_driver]['make_rpass'](rp) if con is not None: pass elif rp == 'mesh': con = make_mesh.make(rp, rpasses) elif rp == 'shadowmap': con = make_depth.make(rp, rpasses, shadowmap=True) elif rp == 'translucent': con = make_transluc.make(rp) elif rp == 'overlay': con = make_overlay.make(rp) elif rp == 'decal': con = make_decal.make(rp) elif rp == 'depth': con = make_depth.make(rp, rpasses) elif rp == 'voxel': con = make_voxel.make(rp) elif rpass_hook is not None: con = rpass_hook(rp) write_shaders(rel_path, con, rp, matname) shader_data_name = matname + '_data' if wrd.arm_single_data_file: if 'shader_datas' not in arm.exporter.current_output: arm.exporter.current_output['shader_datas'] = [] arm.exporter.current_output['shader_datas'].append( mat_state.data.get()['shader_datas'][0]) else: arm.utils.write_arm(full_path + '/' + matname + '_data.arm', mat_state.data.get()) shader_data_path = arm.utils.get_fp_build( ) + '/compiled/Shaders/' + shader_data_name + '.arm' assets.add_shader_data(shader_data_path) return rpasses, mat_state.data, shader_data_name, bind_constants, bind_textures