Depth + Normals to Mesh
Turn a normal map into an actual 3D mesh, without leaving ComfyUI
- normal_map
- depth
- depth_image
- mesh
- info
This is the pack's "image to geometry" trick, and honestly the one people demo first. You feed it a normal map - the blue-ish image where color encodes surface direction - and it reconstructs a real 3D mesh. That's the pipeline behind a lot of the "take a 2D image and make it physical" work: render a normal pass, or generate one from Stable Diffusion via a normal ControlNet preprocessor, and turn it into geometry you can actually orbit, slice, or print. The depth-estimation world has been feeding these maps into Blender for years; this node keeps the whole loop inside ComfyUI.
How it works, roughly: the node integrates the normal map into a height field - that's what turns directions into elevations - samples that height field into a point cloud, and then runs a surface reconstruction, by default Poisson reconstruction, to wrap the points in a clean mesh. If you already have an explicit depth map, you can skip the integration and hand it over directly.
The inputs that matter
- normal_map (IMAGE) - required. The normal pass that drives everything.
- resolution - point-cloud sampling resolution, 64–2048, default 512. Higher is more detail and slower; 512 is a good starting point.
- depth_scale - scales the depth values, 0.01–10, default 1. Crank it up for dramatic relief, down for a subtle bas-relief.
- depth (MASK) and depth_image (IMAGE) - optional explicit depth, if you have a real depth map rather than just normals.
- method - reconstruction method, default
poisson. - poisson_depth - octree depth for Poisson (4–12, default 8). Higher = finer detail, more VRAM and time. The tooltip's guidance is worth trusting.
- poisson_scale - bounding-box scale factor for the reconstruction (1–2, default 1.1).
- skip_background (default true) and background_threshold - drop pixels below a depth threshold so the flat background doesn't become a giant slab. Leave both on.
- invert_depth - for depth maps where white = far instead of near; flip it if your relief comes out inverted.
Outputs: mesh (the TRIMESH) and info (STRING diagnostics).
Installing it
Standard GeometryPack install:
cd ComfyUI/custom_nodes
git clone https://github.com/PozzettiAndrea/ComfyUI-GeometryPack.git
cd ComfyUI-GeometryPack
pip install -r requirements.txt --upgrade
python install.py
Restart ComfyUI. ComfyUI Manager also works (search "GeometryPack" or install via Git URL). The one-click installer is experimental and drags in pixi; manual is the README's "most reliable."
Where it gets fiddly
The normal-map coordinate convention is the classic gotcha - OpenGL and DirectX/Unity normal maps disagree on the green channel direction, so if your result comes out with inverted or warped relief, flip the convention before you touch the dials. And invert_depth bites people who feed in a depth map with a white-is-far convention and get a bowl instead of a bump. The other practical thing: this node is a memory hog at high resolution × high poisson_depth on big images - drop to 256/8 if you hit OOM, not 2048/12. It's a young pack, so expect rough edges and keep it updated; but this is the node that makes the "AI image → physical object" pipeline feel like it finally lives in the graph.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| normal_map | IMAGE | — | |
| resolution | INT | 51264–2048 | Resolution for point cloud sampling (higher = more detail, slower) |
| depth_scale | FLOAT | 1.00.01–10 | Scale factor for depth values |
| depthopt | MASK | — | |
| depth_imageopt | IMAGE | — | |
| methodopt | COMBO | poisson | 2 options: poisson, ball_pivoting |
| poisson_depthopt | INT | 84–12 | Octree depth for Poisson reconstruction (higher = more detail) |
| poisson_scaleopt | FLOAT | 1.11–2 | Scale factor for Poisson bounding box |
| skip_backgroundopt | COMBO | true | Skip pixels with depth below threshold (background removal) |
| background_thresholdopt | FLOAT | 0.010–1 | Depth threshold for background pixels |
| invert_depthopt | COMBO | false | Invert depth values (for depth maps where white = far) |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| mesh | TRIMESH | — |
| info | STRING | — |