Nodes/ComfyUI_LC_MaskMaker_nodes/LC Normal Map (BAE) πŸ—ΊοΈ
ComfyUI Node

LC Normal Map (BAE) πŸ—ΊοΈ

The normal map your ControlNet was trained on

By lonecatone23Β·Created 26 days agoΒ·Updated about 15 hours agoΒ· 5
LC Normal Map (BAE) πŸ—ΊοΈ
  • image
  • normal_map
β—„modelβ–Ύβ–Ί
β—„resolution512β–Ί
β—„flip_yfalseβ–Ί
β—„blur_radius0β–Ί
β—„sigma1.0β–Ί

Normal maps are the preprocessor nobody uses until they need relighting. Instead of brightness-encodes-distance like a depth map, a normal map encodes which direction every surface faces as RGB. That makes it the right input for "keep the geometry, change the light" work, and it's why the ControlNet preprocessor everyone actually names is normal_bae - the BAE network trained on ScanNet.

This node runs that same network. If you've been keeping comfyui_controlnet_aux installed for exactly one node, this replaces it.

How it works

A single image in, an RGB map out where the channels are the X, Y and Z components of the surface normal. It's a discriminative network - vendored into the pack from baegwangbin/surface_normal_uncertainty, the same code comfyui_controlnet_aux wraps - so there's no separate package to install beyond timm, which the pack's installer adds if it's missing.

The author measured it at correlation 0.9999 against comfyui_controlnet_aux's BAE, which for practical purposes means identical. Weights are read from a copy you already have (models/normalbae, or the comfyui_controlnet_aux folder) before anything is downloaded.

The inputs

model has exactly one entry: scannet.pt, the BAE weights. The label carries the license warning the author put on every model entry in this pack - trained on ScanNet, Hugging Face card just says "other", so treat it as not cleared for commercial use until you've checked for yourself. That's unusually honest labeling and it's the kind of thing you normally find out after shipping.

resolution (512 default, steps of 64) is the size the shorter side is processed at. 512 is what ControlNet's own normal_bae uses, so it's the matching number; higher is slower and adds detail that the estimated normals may not actually have.

flip_y flips the green channel, which is the OpenGL-versus-DirectX convention difference. If you're comparing against a normal map generated by a game engine, a Blender render, or another node, and one of them looks "inside out" on the vertical, this is the toggle - not a bug.

Then the polish: blur_radius (0–31, radius in pixels, kernel 2r+1 wide) and sigma (0.1–10, how evenly the blur spreads across its radius). The blur is ComfyUI's own Blur Image, deliberately, so the result matches chaining that node after this one - same operator, same numbers. Default is 0, meaning off. Turn it on when you see the fine speckle BAE leaves on flat surfaces; a radius of 2–4 usually kills it without smearing the actual geometry. sigma only applies when radius is above 0.

One output: normal_map, a plain IMAGE.

Where it goes

Straight into a ControlNet Apply on a normal ControlNet, then generated with a relighting-friendly prompt. The pairing that actually wins is normal map plus IC-Light-style relighting, where the map is what stops the model from inventing new geometry while it changes where the light comes from. Both outputs of this pack's depth and normal nodes are also what LC Lighting Control in ComfyUI_LC123_nodes wants as its depth_map and normal_map.

A dated, honest caveat: on a mid-2026 stack this is a narrower tool than it was in 2024. The union ControlNets that landed for Z-Image, Flux 2 and Qwen-Image cover roughly seven conditions and normal maps were not among them - segmentation, normal maps, Reference and QR/brightness simply were never rebuilt post-Flux. If your workflow depends on a normal ControlNet, SDXL's union is still the place it exists, which is not a sentence anyone expected to write in 2026.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/lonecatone23/ComfyUI_LC_MaskMaker_nodes
# restart ComfyUI

Manager β†’ search LC MaskMaker, or let the installer do it. It pip-installs timm only if it's not importable already, and it doesn't upgrade or pin anything you have. That's the one dependency this node has that the rest of the pack doesn't.

Gotchas

  • scannet.pt isn't downloading. The entry shows a download label the first time and saves to models/normalbae. If you have comfyui_controlnet_aux installed, it'll read that copy instead and skip the download entirely - so check there before assuming it failed.
  • Normals look inverted vertically. flip_y. OpenGL vs DirectX, and yes, you're allowed to just try both.
  • Flat surfaces look grainy. That's BAE, not your input. Give blur_radius a value of 2–4.
  • The map looks blocky at high resolution. Normals don't have more detail to give you at 2048 than at 512; you're just paying for it.
  • timm missing on a manual install. python -m pip install timm in your ComfyUI environment. Manager normally handles this, but a manual git clone with no Manager run means install.py never executed.
  • License check before shipping anything commercial. ScanNet-trained weights, unclear terms. The label says so.
CategoryLC MaskMaker/depth

Inputs (6)

NameTypeDefaultDescription
imageIMAGEImage to estimate surface normals for.
modelCOMBOBAE weights (scannet.pt). Trained on ScanNet, whose terms are not commercial-friendly, and the weights' Hugging Face card just says 'other'. Verify before commercial use. Uses the copy you already have (models/normalbae or comfyui_controlnet_aux), or downloads it the first time you run.
resolutionINT512256–2048Size the shorter side is processed at. 512 is what ControlNet uses; higher is slower and can add detail.
flip_yBOOLEANfalseFlip the green channel (OpenGL vs DirectX style normal maps).
blur_radiusINT00–31Blur the finished normal map with ComfyUI's Blur Image. The radius is in pixels, the blur kernel is 2 x radius + 1 wide. Smooths the fine noise BAE leaves on flat surfaces. 0 = no blur.
sigmaFLOAT1.00.1–10How evenly the blur spreads across its radius (same meaning as in Blur Image). Higher = stronger, closer to a plain box blur. Lower = gentler, weighted toward the center. Only used when blur_radius is above 0.

Outputs (1)

NameTypeDescription
normal_mapIMAGEβ€”