Normal to Depth (Poisson)
Poisson depth reconstruction from normals
- normal_map
- depth_map
Of the two "normal map to depth map" solvers in ComfyUI-NormalsToDepth, this is the one I'd actually reach for. "Normal to Depth (Poisson)" reconstructs a depth map from a normal map by solving a Poisson equation - the classic surface-from-gradients approach - and it keeps the fine detail that the Fourier-based Frankot-Chellappa sibling tends to sand off.
What it does
Same contract as its sibling: feed it a normal map, get a depth map out. No weights, no model, no GPU - it's a few lines of numpy/scipy per frame, so it runs in a fraction of a second on CPU. If you already have normals (ControlNet aux, a renderer, a normal estimator) and you want a depth map for depth ControlNet, parallax, or bas-relief-style 3D printing, this is the cleanest path there.
How it works
Normals encode surface tilt: remapped to [-1,1], the X and Y channels give the surface slopes p = -nx/nz and q = -ny/nz. Integrating those slopes back into heights is the hard part, and Poisson's trick is to do it locally instead of globally.
Take the divergence of the gradient field (np.gradient over p and q), then solve ∇²z = div for the height z. This node solves it in the DCT domain: a discrete cosine transform, divide by the Laplacian's eigenvalues (which come out as 2cos(πx/cols) − 2 + 2cos(πy/rows) − 2), inverse transform back. Because a DCT-based solve respects local structure instead of treating the whole image as one frequency blob, edges and details survive the trip.
The inputs that matter
normal_map- IMAGE. A real normal map, please; the math has no way to know you fed it a color photo.invert_output- BOOLEAN, default off. Flips the white-is-near / white-is-far convention. Depth looks backwards? This is the switch.
Output: depth_map, an IMAGE, normalized to [0,1], ready for depth ControlNet or whatever downstream consumer wants it.
Frankot-Chellappa vs Poisson, quickly
- Frankot-Chellappa: global Fourier integration → smooth results, shrugs at noisy normals. Good when you want to average roughness away.
- Poisson: local, edge-preserving → sharper maps. Better for ControlNet, which wants edge clarity over absolute accuracy (same lesson as the MiDaS vs ZoeDepth debate in the knowledge base), and for parallax where silhouettes need to read.
Honestly, most of the time you want Poisson. Run both once and look - the difference is visible in 30 seconds.
Install and gotchas
ComfyUI Manager → search "ComfyUI-NormalsToDepth", or:
cd ComfyUI/custom_nodes
git clone https://github.com/EMkrtchyan/ComfyUI-NormalsToDepth
Restart and you're done. Requirements are scipy, numpy, torch - no downloads, no model files, no VRAM pressure.
Where people get burned: feed it a non-normal-map and you get garbage with a smile - the near-zero nz guard keeps the math from dividing by zero, but it can't save a wrong input. And watch the green channel: OpenGL and DirectX normal maps flip the Y component, which inverts the slope direction and produces a warped, smeared depth map that invert_output won't fix. Flip green upstream if you see that. There's no real documentation to fall back on (the README is a single screenshot), so treat these nodes as the experiment-friendly utilities they are: cheap to run, easy to A/B.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| normal_map | IMAGE | — | |
| invert_output | BOOLEAN | false | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| depth_map | IMAGE | — |