Example #1
0
def process_call_function(stage, stages, node, node_group):
    # Step till merge node
    stage['returns_true'] = []
    if node.outputs[0].is_linked:
        stageNode = nodes.find_node_by_link_from(node_group, node, node.outputs[0])
        buildNode(stage['returns_true'], stageNode, node_group)
    
    stage['returns_false'] = []
    if node.outputs[1].is_linked:
        stageNode = nodes.find_node_by_link_from(node_group, node, node.outputs[1])
        margeNode = buildNode(stage['returns_false'], stageNode, node_group)
    
    # Continue using top level stages after merge node
    afterMergeNode = nodes.find_node_by_link_from(node_group, margeNode, margeNode.outputs[0])
    buildNode(stages, afterMergeNode, node_group)
Example #2
0
def process_call_function(stage, stages, node, node_group):
    # Step till merge node
    stage['returns_true'] = []
    if node.outputs[0].is_linked:
        stageNode = nodes.find_node_by_link_from(node_group, node,
                                                 node.outputs[0])
        buildNode(stage['returns_true'], stageNode, node_group)

    stage['returns_false'] = []
    margeNode = None
    if node.outputs[1].is_linked:
        stageNode = nodes.find_node_by_link_from(node_group, node,
                                                 node.outputs[1])
        margeNode = buildNode(stage['returns_false'], stageNode, node_group)

    # Continue using top level stages after merge node
    if margeNode != None:
        afterMergeNode = nodes.find_node_by_link_from(node_group, margeNode,
                                                      margeNode.outputs[0])
        buildNode(stages, afterMergeNode, node_group)
Example #3
0
def get_root_node(node_group):
    # Find first node linked to begin node
    rn = None
    for n in node_group.nodes:
        if n.bl_idname == 'BeginNodeType':
            # Store contexts
            build_node_tree.cam.renderpath_id = n.inputs[0].default_value
            # TODO: deprecated
            if len(n.inputs) > 5:
                if n.inputs[5].default_value == False:
                    bpy.data.worlds['Arm'].rp_defs += '_LDR'
            else:
                if n.inputs[1].default_value == False:
                    bpy.data.worlds['Arm'].rp_defs += '_LDR'

            rn = nodes.find_node_by_link_from(node_group, n, n.outputs[0])
            break
    return rn
Example #4
0
def get_root_node(node_group):
    # Find first node linked to begin node
    rn = None
    for n in node_group.nodes:
        if n.bl_idname == 'BeginNodeType':
            # Store contexts
            build_node_tree.cam.renderpath_id = n.inputs[0].default_value            
            # TODO: deprecated
            if len(n.inputs) > 5:
                if n.inputs[5].default_value == False:
                    bpy.data.worlds['Arm'].world_defs += '_LDR'
            else:
                if n.inputs[1].default_value == False:
                    bpy.data.worlds['Arm'].world_defs += '_LDR'
            
            rn = nodes.find_node_by_link_from(node_group, n, n.outputs[0])
            break
    return rn
