Atlas Occlusion Mask π³
Know exactly where the primary camera is lying to you
- solve
- target_image
- primary_depth
- occlusion_mask
- coverage_mask
The atlas-camera patch pipeline works like this: a novel view (a patch, a LoRA-generated repair) shows you geometry that the primary photo either can't see or only sees at a grazing angle. Before you composite that patch in, you need a mask of exactly where the primary is missing that information. Atlas Occlusion Mask is that mask. White means "the primary camera has no valid coverage here, a patch should fill it"; black means "the primary already has it, head-on." It's the π³ in Atlas/04 Β· Masks.
It's the phase-gate of the patch path: no mask, no idea whether you're genuinely adding information or smearing a patch over pixels the primary already owns.
How it works
The node places the target/patch camera identically to how AtlasAddPatchView will place it later - same named-view widgets, same orbit construction - so the mask lines up with whatever patch geometry that node derives from the same image. Then it projects the primary's coverage onto the scene and marks the failures:
- simple mode (default) - Phase-1 tests only: frustum, behind-camera, and out-of-frame failures, plus a facing-angle gate (angle_threshold, default 90Β° = only true "can't see it" failures; lower it and surfaces too grazing to the primary also get masked).
- depth_shadow mode - adds the real matte-painting trick: a camera-as-light shadow test. Surfaces hidden behind nearer geometry from the primary's view get masked, using
primary_depthas the shadow map. This is the true "MPTK-style" test, and it needs primary_depth wired - the sharedAtlasDepthMaprun on the primary photo. Without it, the mode falls back to simple and the report says so.
The patch_* and source_* dropdowns exist to keep the mask aligned with the LoRA that generated the target image - they describe which azimuth/elevation/distance the target was generated at and which view the source photo already is. The contract is blunt: they must match the values you'll use in AtlasAddPatchView, or the mask and the patch drift. If you'd rather not hand-sync, patch_view_override / exact_view_override accept the snapped or raw orbit strings from AtlasBlockoutViewport.
Inputs and outputs
Required: solve and target_image. Optional: the view dropdowns above, flip_azimuth, depth_model (default DA-V2-Metric-Outdoor), device, angle_threshold, dilate_px (expand the white region), soft_edge_px (feather it), power (gamma remap after blur), occlusion_mode, primary_depth, depth_bias (relative depth tolerance before a point counts as shadowed), and the two view overrides.
Outputs: occlusion_mask (white = missing) and coverage_mask (the inverse view - white = valid primary coverage).
Installing it
Core node; depth_model/primary_depth are inputs, not a dependency of this node:
cd <ComfyUI>/custom_nodes
git clone https://github.com/mikejamesvfx/atlas-camera.git
Restart, find it in Atlas/04 Β· Masks (ComfyUI Manager: "atlas-camera").
Common issues
The alignment contract is where people burn time. The patch azimuth/elevation/distance and source view must agree between this mask and the AtlasAddPatchView wiring - if you generate the target at "front-right quarter view" but tell the mask "front view," the mask shows the wrong holes. If that's fiddly, use patch_view_override / exact_view_override from AtlasBlockoutViewport so one string drives both, and the "never-drift" contract holds. For final compositing, set dilate_px and soft_edge_px sensibly - a hair of dilation plus a feather is usually enough; the power knob >1 makes the patch contribution more solid near the feathered edge.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| solve | ATLAS_SOLVE | β | |
| target_image | IMAGE | β | |
| patch_azimuth_viewopt | COMBO | front-right quarter view | The LoRA azimuth target_image was generated at β should match whatever you'll later pass to AtlasAddPatchView for this image. |
| patch_elevation_viewopt | COMBO | eye-level shot | The LoRA elevation target_image was generated at. |
| patch_distanceopt | COMBO | medium shot | The LoRA distance target_image was generated at. |
| source_azimuth_viewopt | COMBO | front view | Which view your SOURCE photo already is, in the LoRA's absolute frame. Must match the value you'll use in AtlasAddPatchView. |
| source_elevation_viewopt | COMBO | eye-level shot | Elevation of the SOURCE photo in the LoRA's frame. |
| flip_azimuthopt | BOOLEAN | false | Must match the AtlasAddPatchView setting for this patch. |
| depth_modelopt | COMBO | depth-anything/Depth-Anything-V2-Metric-Outdoor-Large-hf | 10 options: depth-anything/Depth-Anything-V2-Metric-Outdoor-Large-hf, depth-anything/Depth-Anything-V2-Metric-Indoor-Large-hf, depth-anything/DA3METRIC-LARGE, depth-anything/DA3MONO-LARGE, depth-anything/DA3NESTED-GIANT-LARGE-1.1, Ruicheng/moge-2-vitl-normal, +4 |
| deviceopt | COMBO | auto | 4 options: auto, cuda, mps, cpu |
| angle_thresholdopt | FLOAT | 900β90 | Facing-angle gate in degrees for the PRIMARY camera's coverage. 90 (default) = only frustum/behind-camera/out-of-frame failures are masked. Lower values also mask surfaces too grazing to the primary. |
| dilate_pxopt | INT | 00β200 | Expand the white (missing) mask region by this many pixels. |
| soft_edge_pxopt | INT | 00β200 | Blur the dilated mask edge by this many pixels, for compositing. |
| poweropt | FLOAT | 1.00.1β8 | Gamma remap after blur; > 1 makes the patch contribution more solid near the feathered edge. |
| occlusion_modeopt | COMBO | simple | simple = Phase-1 frustum/frame/facing tests only (unchanged). depth_shadow = additionally detect surfaces hidden behind NEARER geometry from the primary's view (true MPTK camera-as-light shadow test, using primary_depth as the shadow map). Falls back to simple when primary_depth isn't connected. |
| primary_depthopt | ATLAS_DEPTH_MAP | AtlasDepthMap run on the PRIMARY/source photo β the shadow map for depth_shadow mode. Wire the same shared AtlasDepthMap the derive nodes already use. | |
| depth_biasopt | FLOAT | 0.050β1 | depth_shadow only: relative depth tolerance before a point counts as shadowed β guards against monocular depth-precision false positives. 0.05 = must be 5% farther than the stored depth. |
| patch_view_overrideopt | STRING | Optional: wire AtlasBlockoutViewport's patch_prompt output here β overrides the three patch_* dropdowns with π Extract Angle's snapped views, keeping this mask aligned with the same AtlasAddPatchView wiring. Errors loudly if unparseable. | |
| exact_view_overrideopt | STRING | Optional: wire AtlasBlockoutViewport's patch_exact output here (π's RAW orbit floats) β wins over patch_view_override and the dropdowns, flip_azimuth ignored, placing this mask's target camera IDENTICALLY to an AtlasAddPatchView driven by the same string (the shared never-drift contract). Errors loudly if unparseable. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| occlusion_mask | MASK | β |
| coverage_mask | MASK | β |