Nodes/ComfyUI-ReLight/ReLight πŸ’‘
ComfyUI Node

ReLight πŸ’‘

Fake a three-point lighting rig without regenerating a single pixel

By EnragedAntelopeΒ·Created about a year agoΒ·Updated 7 days agoΒ· 107
ReLight πŸ’‘
  • image
  • mask
  • image
  • mask
  • debug_image
β—„presetNoneβ–Ί
β—„num_light_sources1β–Ί
β—„preserve_positioningfalseβ–Ί
β—„show_debug_infofalseβ–Ί
β—„use_colored_lightsfalseβ–Ί
β—„use_gradient_modefalseβ–Ί
β—„apply_3d_lightingtrueβ–Ί
β—„light_directionNo Occlusionβ–Ί
β—„remove_backgroundfalseβ–Ί
β—„effect_strength1.0β–Ί
β—„mask_blur50β–Ί
β—„rim_amplification2.0β–Ί
β—„light_position_x0.50β–Ί
β—„light_position_y0.50β–Ί
β—„inner_circle_radius0.40β–Ί
β—„outer_circle_radius0.70β–Ί
β—„light_color_r255β–Ί
β—„light_color_g255β–Ί
β—„light_color_b255β–Ί
β—„light_intensity1.0β–Ί
β—„inner_brightness10β–Ί
β—„inner_contrast5β–Ί
β—„inner_saturation5β–Ί
β—„inner_temperature0β–Ί
β—„inner_tint0β–Ί
β—„inner_gamma1.00β–Ί
β—„outer_brightness-10β–Ί
β—„outer_contrast0β–Ί
β—„outer_saturation-10β–Ί
β—„outer_temperature0β–Ί
β—„outer_tint0β–Ί
β—„outer_gamma0.91β–Ί
β—„light2_position_x0.80β–Ί
β—„light2_position_y0.20β–Ί
β—„light2_inner_radius0.30β–Ί
β—„light2_outer_radius0.60β–Ί
β—„light2_color_r180β–Ί
β—„light2_color_g180β–Ί
β—„light2_color_b255β–Ί
β—„light2_intensity0.7β–Ί
β—„light3_position_x0.30β–Ί
β—„light3_position_y0.80β–Ί
β—„light3_inner_radius0.25β–Ί
β—„light3_outer_radius0.50β–Ί
β—„light3_color_r255β–Ί
β—„light3_color_g150β–Ί
β—„light3_color_b120β–Ί
β—„light3_intensity0.5β–Ί

There are two different things called "relighting" in this ecosystem, and keeping them straight is half the battle. IC-Light and the Qwen/Flux edit models are diffusion relighters - they re-emit the whole frame, shadows and all, and can hallucinate a logo or alter a texture while they're at it. ReLight is the other kind. It's a single ComfyUI node that paints up to three positionable light sources onto an image with pure math: numpy, Pillow, scipy, zero diffusion passes, zero models to download, deterministic every run. If you want a subject to catch a warm window glow without ever asking a denoiser to re-invent it, this is the node.

That determinism is the whole pitch. Diffusion relighters can't promise a consistent product catalogue; ReLight only promises that, because it modifies illumination and leaves the pixels' structure alone by construction. It's also near-instant, so it's what you reach for when you want to try twenty lighting ideas on a hero image before committing to a generation, or when you want to feed a deliberately lit result into ControlNet. It won't give you physically-correct global illumination or move reflections - it paints light onto what's already there, it doesn't re-render the scene. Know the limit and you won't be disappointed.

How it works

For each light source the node builds a mask centered on light_position_x/light_position_y - a radial falloff that's full strength inside inner_circle_radius and fades linearly to zero at outer_circle_radius, or a directional gradient if you flip on use_gradient_mode (that's your sunset-rays and window-light look). Everything gets softened by mask_blur.

Then it picks a lane. In the default color-correction mode it applies brightness/contrast/saturation/temperature/tint/gamma to the inner zone and a separate set to the outer ring - the v2.1.0 changelog fixed the outer values actually applying, so presets like "Spotlight" behave as designed now. With colored lights on, it does plain additive light: image + color Γ— intensity Γ— mask, clamped to a valid range.

