Atlas Fill Occluded π³οΈβπ©Ή
Fill the holes a camera move reveals β and register each fill back as geometry
- solve
- source_image
- model
- clip
- vae
- camera_path
- primary_depth
- exclude_mask
- solve
- image
- report
The moment your camera moves off the recovered viewpoint, it reveals parts of the scene the photograph never saw - the far side of a column, the ground behind a foreground figure. Those are disocclusion holes, and they're the thing that makes a 2.5D projection read as a cheap card trick instead of a move. Most fill approaches answer the wrong question: they fill a hole in a render, which is only valid for the exact camera path it was generated against. Change the angle by a degree and the fill is worthless, and nothing ever comes back into the scene.
Atlas Fill Occluded π³οΈπ©Ή fills a hole in the scene. Each fill is registered back as a ProjectionSource - real geometry the solve owns - so it exports to your DCC and every later camera move reuses it instead of re-inventing it. That's the whole architectural difference, and it's why this node sits in Atlas/advanced and why the fix it does actually sticks.
How it works
For each move-revealed cluster of holes it runs a per-ROI loop: survey the hole regions β crop the ROI at its own native raster β fill it with an edit model at that size β composite the fill back into the plate β register the fill plus its crop camera back as geometry via AtlasAddPatchView. It fills at most max_rois clusters (default 8), largest first, with min_area_px (default 1024) as the floor. That budget is on purpose: leftover speckle at the rim of a tear is cheaper handled by a band layer than by a diffusion pass each. Residual hole after a defaults run is expected - it isn't evidence the node failed.
The fill model defaults to flux_fill, wired through InpaintModelConditioning so the noise mask confines the sampler to the hole. qwen_edit is the alternative (Qwen Image Edit with an inpainting LoRA is the author's measured pairing for registering fills). If you pick flux_fill, remember its guidance wants to be high - the default flux_guidance of 30 is there because Fill models are not ordinary FLUX. The node takes model, clip, vae sockets like any loader-based graph, and fill_model is not validated against what you wire in - matching them is on you.
What matters most
camera_path- the move whose disocclusion you're filling. Holes are surveyed at its final frame, whose holes are a superset of every earlier frame's. No path = the solved pose, which by definition has almost nothing to fill.primary_depth- metric depth of the primary scene. Theregister_to_primarycamera mode requires it; without it every ROI falls to the failure policy.prompt- a sensible default ("continue the surrounding surfaces, do not invent new objects") that reads like it was written by someone who's seen a fill model wallpaper a hole with a beach.min_gen_long_edgeexists for the same reason: below ~1024, small clusters reach FLUX at native size and answer with nonsense - the author measured two 256Γ256 ROIs both answered with sand.
Outputs are the repaired image, the updated solve, and a report. Read the report's fillable hole numbers, not the raw peak hole figure - the raw number counts sky and off-plate pixels and will make a good run look like a failure.
Installing
Part of atlas-camera:
cd <ComfyUI>/custom_nodes
git clone https://github.com/mikejamesvfx/atlas-camera.git
Restart. The heavy lifting is model loading, which you already know how to do - you need FLUX Fill (or Qwen Image Edit) plus CLIP and VAE on the inputs. No non-commercial model is required by the pack itself.
Honest expectations
This is the most demanding node of the batch, and the author's own notes are refreshingly blunt about what "worked" means: at defaults on their test shot, fillable hole went from 4.56% to 1.28% of frame - 72% of the real disocclusion closed, zero pixels opened. That's the shape of success: not zero holes, but most of the real ones gone with none invented. And the default camera_source (declared_orbit) constructs the end pose exactly rather than measuring it, because a measured pose of a generated view was demonstrably worse than the constructed one. If you switch to register_to_primary, on_registration_failure decides what happens to ROIs the registration won't stand behind - skip for unattended loops, declared_orbit for artist-mode fallback. For a first run, leave the defaults alone and read the report.
Inputs (31)
| Name | Type | Default | Description |
|---|---|---|---|
| solve | ATLAS_SOLVE | β | |
| source_image | IMAGE | β | |
| model | MODEL | The edit model that fills each crop -- Qwen Image Edit 2509 with an inpainting LoRA is the measured pairing. It must be an EDIT model: a video model's fills cannot be registered. | |
| clip | CLIP | β | |
| vae | VAE | β | |
| camera_pathopt | ATLAS_CAMERA_PATH | The move whose disocclusion is being filled. Holes are surveyed at its FINAL frame, whose holes are a superset of every earlier frame's. No path = the solved pose, which by definition has almost nothing to fill. | |
| primary_depthopt | ATLAS_DEPTH_MAP | Metric depth of the primary. REQUIRED by register_to_primary -- without it every ROI falls to the failure policy. | |
| exclude_maskopt | MASK | Region carried by something other than geometry (a SkyDome, a matte). Subtracted from every survey mask, so it can only ever REMOVE candidate clusters. | |
| exact_view_overrideopt | STRING | AtlasCameraMovePreset's exact_view. Carries the pivot= term, so the patch camera reproduces the move's END pose exactly instead of orbiting the ground ray. | |
| max_roisopt | INT | 81β64 | Ceiling on clusters filled, largest first. The long tail of speckle is not worth a generation each. |
| min_area_pxopt | INT | 102464β1048576 | β |
| pad_fracopt | FLOAT | 0.100β0.5 | β |
| snapopt | INT | 648β128 | β |
| hole_dilate_pxopt | INT | 40β64 | β |
| max_gen_long_edgeopt | INT | 1280256β4096 | β |
| promptopt | STRING | Reconstruct the masked region so it matches the surrounding lighting direction, materials, palette and camera perspective. The masked pixels are geometry the original camera never saw, revealed by a camera move -- continue the surrounding surfaces, do not invent new objects. | β |
| seedopt | INT | 9901122330β72057594037927940 | β |
| fill_modelopt | COMBO | flux_fill (default) wires FLUX Fill through InpaintModelConditioning, whose noise_mask confines the sampler to the hole. qwen_edit wires Qwen Image Edit, whose mask is advisory -- measured, it returned the hole's neutral fill untouched even with 79% of the crop as real context. Wire the loaders to match: the model/clip/vae inputs are not validated against this choice. | |
| flux_guidanceopt | FLOAT | 30.00β100 | FLUX Fill's guidance (ignored by qwen_edit). The Fill models want a much higher value than ordinary FLUX. |
| stepsopt | INT | 201β200 | β |
| cfgopt | FLOAT | 1.00β30 | β |
| sampler_nameopt | COMBO | 6 options: euler, euler_ancestral, dpmpp_2m, dpmpp_2m_sde, ddim, uni_pc | |
| scheduleropt | COMBO | normal | 6 options: beta57, normal, karras, simple, beta, sgm_uniform |
| denoiseopt | FLOAT | 1.000β1 | β |
| relief_gridopt | INT | 9616β512 | β |
| camera_sourceopt | COMBO | declared_orbit (default) uses the camera Atlas CONSTRUCTED for this fill -- the move's end pose, exact, not a guess. register_to_primary MEASURES it instead, which is right for a novel-view generator whose camera is unknown and wrong here: measured 2026-09-03, the composited frame registers with 3583 inliers yet lands 10.1 deg from the pose it was demonstrably rendered at, while the plate at the primary pose -- a genuine 12 deg away -- measured 10.0 deg. The estimate does not track the difference, so a high inlier count is not proof of a correct pose. | |
| on_registration_failureopt | COMBO | An unattended loop must not append geometry the pixels do not support. 'skip' drops the ROI and reports it; 'declared_orbit' restores AtlasAddPatchView's artist-mode fallback. | |
| registration_min_inliersopt | INT | 404β10000 | β |
| registration_max_residual_mopt | FLOAT | 0.350.01β10 | β |
| registration_max_deviation_degopt | FLOAT | 25.01β180 | β |
| min_gen_long_edgeopt | INT | 10240β4096 | Scale each crop UP to this long edge before the fill, and back DOWN to its native rect afterwards (0 = off). max_gen_long_edge only caps, so without a floor a small cluster reaches the model at its native size -- and an auto survey produces exactly those. Measured 2026-09-04 on the sea-cliff castle: two 256x256 ROIs, and FLUX Fill answered both with a sand beach. 1024 is FLUX's own training band; the cap still wins a conflict. Nothing downstream sees the working raster -- the fill is resampled to the crop rect before the composite and before the patch camera. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| solve | ATLAS_SOLVE | β |
| image | IMAGE | β |
| report | STRING | β |