Nodes/BV Node Pack/πŸŒ€ BV LUT Loop Start
ComfyUI Node

πŸŒ€ BV LUT Loop Start

The kickoff for a chain of grades

By BlackVortexAIΒ·Created 8 months agoΒ·Updated a day agoΒ· 6
πŸŒ€ BV LUT Loop Start
  • plan
  • initial_image
  • resource_provider_1
  • resource_provider_2
  • resource_provider_3
  • resource_provider_4
  • resource_provider_5
  • resource_provider_6
  • resource_provider_7
  • resource_provider_8
  • resource_provider_9
  • resource_provider_10
  • resource_provider_11
  • resource_provider_12
  • resource_provider_13
  • resource_provider_14
  • resource_provider_15
  • resource_provider_16
  • resource_provider_17
  • resource_provider_18
  • resource_provider_19
  • resource_provider_20
  • resource_provider_21
  • resource_provider_22
  • resource_provider_23
  • resource_provider_24
  • resource_provider_25
  • resource_provider_26
  • resource_provider_27
  • resource_provider_28
  • resource_provider_29
  • resource_provider_30
  • resource_provider_31
  • resource_provider_32
  • resource_provider_33
  • resource_provider_34
  • resource_provider_35
  • resource_provider_36
  • resource_provider_37
  • resource_provider_38
  • resource_provider_39
  • resource_provider_40
  • flow
  • loop_state

Most LUT workflows are one look on one image, and for those you don't need this node. But the interesting case is a sequence of grades - a hero look, then a sky look on top, then a vignette - where each step's mask is computed from the previous step's output. ComfyUI has no native loop construct, so BV Node Pack builds one out of graph expansion, and BV LUT Loop Start is where that loop begins.

It takes a plan (an ordered list of LUT jobs), grabs the starting image, and initializes the loop's accumulator and job counter. Everything after it - the resolver that tells you what the current job is, the Apply LUT that does the work, the Loop End that feeds the result back in - runs in a controlled loop until the plan is exhausted.

How it works

Two inputs do the real work: plan and initial_image. The plan input is deliberately typed as * (anything), because it accepts two different shapes:

  • A raw BV_LUT_PLAN - the output of BV LUT Job chains or BV Regional LUT Plan.
  • A BV_REGIONAL context - in which case the node materializes the LUT plan itself from the regional capabilities plus whatever LUT resource providers you hand it (that's what the 40 optional resource_provider_1…resource_provider_40 inputs are for).

Internally it builds the loop state - a BV_LUT_LOOP_STATE holding the plan, the current accumulated image, and a job index - then expands into an invisible BV LUT While Start (Prototype internal) node so the loop can actually re-run in ComfyUI's execution model. You never see that scaffolding; you just see flow and loop_state outputs.

If you hand it an empty plan, it doesn't crash - it substitutes a single Identity LUT job at strength 0, which is a graceful "pass the image through unchanged" fallback.

The inputs and outputs that matter

  • plan - the job list. From BV Regional LUT Plan if your grades come from regions, or from chained BV LUT Job nodes for a manual list.
  • initial_image - the IMAGE the first job starts from. Usually your decoded latent or the output of the previous processing stage.
  • Outputs: flow (a FLOW_CONTROL signal) and loop_state - the latter is what feeds the resolver and eventually Loop End.

That 40-slot provider array looks intimidating but it's just capacity: the regional resource protocol allows up to 40 LUT providers in a graph, and you'll typically wire one or two.

How to install

Part of BV Node Pack, installed as a pack:

cd ComfyUI/custom_nodes
git clone https://github.com/BlackVortexAI/bv_nodepack.git

Restart ComfyUI, hard-refresh the browser (or install via ComfyUI Manager β†’ "BV Node Pack"). No model downloads.

Common issues

  • "plan must be a version 1 BV LUT prototype plan" - you fed it something that isn't a valid plan or a regional context. Check that a BV Regional LUT Plan or BV LUT Job actually produced the plan, and that its jobs have lut, strength, and mask_invert fields.
  • "requires IMAGE shaped B,H,W,C" - initial_image is missing or a non-image type.
  • Loop runs fewer/more iterations than expected - the loop ends when the job index hits the plan length. If the plan has one job, you get exactly one pass; if you expected stacked looks, you need more jobs in the plan.

For a single look you don't want this at all - BV Apply LUT alone is the right tool. You reach for the loop when later looks genuinely depend on earlier ones.

CategoryπŸŒ€ BV Node Pack/regional/LUT

Inputs (42)

NameTypeDefaultDescription
plan*β€”
initial_imageIMAGEβ€”
resource_provider_1optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_2optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_3optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_4optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_5optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_6optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_7optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_8optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_9optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_10optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_11optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_12optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_13optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_14optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_15optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_16optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_17optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_18optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_19optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_20optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_21optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_22optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_23optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_24optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_25optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_26optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_27optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_28optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_29optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_30optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_31optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_32optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_33optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_34optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_35optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_36optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_37optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_38optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_39optBV_RUNTIME_RESOURCE_PROVIDERβ€”
resource_provider_40optBV_RUNTIME_RESOURCE_PROVIDERβ€”

Outputs (2)

NameTypeDescription
flowFLOW_CONTROLβ€”
loop_stateBV_LUT_LOOP_STATEβ€”