Nodes/ComfyUI Field/Field Scatter
ComfyUI Node

Field Scatter

Stamps on a Lattice, Deterministically

By jeremieLouvaert·Created 3 months ago·Updated 24 days ago· 1
Field Scatter
  • reference_image
  • reference_mask
  • fill_mask
  • mask
  • preview
◄shapecircle►
◄density8.0►
◄size0.350►
◄sides5►
◄star_ratio0.50►
◄stamp_aspect1.00►
◄rotation0►
◄rotation_jitter0.00►
◄fill1.00►
◄size_jitter0.00►
◄position_jitter0.00►
◄value_jitter0.00►
◄falloff0.000►
◄aa_width1.0►
◄seed0►
◄distributionnative►
◄coverage0.50►
◄invertfalse►
◄width512►
◄height512►
◄mask_min0.00►
◄mask_gamma1.00►

Random-looking dots that are actually a grid

Field Scatter places one shape per lattice cell - a circle, rectangle, polygon or star - with seeded jitter on position, size, rotation and value. It's the node for confetti, bokeh, dust motes, painted speckle, a field of soft lights, or a stipple mask you want to composite an effect through. And it's the deterministic kind of random: same settings, same seed, same stamps, every run, at every resolution.

That last part is the pack's whole thesis applied to scattering. density is cells across the reference dimension S = max(H, W), so cells are square at every aspect ratio - the same scatter at 512 and at 2048, just resolved more finely.

The controls worth understanding

  • shape, sides, star_ratio, stamp_aspect - the stamp geometry. stamp_aspect is rect-only and controls the native half-width, so an oblong stamp is exact rather than a stretched circle.
  • density - cells across S. Default 8. This is your "how many slots are there" control.
  • size - the stamp radius in cell units, where 1.0 is one full cell width. That's an unusually nice choice: size means the same thing whether you've got 8 cells or 40, so changing density doesn't also change how big the dots are.
  • fill - the probability any given cell is occupied. 1.0 means every cell stamped, which gives you a perfect grid rather than a scatter. Drop it to 0.4 and you get a scatter. This is the knob that makes it look random.
  • position_jitter, size_jitter, rotation_jitter, value_jitter, rotation - each jitter draws from an independent per-cell hash channel driven by seed. That independence matters: turning up size jitter never reshuffles which cells are occupied or how they're rotated. You can tune one thing without losing the arrangement you liked.
  • falloff and aa_width - the authored soft edge and the antialiasing width, exactly as on Field Shape. With falloff at 0 you get hard stamps.
  • distribution, coverage, invert, seed, width/height - the standard pack tail.

