Nodes/Atlas Camera/Atlas Scope Mask 🎯
ComfyUI Node

Atlas Scope Mask 🎯

Atlas Scope Mask 🎯 β€” the smart exclusion mask for the 2.5D layer stack

By mikejamesvfxΒ·Created 2 months agoΒ·Updated a day agoΒ· 1
Atlas Scope Mask 🎯
  • sky_mask
  • segment_mask
  • fallback_mask
  • exclude_mask
  • status
β—„promptβ–Ί
β—„grow_px16β–Ί
β—„min_coverage_pct0.2β–Ί

AtlasScopeMask is where the pack's 2.5D matte-painting layer stack decides what a layer is not allowed to cover. In the Atlas model, each depth band gets a projection layer, and each layer needs to know which pixels belong to other layers so it doesn't paint over them. The sky is the permanent exclusion - that's the sky_mask you're required to wire in, and it's the always-on base of every fallback. The scope part is the extra exclusions: for a given band, you can prompt for the content that should be carved out of it.

The name tells you the game. This isn't a segmenter - it's a combiner and decision-maker that turns "the base exclusion" plus "whatever this band's content is" into one clean exclude_mask, with sensible fallbacks when the content detector can't find what you asked for.

How the fallback ladder works

The inputs read like a decision tree, and that's intentional:

  1. sky_mask (required) - the always-on base. Every fallback path returns exactly this.
  2. prompt + segment_mask - the SAM3 segment for this band's content. The neat bit: this is lazy. Empty prompt means the layer is unscoped/absent, the node returns the sky mask alone, and via lazy evaluation the segmenter never runs. Wire the prompt and the segment gets evaluated.
  3. fallback_mask - the geometry-prior fallback, tried before giving up: wire an AtlasSemanticMask here. Its fixed ADE20K vocabulary can't miss the way free text can, so it's the reliable second opinion. Also lazy - only evaluated on an actual no-match.
  4. min_coverage_pct - if the segment covers less than this % of the frame, the prompt is treated as a NO-MATCH, and instead of excluding the whole layer you fall back to band-only.

Round it out with grow_px (dilate the segment before inverting - the classic GrowMask-16 default, so silhouettes don't clip) and you get the full picture.

Outputs

exclude_mask (MASK) - what this layer must not project onto - and a status string telling you which path it took (scoped, no-match + fallback, or band-only). That status output is the quiet hero: when a layer mysteriously eats the sky, the status tells you the scope prompt no-matched and what it fell back to.

The honest gotcha

The failure mode to watch is a too-loose prompt producing a too-big exclusion: prompt "building" for a band that's mostly facade and the segment covers 60% of the frame, which is real, and your foreground layer suddenly has a building-shaped hole it never should have. min_coverage_pct guards against misses, not overreaches - so scope prompts should name the thing you want to remove from the layer, narrowly, not the whole layer's subject.

Install

Pure logic node - core tier, no models, no deps beyond the pack:

cd <ComfyUI>/custom_nodes
git clone https://github.com/mikejamesvfx/atlas-camera.git

Restart, or install via ComfyUI Manager ("atlas-camera"). It lives in Atlas/04 Β· Masks. The masks you feed it come from AtlasSAM3Mask or AtlasSemanticMask, which carry their own install notes.

CategoryAtlas/04 Β· Masks

Inputs (6)

NameTypeDefaultDescription
sky_maskMASKThe always-on base exclusion (SAM sky mask). Every fallback path returns exactly this.
promptoptSTRINGThe scope prompt β€” wire the same sam_* rail that feeds this row's SAM3Segment. Empty = this layer is unscoped/absent: the node returns the sky mask alone and (via lazy evaluation) the segmenter never runs.
segment_maskoptMASKThe SAM3 segment for this band's content. Only evaluated when prompt is non-empty.
grow_pxoptINT160–256Dilate the segment before inverting (keeps silhouettes from clipping β€” the old GrowMask 16 default).
min_coverage_pctoptFLOAT0.20–50If the segment covers less than this % of the frame, treat the prompt as a NO-MATCH and fall back to band-only instead of excluding the whole layer.
fallback_maskoptMASKGeometry-prior fallback, tried BEFORE band-only when the SAM prompt no-matches β€” wire an AtlasSemanticMask (fixed ADE20K vocabulary, can't miss the way free-text prompts can). Lazy: only evaluated on an actual no-match.

Outputs (2)

NameTypeDescription
exclude_maskMASKβ€”
statusSTRINGβ€”