The "3D" part is where the optional mask input earns its keep. The node runs a Sobel edge detection over your foreground mask, then modulates the light by how its direction lines up with the edge normals - that's how it fakes occlusion. Behind Subject leaves a rim of light around the silhouette (boost with rim_amplification); In Front of Subject lights the subject's face. No ray tracing, but for a static image it reads surprisingly well.

The inputs and outputs that matter

You'll set five things, honestly:

  • image - the only required input.
  • mask - white = subject, black = background. Needed for the occlusion directions and for remove_background.
  • preset - 8 ready-made looks. One gotcha: a preset overrides the widgets on the node, so the values you see may be ignored for whatever the preset defines. preserve_positioning keeps your light positions and radii when you pick one.
  • num_light_sources (1–3) - but note: lights 2 and 3 get their own position, radius and color while reusing Light 1's correction settings in color-correction mode. Set Light 1's first.
  • effect_strength - master intensity. If you see nothing, raise this first.

Outputs are three: image (the relit result, which is what you wire into a Save/Preview or into ControlNet), mask (pass-through of your input, black if none connected), and debug_image - a visualization of light positions and masks, produced when show_debug_info is on.

Install

ComfyUI Manager: search "ReLight" and install, then restart. Or the old-fashioned way:

cd path/to/ComfyUI/custom_nodes
git clone https://github.com/EnragedAntelope/comfyui-relight
pip install -r comfyui-relight/requirements.txt

That's it - numpy, Pillow, scipy; torch comes from ComfyUI itself. There are no model files to download. One version catch worth knowing: the node is built on the ComfyUI v3 node schema, which needs ComfyUI 0.3.48+. If the node never shows up after install, update ComfyUI first, not the node. The README also recommends ComfyUI Essentials for proper masks (its RemBG node gives you the clean foreground mask this thing wants).

Common issues

  • Subject looks unlit, or the effect is backwards. Your mask is inverted. ReLight expects white = subject; invert it upstream with an InvertMask node.
  • No visible effect. Raise effect_strength or the per-light light_intensity.
  • Occlusion isn't doing anything. apply_3d_lighting must be on and a mask connected; without one it silently degrades to flat lighting.
  • Node fails to load. scipy isn't installed - pip install scipy and restart.
  • Black debug image. Check the ComfyUI console; the debug output only renders for the first image in a batch.

A quick workflow to try: load an image, run RemBG for a mask, drop ReLight in with "Warm Sunset Glow" behind the subject, and preview alongside the debug image - the sample workflow in the repo does exactly this. It's the fastest way to see whether the "fake it with math" school of relighting is for you.

Categoryimage/lighting

Inputs (50)

