Atlas MoGe Normals π§
Keep your good depth, upgrade the normals
- depth
- image
- solve
- depth
- report
Depth models and normal models are not the same animal, and the atlas-camera pack refuses to pretend otherwise. MoGe is the monocular-geometry specialist from Microsoft Research - it predicts a point map and clean, physically-plausible normals from a single image. But its depth behaviour has a blind spot: it masks sky and runs away on wide exteriors. Atlas MoGe Normals exists to let you have both - MoGe's normals, and a depth model of your choice for the depth. It's the π§ in Atlas/03 Β· Depth.
The node's whole reason to exist is in its docstring: it runs a MoGe *-normal model purely for the per-pixel normals, discards MoGe's own depth, and attaches those normals to a copy of whatever ATLAS_DEPTH_MAP you feed it. The clean-plate layer downstream then uses them as its world-normal relight map exactly as if MoGe had been the depth model - so you keep Depth Anything V2 or DA3's far-field depth (which behaves on exteriors where MoGe's runs away) and still get MoGe's cleaner predicted normals for the lighting.
How it works
Wire it between AtlasDepthMap (any model) and AtlasCleanPlateLayer. It takes the input depth plus the original image, runs MoGe's normal prediction, resizes the normals to the input depth's resolution, and hands back the same ATLAS_DEPTH_MAP - with normals attached. The solve is optional but does real work: feeding the solved focal into MoGe as fov_x gives better geometry. The normals get aligned to the recovered world frame downstream regardless, so it's a quality knob, not a correctness requirement.
Inputs and outputs
Required inputs:
- depth - an
ATLAS_DEPTH_MAPfrom any depth model. - image - the original photograph.
Optional inputs:
- normal_model - which MoGe
*-normalcheckpoint:vitl(best quality),vitb(lighter GPU), orvits(35M, CPU/MPS-viable). Auto-downloads from HuggingFace. - device - auto/cuda/mps/cpu.
- solve - optional solved focal for
fov_x. - resolution_level - MoGe's token-budget dial, 0β9; 9 is the default and full detail.
- max_side - cap the longer edge before inference (0 = off). This only buys VRAM and time: normals come back at source size either way, and because normals are lower-frequency than depth, a downscaled pass costs less quality than a downscaled depth pass.
- checkpoint_path - a local MoGe
model.ptinstead of a HF download. Note the tooltip's warning: this is not ComfyUI core's.safetensorsformat - different container.
Outputs: depth (with normals attached) and report.
Installing it
Requires the [moge] extra (MoGe is GitHub-only):
cd <ComfyUI>/custom_nodes
git clone https://github.com/mikejamesvfx/atlas-camera.git
<ComfyUI>/venv/Scripts/python.exe -m pip install ".[moge]"
MoGe is MIT-licensed (the repo dual-licenses MIT and Apache 2.0), so no licensing caveat here. Into an existing ComfyUI venv, the pack's INSTALL.md recommends the --no-deps route - MoGe's own dependency list pulls gradio/matplotlib/pipeline you don't want.
Common issues
MoGe's sky masking is the thing to remember: it's great on enclosed/interior shots, poor outdoors. That's precisely why this node decouples normals from depth - if you let MoGe be your depth model on an exterior, the sky gets holes. Let it do normals, keep DA-V2-Metric-Outdoor for depth, and the two cover each other's weaknesses. If the normals come back at the wrong resolution, don't panic - resize happens against the input depth map, so feed the same depth map you're using downstream.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| depth | ATLAS_DEPTH_MAP | β | |
| image | IMAGE | β | |
| normal_modelopt | COMBO | Ruicheng/moge-2-vitl-normal | MoGe *-normal checkpoint. vitl=best quality, vitb=lighter GPU, vits=35M CPU/MPS-viable (non-CUDA). Auto-downloads from HuggingFace. |
| deviceopt | COMBO | auto | 4 options: auto, cuda, mps, cpu |
| solveopt | ATLAS_SOLVE | Optional β feeds the SOLVED focal to MoGe (fov_x) for better geometry; the normals are aligned to the recovered world frame downstream regardless, so this is a minor quality knob. | |
| resolution_levelopt | INT | 90β9 | MoGe's token-budget dial; 9 is its default and full detail. Lower = faster, coarser normals. |
| max_sideopt | INT | 00β16384 | Cap the longer edge before inference (0 = off). Normals come back at SOURCE size either way β this only buys VRAM and time. Cheap here: normals are lower-frequency than depth, so a downscaled normal pass costs less quality than a downscaled depth pass. |
| checkpoint_pathopt | STRING | Local MoGe `model.pt` instead of a HuggingFace download. NOT ComfyUI core's *.safetensors β different container. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| depth | ATLAS_DEPTH_MAP | β |
| report | STRING | β |