Example #5
0
def buildNode(stages, node, node_group):
    stage = {}
    stage['params'] = []

    append_stage = True

    if node.bl_idname == 'MergeStagesNodeType':
        return node

    elif node.bl_idname == 'SetTargetNodeType':
        buildNode.last_bind_target = None
        make_set_target(stage, node_group, node)

    elif node.bl_idname == 'SetViewportNodeType':
        make_set_viewport(stage, node_group, node)

    elif node.bl_idname == 'ClearTargetNodeType':
        color_val = None
        depth_val = None
        stencil_val = None
        if node.inputs[1].default_value == True:
            if node.inputs[
                    2].is_linked:  # Assume background color node is linked
                color_val = -1  # Clear to world.background_color
            else:
                color_val = node.inputs[2].default_value
        if node.inputs[3].default_value == True:
            depth_val = node.inputs[4].default_value
        if node.inputs[5].default_value == True:
            stencil_val = node.inputs[6].default_value
        make_clear_target(stage,
                          color_val=color_val,
                          depth_val=depth_val,
                          stencil_val=stencil_val)

    elif node.bl_idname == 'ClearImageNodeType':
        image_node = node.inputs[1].links[0].from_node
        image_name = image_node.inputs[0].default_value
        color_val = node.inputs[2].default_value
        make_clear_image(stage, image_name, color_val)

    elif node.bl_idname == 'GenerateMipmapsNodeType':
        make_generate_mipmaps(stage, node_group, node)

    elif node.bl_idname == 'DrawMeshesNodeType':
        make_draw_meshes(stage, node_group, node)

    elif node.bl_idname == 'DrawDecalsNodeType':
        make_draw_decals(stage, node_group, node)

    elif node.bl_idname == 'BindTargetNodeType':
        if buildNode.last_bind_target is not None:
            stage = buildNode.last_bind_target
            append_stage = False
        buildNode.last_bind_target = stage
        constant_name = node.inputs[2].default_value
        make_bind_target(stage, node_group, node, constant_name)

    elif node.bl_idname == 'DrawMaterialQuadNodeType':
        make_draw_material_quad(stage, node_group, node)

    elif node.bl_idname == 'DrawQuadNodeType':
        make_draw_quad(stage, node_group, node)

    elif node.bl_idname == 'DrawWorldNodeType':
        # Bind depth for quad
        # if node.inputs[1].is_linked:
        #     stage = {}
        #     stage['params'] = []
        #     buildNode.last_bind_target = stage
        #     if node.inputs[1].is_linked:
        #         make_bind_target(stage, node_group, node, target_index=1, constant_name='gbufferD')
        #     stages.append(stage)
        stage = {}
        stage['params'] = []
        # Draw quad
        # make_draw_world(stage, node_group, node, dome=False)
        # Draw dome
        make_draw_world(stage, node_group, node, dome=True)

    elif node.bl_idname == 'DrawCompositorNodeType' or node.bl_idname == 'DrawCompositorWithFXAANodeType':
        # Set target
        if node.inputs[1].is_linked:
            make_set_target(stage, node_group, node)
            stages.append(stage)
        # Bind targets
        if node.inputs[2].is_linked or node.inputs[3].is_linked or node.inputs[
                4].is_linked:
            stage = {}
            stage['params'] = []
            buildNode.last_bind_target = stage
            if node.inputs[2].is_linked:
                make_bind_target(stage,
                                 node_group,
                                 node,
                                 target_index=2,
                                 constant_name='tex')
            if node.inputs[3].is_linked:
                make_bind_target(stage,
                                 node_group,
                                 node,
                                 target_index=3,
                                 constant_name='gbufferD')
            if node.inputs[4].is_linked:
                make_bind_target(stage,
                                 node_group,
                                 node,
                                 target_index=4,
                                 constant_name='gbuffer0')
            stages.append(stage)
        # Draw quad
        stage = {}
        stage['params'] = []
        with_fxaa = node.bl_idname == 'DrawCompositorWithFXAANodeType'
        make_draw_compositor(stage, node_group, node, with_fxaa=with_fxaa)

    elif node.bl_idname == 'DrawGreasePencilNodeType':
        stage = {}
        stage['params'] = []
        make_draw_grease_pencil(stage, node_group, node)

    elif node.bl_idname == 'BranchFunctionNodeType':
        make_branch_function(stage, node_group, node)
        stages.append(stage)
        process_call_function(stage, stages, node, node_group)
        return

    elif node.bl_idname == 'LoopStagesNodeType':
        # Just repeats the commands
        append_stage = False
        if node.outputs[1].is_linked:
            count = node.inputs[2].default_value
            for i in range(0, count):
                loopNode = nodes.find_node_by_link_from(
                    node_group, node, node.outputs[1])
                buildNode(stages, loopNode, node_group)

    elif node.bl_idname == 'LoopLampsNodeType':
        append_stage = False
        stage['command'] = 'loop_lamps'
        stages.append(stage)
        stage['returns_true'] = []
        if node.outputs[1].is_linked:
            loopNode = nodes.find_node_by_link_from(node_group, node,
                                                    node.outputs[1])
            buildNode(stage['returns_true'], loopNode, node_group)

    elif node.bl_idname == 'DrawStereoNodeType':
        append_stage = False
        stage['command'] = 'draw_stereo'
        stages.append(stage)
        stage['returns_true'] = []
        if node.outputs[1].is_linked:
            loopNode = nodes.find_node_by_link_from(node_group, node,
                                                    node.outputs[1])
            buildNode(stage['returns_true'], loopNode, node_group)

    elif node.bl_idname == 'CallFunctionNodeType':
        make_call_function(stage, node_group, node)

    elif node.bl_idname == 'QuadPassNodeType':
        make_quad_pass(stages, node_group, node)
        append_stage = False

    elif node.bl_idname == 'SSAOPassNodeType':
        make_ssao_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'SSAOReprojectPassNodeType':
        make_ssao_reproject_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'ApplySSAOPassNodeType':
        make_apply_ssao_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'SSRPassNodeType':
        make_ssr_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'BloomPassNodeType':
        make_bloom_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'MotionBlurPassNodeType':
        make_motion_blur_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'MotionBlurVelocityPassNodeType':
        make_motion_blur_velocity_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'CopyPassNodeType':
        make_copy_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'BlendPassNodeType':
        make_blend_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'CombinePassNodeType':
        make_combine_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'BlurBasicPassNodeType':
        make_blur_basic_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'DebugNormalsPassNodeType':
        make_debug_normals_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'FXAAPassNodeType':
        make_fxaa_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'SMAAPassNodeType':
        make_smaa_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'TAAPassNodeType':
        make_taa_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'SSSPassNodeType':
        make_sss_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'WaterPassNodeType':
        make_water_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'DeferredLightPassNodeType':
        make_deferred_light_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'DeferredIndirectPassNodeType':
        make_deferred_indirect_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'VolumetricLightPassNodeType':
        make_volumetric_light_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'TranslucentResolvePassNodeType':
        make_translucent_resolve_pass(stages, node_group, node)
        append_stage = False

    if append_stage:
        stages.append(stage)

    # Build next stage
    if node.outputs[0].is_linked:
        stageNode = nodes.find_node_by_link_from(node_group, node,
                                                 node.outputs[0])
        buildNode(stages, stageNode, node_group)

    return None