NameTypeDefaultDescription
imageIMAGEThe input image to apply lighting effects to
presetCOMBONoneSelect a preset or 'None' for custom settings. NOTE: a preset overrides the widgets below - the values shown on the node are ignored for whatever the preset defines. The one exception is 'effect_strength', which scales the preset instead of being replaced by it
num_light_sourcesINT11–3Number of light sources (1-3). Lights 2 and 3 have their own position, radius and color, but in color-correction mode they reuse Light 1's correction settings
preserve_positioningBOOLEANfalseKeep your own light positions and radii when a preset is selected, instead of letting the preset set them
show_debug_infoBOOLEANfalseOutput a debug visualization image (first image of the batch; zone overlays show Light 1, position and radius indicators are drawn for every light)
use_colored_lightsBOOLEANfalseUse additive colored light instead of color correction?
use_gradient_modeBOOLEANfalseUse directional gradient masks instead of radial?
apply_3d_lightingBOOLEANtrueMaster switch for occlusion. Leave on and use 'light_direction' to choose the behaviour; turning this off forces 'No Occlusion'
light_directionCOMBONo OcclusionHow light interacts with the subject. 'Behind'/'In Front' require a mask
remove_backgroundBOOLEANfalseComposite the lit result back over the untouched original using the mask, so only the subject is relit. Does not remove anything. Ignored for 'Behind Subject' and 'In Front of Subject'
effect_strengthFLOAT1.00–5Overall intensity multiplier for lighting adjustments/colors, gamma included. 0.0 leaves the image untouched. With a preset active this scales the preset's own strength, so 1.0 is the preset as designed. Does not scale rim_amplification or mask_blur - those have their own controls
mask_blurFLOAT500–200Blur radius for light mask edges (smoother transitions)
rim_amplificationFLOAT2.00–10Intensity boost specifically for rim light component (when 'Behind Subject')
light_position_xFLOAT0.500–1Light 1: Horizontal position (0=left, 1=right)
light_position_yFLOAT0.500–1Light 1: Vertical position (0=top, 1=bottom)
inner_circle_radiusFLOAT0.400–1Light 1: Inner radius (strongest effect area)
outer_circle_radiusFLOAT0.700–1Light 1: Outer radius (falloff area)
light_color_rINT2550–255Light 1: Red color (if 'Use Colored Lights' is True)
light_color_gINT2550–255Light 1: Green color (if 'Use Colored Lights' is True)
light_color_bINT2550–255Light 1: Blue color (if 'Use Colored Lights' is True)
light_intensityFLOAT1.00–3Light 1: Intensity (if 'Use Colored Lights' is True)
inner_brightnessFLOAT10-100–100Light 1: Inner area brightness (Color Correction mode)
inner_contrastFLOAT5-100–100Light 1: Inner area contrast (Color Correction mode)
inner_saturationFLOAT5-100–100Light 1: Inner area saturation (Color Correction mode)
inner_temperatureFLOAT0-100–100Light 1: Inner area temperature (-100=cool, 100=warm)
inner_tintFLOAT0-100–100Light 1: Inner area tint (-100=magenta, 100=green)
inner_gammaFLOAT1.000.1–5Light 1: Inner area gamma. Above 1.0 brightens midtones, below 1.0 darkens them
outer_brightnessFLOAT-10-100–100Light 1: Outer area brightness (Color Correction mode)
outer_contrastFLOAT0-100–100Light 1: Outer area contrast (Color Correction mode)
outer_saturationFLOAT-10-100–100Light 1: Outer area saturation (Color Correction mode)
outer_temperatureFLOAT0-100–100Light 1: Outer area temperature
outer_tintFLOAT0-100–100Light 1: Outer area tint
outer_gammaFLOAT0.910.1–5Light 1: Outer area gamma. Above 1.0 brightens midtones, below 1.0 darkens them
maskoptMASKForeground mask (white=subject, black=background). Needed for occlusion ('Behind Subject' / 'In Front of Subject') and for 'remove_background' compositing. Resized automatically if it does not match the image
light2_position_xoptFLOAT0.800–1Light 2: Horizontal position
light2_position_yoptFLOAT0.200–1Light 2: Vertical position
light2_inner_radiusoptFLOAT0.300–1Light 2: Inner radius
light2_outer_radiusoptFLOAT0.600–1Light 2: Outer radius
light2_color_roptINT1800–255Light 2: Red color
light2_color_goptINT1800–255Light 2: Green color
light2_color_boptINT2550–255Light 2: Blue color
light2_intensityoptFLOAT0.70–3Light 2: Intensity (Colored mode)
light3_position_xoptFLOAT0.300–1Light 3: Horizontal position
light3_position_yoptFLOAT0.800–1Light 3: Vertical position
light3_inner_radiusoptFLOAT0.250–1Light 3: Inner radius
light3_outer_radiusoptFLOAT0.500–1Light 3: Outer radius
light3_color_roptINT2550–255Light 3: Red color
light3_color_goptINT1500–255Light 3: Green color
light3_color_boptINT1200–255Light 3: Blue color
light3_intensityoptFLOAT0.50–3Light 3: Intensity (Colored mode)

Outputs (3)

NameTypeDescription
imageIMAGEThe relit image
maskMASKPass-through of the input mask, normalised to (batch, height, width) and resized to the image (black if none connected)
debug_imageIMAGEVisualization of light positions and masks (enable 'show_debug_info')