Normal Format Auto-Converter
It figures out your normal map's format so you don't have to
- normal_map
- normal_map
- detected_format
- conversion_info
The Normal Format Converter in this pack has a dirty little secret: despite the "auto_detect" option in its dropdown, it always just flips green. Normal Format Auto-Converter is the node that actually does the detecting. You give it a normal map and tell it which format you want out, and it inspects the green channel, decides whether the source is OpenGL or DirectX, converts if needed, and passes it through untouched if it already matches. One node, no thinking, no "wait, which way was it again?"
It's part of TextureAlchemy's Texture Alchemist/Normal family, and if you're doing any volume of texture work, it quietly eliminates the single most common normal-map error.
How it works
The detection is a distribution test on the green channel. In OpenGL, Y points up, so flat/up-facing surfaces have green values above 0.5 (encoded as 0.5 + ny/2). In DirectX, Y points down, so the green channel skews below 0.5. The node measures the mean of the green channel and compares it to the 0.5 neutral line with a small detection threshold (0.03, deliberately matching the sibling Validator node so the two tools agree). If the mean sits above neutral, the map is read as OpenGL; below, DirectX.
Then it compares that read to your target_format:
- Match - the map passes through unchanged, and the info string says so.
- Mismatch - the green channel gets flipped (
1.0 - green), converting the format.
Inputs with fewer than three channels get flagged rather than silently mangled. Outputs are the converted-or-untouched normal_map, a detected_format STRING (so you can see what it thought you had), and a conversion_info STRING explaining what it did - genuinely useful for audits and for learning the format tells yourself.
The inputs that matter
- normal_map - the map to check and convert.
- target_format - what you want out:
DirectX(Unreal, Maya) orOpenGL(Unity, Blender). Defaults to DirectX.
Where it fits
Drop it inline before any normal map that's about to hit a material pipeline - extract, auto-convert, done. It's also the best teacher of the format concept in the pack: feed it maps from different sources and read the detected_format output to see which way each one leans. When a downstream material still looks inverted after this node, you know the problem isn't format - it's something else in the chain.
Installing it
Ships with ComfyUI-TextureAlchemy. ComfyUI Manager → search "TextureAlchemy" → install → restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/amtarr/ComfyUI-TextureAlchemy
Restart, find it under Texture Alchemist → Normal. No pip packages or model downloads.
Common issues
- "It said the format but nothing was converted." That means your map already matched the target - working as intended. Check
conversion_infoto confirm. - "It flips when it shouldn't." The detection is a global mean. A map that's mostly flat geometry (everything hugging the neutral line) can read slightly one way or the other - the 0.03 threshold is deliberately small, and genuinely ambiguous maps can go either way. If you know the source format, use the plain Normal Format Converter instead.
- "Ambiguous result." A mostly-flat normal map has a green channel hugging 0.5, where detection is unreliable. That's not a bug - it's a map that barely has a format either way.
The verdict: if you don't know what format your normals are, this is the node to reach for. It's the auto-detect the sibling node only pretends to be.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| normal_map | IMAGE | — | |
| target_format | COMBO | DirectX | Desired output format |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| normal_map | IMAGE | — |
| detected_format | STRING | — |
| conversion_info | STRING | — |