CCTech Normal Map Preprocessor (DSINE) ⚡
DSINE normal maps — camera-aware, with a field-of-view dial nobody else gives you
- image
- IMAGE
If the pack's BAE node is the normal-map standard, DSINE is the one you reach for when a standard isn't good enough. DSINE is a surface-normal estimator that's camera-intrinsics-aware: instead of assuming every photo was taken with the same lens, it reasons about perspective and iteratively refines its estimate. For images with strong perspective - wide-angle shots, interiors, anything where the camera clearly had a field of view - that produces noticeably more consistent normal maps than the vanilla approach.
The use case is the same as any normal map: relighting, material, and shape conditioning, with IC-Light-style relighting as the natural pairing. And the same honest caveat applies - normal maps are an SDXL-era ControlNet condition that never got rebuilt for the post-Flux unions, so plan to use this on SD 1.5/SDXL or hand the map to an edit model that reads structural input images.
How it works
DSINE builds an EfficientNet-B5 encoder (same backbone family as BAE - this is why both normal nodes in the pack pull in the optional timm dependency) with an iterative refinement head that's explicitly aware of camera geometry. It's a from-scratch port of the architecture from comfyui_controlnet_aux (Apache-2.0). Weights download from HuggingFace on first use into ComfyUI/models/dsine/.
Inputs and outputs that matter
image- the photo or render to estimate from.fov(default 60, 0–365) - the interesting one. It's a synthetic camera field-of-view in degrees used to build an assumed intrinsics matrix, because a plain photo carries no real camera metadata. For a wide-angle shot, raise it; for a tight telephoto crop, lower it. Getting this roughly right is the whole point of the node - it's the dial that separates "camera-aware" from "camera-guessing."iterations(default 5, 1–20) - how deep the iterative refinement goes. More iterations usually means a steadier map at the cost of speed; you'll rarely need to go far past the default.resolution(default 512, 64–2048) - internal working size.
Output is one IMAGE - the color-coded surface-normal map. Feed it into a normal-conditioned ControlNet's control_image or to an edit model that consumes structure.
Installing it
Part of ChrisColeTech/ComfyUI-ControlNet-Nodes, under 🤖 CCTech/Preprocessors. Install via ComfyUI Manager (search "ComfyUI-ControlNet-Nodes") or:
cd ComfyUI/custom_nodes
git clone https://github.com/ChrisColeTech/ComfyUI-ControlNet-Nodes
Restart ComfyUI. This is one of the two nodes in the pack that needs timm - normally handled by the pack's requirements.txt, but if the node throws on first run, pip install timm and restart.
Common issues
Same two setup gotchas as BAE: timm must be installed, and the first run downloads the checkpoint. Then there's the DSINE-specific one: fov matters more than it looks. If your wide-angle shots produce warped or inconsistent normals, the default 60° is fighting your image - bump it toward 90-110. If you're unsure what the camera actually was, BAE's simpler assumption-free estimate may serve you better than guessing. And as with all normal maps on modern bases: check that whatever ControlNet you're loading actually has a normal mode before building the workflow around it.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| fov | FLOAT | 600–365 | Synthetic camera field-of-view in degrees, used to build an assumed intrinsics matrix (no real camera metadata is available for a plain photo). |
| iterations | INT | 51–20 | — |
| resolution | INT | 51264–2048 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |