Nodes/ComfyUI-TextureAlchemy/Normal Map Relighter (Advanced)
ComfyUI Node

Normal Map Relighter (Advanced)

Normal Map Relighting With Specular and Colored Lights

By amtarr·Created 9 months ago·Updated 4 months ago· 58
Normal Map Relighter (Advanced)
  • image
  • normal_map
  • relit_image
  • diffuse_lighting
  • specular_lighting
light_x0.00
light_y0.00
light_z1.00
diffuse_intensity1.0
specular_intensity0.5
specular_power32
ambient_light0.20
light_color_r1.00
light_color_g1.00
light_color_b1.00
normal_formatOpenGL

The plain Normal Map Relighter gives you a directional light and a light mask. Advanced is what you grab when "a light" isn't enough - you want a colored key light, a proper specular highlight with a shininess knob, and the diffuse and specular passes separated so you can comp them yourself. Same family, same normal-map dot-product core, more control.

This is the node you reach for when you're shading something that needs to look lit rather than just be brighter: a polished surface with a visible highlight, a material preview where you can tell a matte surface from a glossy one, or a "hero" render of an albedo+normal pair before you commit to a full PBR pipeline.

How it works

Like its simpler sibling, it decodes the normal map into vector space, handles the OpenGL/DirectX green-channel flip, and shades with the dot product between normals and your light_x/y/z direction. On top of that it adds two things:

  • Diffuse with a light color. light_color_r/g/b tint the diffuse shading, so you can set a warm key light and get a warm-side/cool-side split instead of gray-on-gray.
  • Blinn-style specular. specular_intensity controls how strong the highlight is and specular_power (1-128, default 32) controls how tight - low values give a broad, soft sheen; high values give a tight, mirror-like glint.

Because the specular is driven by the same light direction, the highlight lands where it should: on surfaces angled toward the light. That's the detail that makes a normal map "pop" in a still image.

Inputs and outputs that matter

The setup inputs are image, normal_map, and light_x/y/z (start at (0,0,1) and nudge X/Y). Then:

  • diffuse_intensity (0-10) - brightness of the shaded albedo.
  • specular_intensity (0-10) - strength of the highlight; 0 turns it off entirely for a pure matte look.
  • specular_power - shininess. Low = plastic sheen, high = metal glint.
  • ambient_light (0-1) - the brightness floor in shadow.
  • normal_format - OpenGL vs DirectX; wrong choice = inverted-looking shading.

Three outputs come out, and they're the real reason to pick this over the basic node: relit_image (combined), diffuse_lighting (the shaded pass on its own), and specular_lighting (just the highlight pass). Having them separate means you can multiply diffuse into your albedo, keep specular as an additive pass, and adjust either without re-running. It's the beginnings of an AOV-style workflow.

Installing it

Ships in TextureAlchemy. ComfyUI Manager (search "TextureAlchemy"), or:

cd ComfyUI/custom_nodes
git clone https://github.com/amtarr/ComfyUI-TextureAlchemy

Restart and look under Texture Alchemist → Lighting. No models, no pip installs - it's all tensor math.

Where it falls short

Don't mistake "Advanced" for physically based. There's no environment, no roughness map, no Fresnel tied to real IBL - the specular is a stylized Blinn approximation. If you're lighting something metal and expect environment reflections to slide across it, this isn't the node; that's the IBL relighter's job. Use Advanced when you want a hand-tuned, art-directed key light with a highlight you can dial in.

CategoryTexture Alchemist/Lighting

Inputs (13)

NameTypeDefaultDescription
imageIMAGE
normal_mapIMAGE
light_xFLOAT0.00-1–1Light direction X component
light_yFLOAT0.00-1–1Light direction Y component
light_zFLOAT1.00-1–1Light direction Z component
diffuse_intensityFLOAT1.00–10Diffuse light intensity
specular_intensityFLOAT0.50–10Specular highlight intensity
specular_powerFLOAT321–128Specular power (shininess)
ambient_lightFLOAT0.200–1Ambient light level
light_color_rFLOAT1.000–1Light color red channel
light_color_gFLOAT1.000–1Light color green channel
light_color_bFLOAT1.000–1Light color blue channel
normal_formatCOMBOOpenGLNormal map format

Outputs (3)

NameTypeDescription
relit_imageIMAGE
diffuse_lightingIMAGE
specular_lightingIMAGE