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 16 days agoΒ· 107
ReLight πŸ’‘
  • image
  • mask
  • image
  • mask
  • debug_image
β—„presetNoneβ–Ί
β—„preserve_positioningfalseβ–Ί
β—„lighting_modeColor Correctionβ–Ί
β—„mask_shapeRadial falloffβ–Ί
β—„subject_interactionNoneβ–Ί
β—„remove_backgroundfalseβ–Ί
β—„num_light_sources1β–Ί
β—„effect_strength1.0β–Ί
β—„mask_blur50β–Ί
β—„rim_amplification2.0β–Ί
β—„shadow_strength0.60β–Ί
β—„shadow_length0.35β–Ί
β—„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β–Ί
β—„debug_output_connectedfalseβ–Ί
β—„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 (51)

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
preserve_positioningBOOLEANfalseKeep your own light positions and radii when a preset is selected, instead of letting the preset set them
lighting_modeCOMBOColor CorrectionWhat the light does. Color Correction grades an inner zone and the ring around it. Colored Light adds coloured light on top of the image. Both applies the coloured light first and then the grade
mask_shapeCOMBORadial falloffShape of the light mask. Radial falloff is a lamp; Directional gradient is light arriving from one side (sunset rays, window light)
subject_interactionCOMBONoneHow the light interacts with the masked subject. None lights the whole frame evenly. The other two need a mask connected
remove_backgroundBOOLEANfalseComposite the lit result back over the untouched original using the mask, so only the subject is relit. Does not remove anything. Ignored when the light is in front of or behind the subject
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 correction settings
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 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 for the rim highlight along the subject edge. Only used when the light is behind the subject
shadow_strengthFLOAT0.600–1How dark the shadow the subject casts across the background is. 0.0 casts no shadow. Only used when the light is behind the subject
shadow_lengthFLOAT0.350–1How far the cast shadow reaches, as a fraction of the image shorter side. Only used when the light is behind the 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 (Colored Light / Both)
light_color_gINT2550–255Light 1: Green color (Colored Light / Both)
light_color_bINT2550–255Light 1: Blue color (Colored Light / Both)
light_intensityFLOAT1.00–3Light 1: Intensity (Colored Light / Both)
inner_brightnessFLOAT10-100–100Light 1: Inner area brightness (Color Correction / Both)
inner_contrastFLOAT5-100–100Light 1: Inner area contrast (Color Correction / Both)
inner_saturationFLOAT5-100–100Light 1: Inner area saturation (Color Correction / Both)
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 / Both)
outer_contrastFLOAT0-100–100Light 1: Outer area contrast (Color Correction / Both)
outer_saturationFLOAT-10-100–100Light 1: Outer area saturation (Color Correction / Both)
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 subject interaction (in front of / behind the subject) and for remove_background compositing. Resized automatically if it does not match the image
debug_output_connectedoptBOOLEANfalseManaged by ReLight itself - the node UI hides this and keeps it in step with whether the debug_image output is wired to anything. It exists because a widget value is what ComfyUI hashes to decide a node needs re-running, so without it, wiring the debug output after a run would just replay the cached placeholder. Nothing to set by hand
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 Light / Both)
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 Light / Both)

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. Drawn whenever this output is connected to something - there is no toggle to remember