Nodes/ComfyUI Field/Field Composite
ComfyUI Node

Field Composite

Make Any Effect Follow a Mask Instead of the Whole Frame

By jeremieLouvaert·Created 3 months ago·Updated 24 days ago· 1
Field Composite
  • base
  • effect
  • field
  • image
  • resolved_mask
◄strength1.00►
◄invert_fieldfalse►

The node that leaves mask-land

Field Composite is the one node in this pack that works on IMAGE instead of MASK, and that's the whole point. Everything else in ComfyUI-Field produces or reshapes a field; this one spends it. You feed it two images and a mask, and it dissolves one into the other wherever the mask is bright.

It's the pack's retrofit node, in the author's word. You already have an effect you like - a grungy color grade, a heavy upscale, a different checkpoint blowing out the highlights, a sharpened pass - and it's currently applying to the entire frame. Field Composite is how you tell it to apply there, and not over the face.

Why not just ImageCompositeMasked?

You can, and for paste-a-crop-back-onto-a-canvas work you should. But ImageCompositeMasked is a composite of two images with an optional mask, and its mental model is "cut out and place". Field Composite is a straight per-pixel dissolve between a base and an effect, mask-weighted, and its model is "opacity". Different job, different feel. It's the difference between lassoing a region in Photoshop and painting on a layer mask.

The other reason is that this is the terminal node for a long field chain. Once you've built a mask from Perlin noise, edges, distance falloff, local detail, thresholded and morphed it, you want somewhere to spend it that isn't a diffusion mask. This is that.

How it blends

The math is blunt and documented:

m   = clamp(field * strength, 0, 1)   # inverted first if you asked
out = (1 - m) * base + m * effect

That specific arrangement - rather than the textbook base + (effect - base) * m - exists because the usual form isn't float32-exact at m = 1. With base = 1.0 and a very dark effect, effect - base rounds to exactly -1.0, the product annihilates the effect value, and you get 0.0 where you should get the effect pixel. A blown highlight over a crushed shadow reaches that with real photos. The pack's tests check it with an adversarial grid rather than random data, which is why it's fixed here and not in most nodes you've used.

Blending happens in the incoming display-referred space with no colour conversion - the same convention Photoshop, Nuke and ComfyUI's own ImageCompositeMasked use for opacity. So "mask the highlights" means the bright-looking pixels, not the mathematically bright ones.

Inputs and outputs you'll actually touch

  • base and effect - IMAGE. Base is what stays where the mask is dark; effect is what shows where it's bright.
  • field - MASK. Your field.
  • strength - 0 to 1, default 1. A global multiplier on the mask before the blend; turn it down to make the effect subtle everywhere.
  • invert_field - flips the mask, which is quicker than rebuilding it backwards.

Outputs are image and resolved_mask. Wire image to Save Image or the rest of your chain. resolved_mask is the mask actually used after inversion, strength and any resize - it costs nothing to emit, and it's the thing to preview when the result looks wrong. If resolved_mask doesn't look like what you expected, the problem is upstream of this node; if it looks right and the image still doesn't, the problem is your effect image.

Install

ComfyUI Manager → search ComfyUI Field, or:

cd ComfyUI/custom_nodes
git clone https://github.com/jeremieLouvaert/ComfyUI-Field

Restart. No model downloads, no dependencies beyond the torch ComfyUI already has. You'll find it under AKURATE/Fields/Combine.

Traps

The resize note. If the field's resolution doesn't match the image's, the field is resized bilinearly and the console prints a note. The failure mode that causes is a mask that looks correct in isolation and lands half a tile off on the image - so build fields from a reference_image when you can (Field Noise, Gradient, Shape, Tile and Scatter all accept one), and they'll match automatically.

A batch-1 field broadcasts over a batch-N image, which is usually what you want and occasionally isn't: same mask on every frame.

And the classic opacity confusion - if the output is indistinguishable from effect, your field is nearly all white. Check resolved_mask before you start swapping wires. If it's all black instead, you probably forgot invert_field.

CategoryAKURATE/Fields/Combine

Inputs (5)

NameTypeDefaultDescription
baseIMAGE—
effectIMAGE—
fieldMASK—
strengthFLOAT1.000–1—
invert_fieldBOOLEANfalse—

Outputs (2)

NameTypeDescription
imageIMAGE—
resolved_maskMASK—