Example #6
0
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)
Example #7
0
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)
Example #8
0
def buildNode(stages, node, node_group):
    stage = {}
    stage['params'] = []
    
    append_stage = True
    
    if node.bl_idname == 'MergeStagesNodeType':
        return node
    
    elif node.bl_idname == 'SetTargetNodeType':
        buildNode.last_bind_target = None
        make_set_target(stage, node_group, node)

    elif node.bl_idname == 'SetViewportNodeType':
        make_set_viewport(stage, node_group, node)

    elif node.bl_idname == 'ClearTargetNodeType':
        color_val = None
        depth_val = None
        stencil_val = None
        if node.inputs[1].default_value == True:
            if node.inputs[2].is_linked: # Assume background color node is linked
                color_val = -1 # Clear to world.background_color
            else:
                color_val = node.inputs[2].default_value
        if node.inputs[3].default_value == True:
            depth_val = node.inputs[4].default_value
        if node.inputs[5].default_value == True:
            stencil_val = node.inputs[6].default_value
        make_clear_target(stage, color_val=color_val, depth_val=depth_val, stencil_val=stencil_val)
    
    elif node.bl_idname == 'GenerateMipmapsNodeType':
        make_generate_mipmaps(stage, node_group, node)

    elif node.bl_idname == 'DrawMeshesNodeType':
        make_draw_meshes(stage, node_group, node)
        
    elif node.bl_idname == 'DrawDecalsNodeType':
        make_draw_decals(stage, node_group, node)
        
    elif node.bl_idname == 'BindTargetNodeType':
        if buildNode.last_bind_target is not None:
            stage = buildNode.last_bind_target
            append_stage = False
        buildNode.last_bind_target = stage
        constant_name = node.inputs[2].default_value
        make_bind_target(stage, node_group, node, constant_name)
        
    elif node.bl_idname == 'DrawMaterialQuadNodeType':
        make_draw_material_quad(stage, node_group, node)
        
    elif node.bl_idname == 'DrawQuadNodeType':
        make_draw_quad(stage, node_group, node)
    
    elif node.bl_idname == 'DrawWorldNodeType':
        # Bind depth for quad
        # if node.inputs[1].is_linked:
        #     stage = {}
        #     stage['params'] = []
        #     buildNode.last_bind_target = stage
        #     if node.inputs[1].is_linked:
        #         make_bind_target(stage, node_group, node, target_index=1, constant_name='gbufferD')
        #     stages.append(stage)
        stage = {}
        stage['params'] = []
        # Draw quad
        # make_draw_world(stage, node_group, node, dome=False)
        # Draw dome
        make_draw_world(stage, node_group, node, dome=True)
    
    elif node.bl_idname == 'DrawCompositorNodeType' or node.bl_idname == 'DrawCompositorWithFXAANodeType':
        # Set target
        if node.inputs[1].is_linked:
            make_set_target(stage, node_group, node)
            stages.append(stage)
        # Bind targets
        if node.inputs[2].is_linked or node.inputs[3].is_linked or node.inputs[4].is_linked:
            stage = {}
            stage['params'] = []
            buildNode.last_bind_target = stage
            if node.inputs[2].is_linked:
                make_bind_target(stage, node_group, node, target_index=2, constant_name='tex')
            if node.inputs[3].is_linked:
                make_bind_target(stage, node_group, node, target_index=3, constant_name='gbufferD')
            if node.inputs[4].is_linked:
                make_bind_target(stage, node_group, node, target_index=4, constant_name='gbuffer0')
            stages.append(stage)
        # Draw quad
        stage = {}
        stage['params'] = []
        with_fxaa = node.bl_idname == 'DrawCompositorWithFXAANodeType'
        make_draw_compositor(stage, node_group, node, with_fxaa=with_fxaa)
    
    elif node.bl_idname == 'DrawGreasePencilNodeType':
        stage = {}
        stage['params'] = []
        make_draw_grease_pencil(stage, node_group, node)

    elif node.bl_idname == 'BranchFunctionNodeType':
        make_branch_function(stage, node_group, node)
        stages.append(stage)
        process_call_function(stage, stages, node, node_group)
        return
        
    elif node.bl_idname == 'LoopStagesNodeType':
        # Just repeats the commands
        append_stage = False
        if node.outputs[1].is_linked:
            count = node.inputs[2].default_value
            for i in range(0, count):
                loopNode = nodes.find_node_by_link_from(node_group, node, node.outputs[1])
                buildNode(stages, loopNode, node_group)
    
    elif node.bl_idname == 'LoopLampsNodeType':
        append_stage = False
        stage['command'] = 'loop_lamps'
        stages.append(stage)
        stage['returns_true'] = []
        if node.outputs[1].is_linked:
            loopNode = nodes.find_node_by_link_from(node_group, node, node.outputs[1])
            buildNode(stage['returns_true'], loopNode, node_group)
    
    elif node.bl_idname == 'DrawStereoNodeType':
        append_stage = False
        stage['command'] = 'draw_stereo'
        stages.append(stage)
        stage['returns_true'] = []
        if node.outputs[1].is_linked:
            loopNode = nodes.find_node_by_link_from(node_group, node, node.outputs[1])
            buildNode(stage['returns_true'], loopNode, node_group)

    elif node.bl_idname == 'CallFunctionNodeType':
        make_call_function(stage, node_group, node)
    
    elif node.bl_idname == 'QuadPassNodeType':
        make_quad_pass(stages, node_group, node)
        append_stage = False

    elif node.bl_idname == 'SSAOPassNodeType':
        make_ssao_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'SSAOReprojectPassNodeType':
        make_ssao_reproject_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'ApplySSAOPassNodeType':
        make_apply_ssao_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'SSRPassNodeType':
        make_ssr_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'BloomPassNodeType':
        make_bloom_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'MotionBlurPassNodeType':
        make_motion_blur_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'MotionBlurVelocityPassNodeType':
        make_motion_blur_velocity_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'CopyPassNodeType':
        make_copy_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'BlendPassNodeType':
        make_blend_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'CombinePassNodeType':
        make_combine_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'BlurBasicPassNodeType':
        make_blur_basic_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'DebugNormalsPassNodeType':
        make_debug_normals_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'FXAAPassNodeType':
        make_fxaa_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'SMAAPassNodeType':
        make_smaa_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'TAAPassNodeType':
        make_taa_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'SSSPassNodeType':
        make_sss_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'WaterPassNodeType':
        make_water_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'DeferredLightPassNodeType':
        make_deferred_light_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'DeferredIndirectPassNodeType':
        make_deferred_indirect_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'VolumetricLightPassNodeType':
        make_volumetric_light_pass(stages, node_group, node)
        append_stage = False
    elif node.bl_idname == 'TranslucentResolvePassNodeType':
        make_translucent_resolve_pass(stages, node_group, node)
        append_stage = False

    if append_stage:
        stages.append(stage)
    
    # Build next stage
    if node.outputs[0].is_linked:
        stageNode = nodes.find_node_by_link_from(node_group, node, node.outputs[0])
        buildNode(stages, stageNode, node_group)