size is clamped by the 3×3-neighbourhood reach cap (a stamp can only overhang so far before it would need to read cells it doesn't have), and star_ratio is clamped to what's achievable for the chosen sides. Both cases print a console note. If your stamps look cut down from what you asked for, that's the cap, not a bug.

The optional inputs are the good stuff

  • reference_image / reference_mask - inherit H, W, batch and device. reference_mask is size-only; it supplies dimensions and never touches the scatter itself. People wire a mask here expecting it to control placement and then wonder why the dots are everywhere. It won't. Use fill_mask for that.
  • fill_mask - spatially modulates placement probability. Read once per lattice cell at the cell's centre, so effective fill = fill × (mask_min + (1 − mask_min) · m^mask_gamma). White means full fill; black means mask_min × fill.
  • mask_min - the placement floor where fill_mask is black. 0 thins to nothing; raise it to keep some stamps everywhere. Only active when fill_mask is wired.
  • mask_gamma - a contrast curve on the mask before the floor. 1.0 skips the operation entirely.

Two behaviours to know about fill_mask. Stamps land whole or not at all - edges are honoured at cell resolution, and a stamp can overhang by its own reach - so keep mask features at least two cells wide or you'll get a ragged boundary. And with distribution=uniform, the area that gets masked out is remapped to mid-grey rather than black, because the rank transform ranks the whole frame. If you need truly zero outside the region, use native.

Outputs are mask and preview.

Install

Manager → ComfyUI Field, or:

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

Restart. No models, no extra packages. Under AKURATE/Fields/Generate.

Getting burned

fill at its default of 1.0 stamps every cell, which reads as a grid, not a scatter. The first thing to do with this node is drop fill to about 0.5 and add a little position jitter - that's when it starts to look organic.

Also: when the output is provably binary (falloff 0, value_jitter 0, aa_width 0), the node forces native regardless of what distribution says. The rank transform of a two-valued image isn't useful, so the pack just refuses. If the distribution widget seems to do nothing on hard stamps, that's why.

Finally, the seed widget is only active when it matters: 0 < fill < 1, any jitter above zero, or fill_mask wired. With fill = 1 and no jitter, changing the seed genuinely does nothing, and that's by design rather than a stuck widget.

CategoryAKURATE/Fields/Generate

Inputs (25)

NameTypeDefaultDescription
shapeCOMBOcircleStamp shape, one exact SDF per cell
densityFLOAT8.01–64Lattice cells across the reference dimension S=max(H,W); square cells at every aspect (as Field Tile)
sizeFLOAT0.3500.01–2Stamp radius (rect: half-height) in CELL units -- 1.0 = one full cell width. Clamped by the 3x3-neighbourhood reach cap, with a console note, if requested too large
sidesINT53–12polygon / star point count
star_ratioFLOAT0.500.1–0.95Inner/outer radius ratio, star only. Clamped to the achievable range for `sides` (see console note)
stamp_aspectFLOAT1.000.25–4rect only. Native half-width = size*stamp_aspect (cell units); sdf_rect is natively anisotropic, no gradient correction needed
rotationFLOAT0-360–360Per-instance base rotation, degrees. Inactive on circle
rotation_jitterFLOAT0.000–1Per-cell rotation offset, fraction of a full turn. Inactive on circle
fillFLOAT1.000–1Probability a given cell is occupied. 0 = empty, 1 = every cell stamped
size_jitterFLOAT0.000–1Per-cell size reduction (shrink only), fraction of `size`
position_jitterFLOAT0.000–1Per-cell centre offset, fraction of the cell's half-width
value_jitterFLOAT0.000–1Per-cell output-value reduction, fraction of full strength (1.0). Applied after the falloff quintic
falloffFLOAT0.0000–1Authored soft edge width, fraction of S. 0 = hard
aa_widthFLOAT1.00–4Antialias width, pixels. Active when falloff is <= one pixel
seedINT00–4294967295Active when 0 < fill < 1, any jitter > 0, or fill_mask is wired
distributionCOMBOnativenative: raw combined output. uniform: PIT-normalised against this field's own probe grid. Forced native when the configured output is provably binary (falloff=0, value_jitter=0, aa_width=0)
coverageFLOAT0.500–1Fraction of the frame above the midpoint
invertBOOLEANfalseFlip the output
widthINT51216–8192Output width, ignored if a reference is wired
heightINT51216–8192Output height, ignored if a reference is wired
reference_imageoptIMAGEIf wired, H/W/B and device come from this and the manual width/height widgets are ignored
reference_maskoptMASKAs reference_image, lower priority if both are wired. SIZE-ONLY: supplies H/W/batch/device and never touches the field -- use fill_mask to modulate placement.
fill_maskoptMASKSpatially modulates PLACEMENT probability: effective fill = fill × (mask_min + (1−mask_min)·m^mask_gamma), read once per lattice cell at the cell's centre. White = full fill, black = mask_min×fill (0 = no stamps). Stamps land whole or not at all: edges are honoured at cell resolution and stamps can overhang by their own reach -- keep mask features at least two cells wide. With distribution=uniform the masked-out area is remapped to a mid-grey, not black (the PIT ranks the whole frame). Frame 0 used for batches. NOT the same as reference_mask, which only supplies size/batch/device.
mask_minoptFLOAT0.000–1Placement floor where fill_mask is black. 0 = thin out to nothing; raise it to keep some stamps everywhere (the slice-3 floor-not-gate taste). Only active when fill_mask is wired.
mask_gammaoptFLOAT1.000.25–4Contrast curve on fill_mask before the floor. 1.0 = linear (skips the op entirely); >1 pulls feathered mid-greys toward the floor. Only active when fill_mask is wired.

Outputs (2)

NameTypeDescription
maskMASK—
previewIMAGE—