def make_bind_target(stage, node_group, node, constant_name, currentNode=None, target_index=1): if currentNode == None: currentNode = node stage['command'] = 'bind_target' link = nodes.find_link(node_group, currentNode, currentNode.inputs[target_index]) currentNode = link.from_node if currentNode.bl_idname == 'NodeReroute': make_bind_target(stage, node_group, node, constant_name, currentNode=currentNode, target_index=0) elif currentNode.bl_idname == 'GBufferNodeType': for i in range(0, 5): if currentNode.inputs[i].is_linked: targetNode = nodes.find_node_by_link(node_group, currentNode, currentNode.inputs[i]) targetId = targetNode.inputs[0].default_value # if i == 0 and targetNode.inputs[3].default_value == True: # Depth if targetNode.inputs[3].is_linked: # Depth db_node = nodes.find_node_by_link(node_group, targetNode, targetNode.inputs[3]) db_id = db_node.inputs[0].default_value stage['params'].append('_' + db_id) stage['params'].append(constant_name + 'D') stage['params'].append(targetId) # Color buffer stage['params'].append(constant_name + str(i)) elif currentNode.bl_idname == 'TargetNodeType' or currentNode.bl_idname == 'ImageNodeType' or currentNode.bl_idname == 'Image3DNodeType': targetId = currentNode.inputs[0].default_value stage['params'].append(targetId) stage['params'].append(constant_name) elif currentNode.bl_idname == 'ShadowMapNodeType': targetId = currentNode.inputs[0].default_value stage['params'].append(targetId) stage['params'].append(constant_name) elif currentNode.bl_idname == 'DepthBufferNodeType': targetId = '_' + currentNode.inputs[0].default_value stage['params'].append(targetId) stage['params'].append(constant_name)
def parse_surface(world, node, context): wrd = bpy.data.worlds['Arm'] # Extract environment strength if node.type == 'BACKGROUND': # Append irradiance define if wrd.generate_irradiance: bpy.data.worlds['Arm'].world_defs += '_Irr' # Strength envmap_strength_const = {} envmap_strength_const['name'] = 'envmapStrength' envmap_strength_const['float'] = node.inputs[1].default_value # Always append for now, even though envmapStrength is not always needed context['bind_constants'].append(envmap_strength_const) if node.inputs[0].is_linked: color_node = nodes.find_node_by_link(world.node_tree, node, node.inputs[0]) parse_color(world, color_node, context, envmap_strength_const) # Cache results world.world_envtex_color = node.inputs[0].default_value world.world_envtex_strength = envmap_strength_const['float']
def make_set_target(stage, node_group, node, currentNode=None, target_index=1, viewport_scale=1.0): if currentNode == None: currentNode = node stage['command'] = 'set_target' # First param is viewport scale if len(stage['params']) == 0: stage['params'].append(viewport_scale) currentNode = nodes.find_node_by_link(node_group, currentNode, currentNode.inputs[target_index]) if currentNode.bl_idname == 'TargetNodeType' or currentNode.bl_idname == 'ShadowMapNodeType': targetId = currentNode.inputs[0].default_value stage['params'].append(targetId) # Store current target size buildNode.last_set_target_w = currentNode.inputs[1].default_value buildNode.last_set_target_h = currentNode.inputs[2].default_value elif currentNode.bl_idname == 'GBufferNodeType': # Set all linked targets for i in range(0, 5): if currentNode.inputs[i].is_linked: make_set_target(stage, node_group, node, currentNode, target_index=i) elif currentNode.bl_idname == 'NodeReroute': make_set_target(stage, node_group, node, currentNode, target_index=0) else: # Framebuffer targetId = '' stage['params'].append(targetId)
def buildNode(node_group, node, f, created_nodes): # Get node name name = "_" + node.name.replace(".", "_").replace(" ", "") # Check if node already exists for n in created_nodes: if n == name: return name # Create node type = node.name.split(".")[0].replace(" ", "") + "Node" f.write("\t\tvar " + name + " = new " + type + "();\n") created_nodes.append(name) # Properties if hasattr(node, "property0"): f.write("\t\t" + name + '.property0 = "' + node.property0 + '";\n') if hasattr(node, "property1"): f.write("\t\t" + name + '.property1 = "' + node.property1 + '";\n') if hasattr(node, "property2"): f.write("\t\t" + name + '.property2 = "' + node.property2 + '";\n') if hasattr(node, "property3"): f.write("\t\t" + name + '.property3 = "' + node.property3 + '";\n') if hasattr(node, "property4"): f.write("\t\t" + name + '.property4 = "' + node.property4 + '";\n') # Create inputs for inp in node.inputs: # Is linked - find node inpname = "" if inp.is_linked: n = nodes.find_node_by_link(node_group, node, inp) inpname = buildNode(node_group, n, f, created_nodes) # Not linked - create node with default values else: inpname = build_default_node(inp) # Add input f.write("\t\t" + name + ".inputs.push(" + inpname + ");\n") return name
def buildNode(node_group, node, f, created_nodes): # Get node name name = '_' + node.name.replace('.', '_').replace(' ', '') # Check if node already exists for n in created_nodes: if n == name: return name # Create node type = node.name.split(".")[0].replace(' ', '') + "Node" f.write('\t\tvar ' + name + ' = new ' + type + '(this);\n') created_nodes.append(name) # Properties if hasattr(node, "property0"): f.write('\t\t' + name + '.property0 = "' + node.property0 + '";\n') if hasattr(node, "property1"): f.write('\t\t' + name + '.property1 = "' + node.property1 + '";\n') if hasattr(node, "property2"): f.write('\t\t' + name + '.property2 = "' + node.property2 + '";\n') if hasattr(node, "property3"): f.write('\t\t' + name + '.property3 = "' + node.property3 + '";\n') if hasattr(node, "property4"): f.write('\t\t' + name + '.property4 = "' + node.property4 + '";\n') # Create inputs for inp in node.inputs: # Is linked - find node inpname = '' if inp.is_linked: n = nodes.find_node_by_link(node_group, node, inp) inpname = buildNode(node_group, n, f, created_nodes) # Not linked - create node with default values else: inpname = build_default_node(inp) # Add input f.write('\t\t' + name + '.addInput(' + inpname + ');\n') return name
def parse_world_output(world, node, context): if node.inputs[0].is_linked: surface_node = nodes.find_node_by_link(world.node_tree, node, node.inputs[0]) parse_surface(world, surface_node, context)
def parse_render_target(node, node_group, render_targets, depth_buffers): if node.bl_idname == 'NodeReroute': tnode = nodes.find_node_by_link(node_group, node, node.inputs[0]) parse_render_target(tnode, node_group, render_targets, depth_buffers) elif node.bl_idname == 'TargetNodeType' or node.bl_idname == 'ShadowMapNodeType': # Target already exists id = node.inputs[0].default_value for t in render_targets: if t['name'] == id: return depth_buffer_id = None if node.bl_idname == 'TargetNodeType' and node.inputs[3].is_linked: # Find depth buffer depth_node = nodes.find_node_by_link(node_group, node, node.inputs[3]) depth_buffer_id = depth_node.inputs[0].default_value # Append depth buffer found = False for db in depth_buffers: if db['name'] == depth_buffer_id: found = True break if found == False: db = {} db['name'] = depth_buffer_id db['stencil_buffer'] = depth_node.inputs[1].default_value depth_buffers.append(db) # Get scale scale = 1.0 if node.inputs[1].is_linked: size_node = nodes.find_node_by_link(node_group, node, node.inputs[1]) while size_node.bl_idname == 'NodeReroute': # Step through reroutes size_node = nodes.find_node_by_link(node_group, size_node, size_node.inputs[0]) scale = size_node.inputs[0].default_value # Append target if node.bl_idname == 'TargetNodeType': target = make_render_target(node, scale, depth_buffer_id=depth_buffer_id) render_targets.append(target) else: # ShadowMapNodeType target = make_shadowmap_target(node, scale) render_targets.append(target) # Second shadowmap for point lamps # TODO: check if lamp users are visible for lamp in bpy.data.lamps: if lamp.type == 'POINT': # target = make_shadowmap_target(node, scale, '2') # render_targets.append(target) # break # Clamp omni-shadows, remove if lamp.lamp_omni_shadows: bpy.data.worlds['Arm'].rp_defs += '_Clampstc' elif node.bl_idname == 'ImageNodeType' or node.bl_idname == 'Image3DNodeType': # Target already exists id = node.inputs[0].default_value for t in render_targets: if t['name'] == id: return # Get scale scale = 1.0 if node.inputs[1].is_linked: size_node = nodes.find_node_by_link(node_group, node, node.inputs[1]) while size_node.bl_idname == 'NodeReroute': # Step through reroutes size_node = nodes.find_node_by_link(node_group, size_node, size_node.inputs[0]) scale = size_node.inputs[0].default_value if node.bl_idname == 'ImageNodeType': target = make_image_target(node, scale) else: target = make_image3d_target(node, scale) render_targets.append(target) elif node.bl_idname == 'GBufferNodeType': for i in range(0, 5): if node.inputs[i].is_linked: n = nodes.find_node_by_link(node_group, node, node.inputs[i]) parse_render_target(n, node_group, render_targets, depth_buffers)
def traverse_renderpath(node, node_group, render_targets, depth_buffers): # Gather linked draw geometry contexts if node.bl_idname == 'DrawMeshesNodeType': if build_node_tree.cam.renderpath_passes != '': build_node_tree.cam.renderpath_passes += '_' # Separator build_node_tree.cam.renderpath_passes += node.inputs[1].default_value # Gather defs from linked nodes if node.bl_idname == 'TAAPassNodeType' or node.bl_idname == 'MotionBlurVelocityPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType': if preprocess_renderpath.velocity_def_added == False: assets.add_khafile_def('arm_veloc') bpy.data.worlds['Arm'].rp_defs += '_Veloc' preprocess_renderpath.velocity_def_added = True if node.bl_idname == 'TAAPassNodeType': assets.add_khafile_def('arm_taa') # bpy.data.worlds['Arm'].rp_defs += '_TAA' elif node.bl_idname == 'SMAAPassNodeType': bpy.data.worlds['Arm'].rp_defs += '_SMAA' elif node.bl_idname == 'SSAOPassNodeType' or node.bl_idname == 'ApplySSAOPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType': if bpy.data.worlds['Arm'].generate_ssao: # SSAO enabled bpy.data.worlds['Arm'].rp_defs += '_SSAO' elif node.bl_idname == 'DrawStereoNodeType': assets.add_khafile_def('arm_vr') bpy.data.worlds['Arm'].rp_defs += '_VR' elif node.bl_idname == 'CallFunctionNodeType': global dynRes_added fstr = node.inputs[1].default_value if not dynRes_added and fstr.startswith( 'armory.renderpath.DynamicResolutionScale'): bpy.data.worlds['Arm'].rp_defs += '_DynRes' dynRes_added = True # Collect render targets if node.bl_idname == 'SetTargetNodeType' or node.bl_idname == 'BindTargetNodeType' or node.bl_idname == 'QuadPassNodeType' or node.bl_idname == 'DrawCompositorNodeType' or node.bl_idname == 'DrawCompositorWithFXAANodeType': if node.inputs[1].is_linked: tnode = nodes.find_node_by_link(node_group, node, node.inputs[1]) parse_render_target(tnode, node_group, render_targets, depth_buffers) # Traverse loops elif node.bl_idname == 'LoopStagesNodeType' or node.bl_idname == 'LoopLampsNodeType' or node.bl_idname == 'DrawStereoNodeType': if node.outputs[1].is_linked: loop_node = nodes.find_node_by_link_from(node_group, node, node.outputs[1]) traverse_renderpath(loop_node, node_group, render_targets, depth_buffers) # Prebuilt elif node.bl_idname == 'MotionBlurPassNodeType' or node.bl_idname == 'MotionBlurVelocityPassNodeType' or node.bl_idname == 'CopyPassNodeType' or node.bl_idname == 'BlendPassNodeType' or node.bl_idname == 'CombinePassNodeType' or node.bl_idname == 'DebugNormalsPassNodeType' or node.bl_idname == 'FXAAPassNodeType' or node.bl_idname == 'TAAPassNodeType' or node.bl_idname == 'WaterPassNodeType' or node.bl_idname == 'DeferredLightPassNodeType' or node.bl_idname == 'DeferredIndirectPassNodeType' or node.bl_idname == 'VolumetricLightPassNodeType' or node.bl_idname == 'TranslucentResolvePassNodeType': if node.inputs[1].is_linked: tnode = nodes.find_node_by_link(node_group, node, node.inputs[1]) parse_render_target(tnode, node_group, render_targets, depth_buffers) elif node.bl_idname == 'SSRPassNodeType' or node.bl_idname == 'ApplySSAOPassNodeType' or node.bl_idname == 'BloomPassNodeType' or node.bl_idname == 'SMAAPassNodeType': for i in range(1, 4): if node.inputs[i].is_linked: tnode = nodes.find_node_by_link(node_group, node, node.inputs[i]) parse_render_target(tnode, node_group, render_targets, depth_buffers) elif node.bl_idname == 'SSAOPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType' or node.bl_idname == 'SSSPassNodeType' or node.bl_idname == 'BlurBasicPassNodeType': for i in range(1, 3): if node.inputs[i].is_linked: tnode = nodes.find_node_by_link(node_group, node, node.inputs[i]) parse_render_target(tnode, node_group, render_targets, depth_buffers) # Next stage if node.outputs[0].is_linked: stagenode = nodes.find_node_by_link_from(node_group, node, node.outputs[0]) traverse_renderpath(stagenode, node_group, render_targets, depth_buffers)
def parse_render_target(node, node_group, render_targets, depth_buffers): if node.bl_idname == 'NodeReroute': tnode = nodes.find_node_by_link(node_group, node, node.inputs[0]) parse_render_target(tnode, node_group, render_targets, depth_buffers) elif node.bl_idname == 'TargetNodeType' or node.bl_idname == 'ShadowMapNodeType': # Target already exists id = node.inputs[0].default_value for t in render_targets: if t['name'] == id: return depth_buffer_id = None if node.bl_idname == 'TargetNodeType' and node.inputs[3].is_linked: # Find depth buffer depth_node = nodes.find_node_by_link(node_group, node, node.inputs[3]) depth_buffer_id = depth_node.inputs[0].default_value # Append depth buffer found = False for db in depth_buffers: if db['name'] == depth_buffer_id: found = True break if found == False: db = {} db['name'] = depth_buffer_id db['stencil_buffer'] = depth_node.inputs[1].default_value depth_buffers.append(db) # Get scale scale = 1.0 if node.inputs[1].is_linked: size_node = nodes.find_node_by_link(node_group, node, node.inputs[1]) while size_node.bl_idname == 'NodeReroute': # Step through reroutes size_node = nodes.find_node_by_link(node_group, size_node, size_node.inputs[0]) scale = size_node.inputs[0].default_value # Append target if node.bl_idname == 'TargetNodeType': target = make_render_target(node, scale, depth_buffer_id=depth_buffer_id) render_targets.append(target) else: # ShadowMapNodeType target = make_shadowmap_target(node, scale) render_targets.append(target) # Second shadowmap for point lamps # TODO: check if lamp users are visible for lamp in bpy.data.lamps: if lamp.type == 'POINT': # target = make_shadowmap_target(node, scale, '2') # render_targets.append(target) # break # Clamp omni-shadows, remove if lamp.lamp_omni_shadows: bpy.data.worlds['Arm'].world_defs += '_Clampstc' elif node.bl_idname == 'ImageNodeType' or node.bl_idname == 'Image3DNodeType': # Target already exists id = node.inputs[0].default_value for t in render_targets: if t['name'] == id: return # Get scale scale = 1.0 if node.inputs[1].is_linked: size_node = nodes.find_node_by_link(node_group, node, node.inputs[1]) while size_node.bl_idname == 'NodeReroute': # Step through reroutes size_node = nodes.find_node_by_link(node_group, size_node, size_node.inputs[0]) scale = size_node.inputs[0].default_value if node.bl_idname == 'ImageNodeType': target = make_image_target(node, scale) else: target = make_image3d_target(node, scale) render_targets.append(target) elif node.bl_idname == 'GBufferNodeType': for i in range(0, 5): if node.inputs[i].is_linked: n = nodes.find_node_by_link(node_group, node, node.inputs[i]) parse_render_target(n, node_group, render_targets, depth_buffers)
def traverse_renderpath(node, node_group, render_targets, depth_buffers): # Gather linked draw geometry contexts if node.bl_idname == 'DrawMeshesNodeType': if build_node_tree.cam.renderpath_passes != '': build_node_tree.cam.renderpath_passes += '_' # Separator build_node_tree.cam.renderpath_passes += node.inputs[1].default_value # Gather defs from linked nodes if node.bl_idname == 'TAAPassNodeType' or node.bl_idname == 'MotionBlurVelocityPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType': if preprocess_renderpath.velocity_def_added == False: assets.add_khafile_def('arm_veloc') bpy.data.worlds['Arm'].world_defs += '_Veloc' preprocess_renderpath.velocity_def_added = True if node.bl_idname == 'TAAPassNodeType': assets.add_khafile_def('arm_taa') # bpy.data.worlds['Arm'].world_defs += '_TAA' elif node.bl_idname == 'SMAAPassNodeType': bpy.data.worlds['Arm'].world_defs += '_SMAA' elif node.bl_idname == 'SSAOPassNodeType' or node.bl_idname == 'ApplySSAOPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType': if bpy.data.worlds['Arm'].generate_ssao: # SSAO enabled bpy.data.worlds['Arm'].world_defs += '_SSAO' elif node.bl_idname == 'DrawStereoNodeType': assets.add_khafile_def('arm_vr') bpy.data.worlds['Arm'].world_defs += '_VR' elif node.bl_idname == 'CallFunctionNodeType': global dynRes_added fstr = node.inputs[1].default_value if not dynRes_added and fstr.startswith('armory.renderpath.DynamicResolutionScale'): bpy.data.worlds['Arm'].world_defs += '_DynRes' dynRes_added = True # Collect render targets if node.bl_idname == 'SetTargetNodeType' or node.bl_idname == 'BindTargetNodeType' or node.bl_idname == 'QuadPassNodeType' or node.bl_idname == 'DrawCompositorNodeType' or node.bl_idname == 'DrawCompositorWithFXAANodeType': if node.inputs[1].is_linked: tnode = nodes.find_node_by_link(node_group, node, node.inputs[1]) parse_render_target(tnode, node_group, render_targets, depth_buffers) # Traverse loops elif node.bl_idname == 'LoopStagesNodeType' or node.bl_idname == 'LoopLampsNodeType' or node.bl_idname == 'DrawStereoNodeType': if node.outputs[1].is_linked: loop_node = nodes.find_node_by_link_from(node_group, node, node.outputs[1]) traverse_renderpath(loop_node, node_group, render_targets, depth_buffers) # Prebuilt elif node.bl_idname == 'MotionBlurPassNodeType' or node.bl_idname == 'MotionBlurVelocityPassNodeType' or node.bl_idname == 'CopyPassNodeType' or node.bl_idname == 'BlendPassNodeType' or node.bl_idname == 'CombinePassNodeType' or node.bl_idname == 'DebugNormalsPassNodeType' or node.bl_idname == 'FXAAPassNodeType' or node.bl_idname == 'TAAPassNodeType' or node.bl_idname == 'WaterPassNodeType' or node.bl_idname == 'DeferredLightPassNodeType' or node.bl_idname == 'DeferredIndirectPassNodeType' or node.bl_idname == 'VolumetricLightPassNodeType' or node.bl_idname == 'TranslucentResolvePassNodeType': if node.inputs[1].is_linked: tnode = nodes.find_node_by_link(node_group, node, node.inputs[1]) parse_render_target(tnode, node_group, render_targets, depth_buffers) elif node.bl_idname == 'SSRPassNodeType' or node.bl_idname == 'ApplySSAOPassNodeType' or node.bl_idname == 'BloomPassNodeType' or node.bl_idname == 'SMAAPassNodeType': for i in range(1, 4): if node.inputs[i].is_linked: tnode = nodes.find_node_by_link(node_group, node, node.inputs[i]) parse_render_target(tnode, node_group, render_targets, depth_buffers) elif node.bl_idname == 'SSAOPassNodeType' or node.bl_idname == 'SSAOReprojectPassNodeType' or node.bl_idname == 'SSSPassNodeType' or node.bl_idname == 'BlurBasicPassNodeType': for i in range(1, 3): if node.inputs[i].is_linked: tnode = nodes.find_node_by_link(node_group, node, node.inputs[i]) parse_render_target(tnode, node_group, render_targets, depth_buffers) # Next stage if node.outputs[0].is_linked: stagenode = nodes.find_node_by_link_from(node_group, node, node.outputs[0]) traverse_renderpath(stagenode, node_group, render_targets, depth_buffers)