Reference Latent+
Stop dragging the whole photo in — Reference Latent+ lets you take just the face
- conditioning
- vae
- image_1
- image_2
- image_3
- image_4
- mask_1
- mask_2
- mask_3
- mask_4
- conditioning
Stock ComfyUI has a ReferenceLatent node, and it's about as thin as a node gets: drop a latent in, it tacks it onto your conditioning under the reference_latents key, done. Binary. Whole image, every step, no strength knob. The moment you want "that character's face but not their pose, background, and crop," it's useless - you're back to LoRA training or a ControlNet that fights your composition.
Reference Latent+ is the version the stock node never grew up to be. It's a drop-in replacement by shootthesound (Peter Neill, the same person behind the Fizgig Klein LoRA workbench and the LoRA block analyzer - a known quantity on r/StableDiffusion) that gives you per-image strength, per-image timestep gating, auto-masks, and up to four references in a single node. If you're doing reference-based character or style transfer on Flux, Flux2/Klein, Wan, Hunyuan, Qwen-Image, Z-Image, or Lumina2, this is the node you reach for.
How it works
Same trick as stock ReferenceLatent, one layer deeper. The node VAE-encodes your images internally (yes, there's a vae input, so no more hand-wiring LoadImage → VAE Encode → ReferenceLatent chains) and attaches them to your conditioning's reference_latents key, which those models read directly. Two things make it smart:
- Per-image timestep gating. Each ref gets its own
start_percent/end_percent. The node partitions the denoising schedule so every timestep has exactly one set of active refs - no double-counting. This is the killer feature on Flux2/Klein: style and identity live in the clean, late timesteps, so gating a ref to0.6–1.0lets your prompt's composition run free early and only adds the ref's look at the end. - Megapixel cap.
max_megapixels(default 1.0) downscales each ref by area before encoding, aspect preserved, never upscaled. Reference latents cost quadratic attention, so a 2K ref photo will wreck your generation speed; capping keeps it proportional to a 1024² render.
The inputs that matter
Only four required: conditioning, vae, image_1, plus the max_megapixels and mask_fill_mode globals. Connect image_1 and an image_2 slot appears; connect that and image_3 shows up - progressive disclosure, up to four refs.
image1_strength- signed,-5.0to50.0, default0.85. 1.0 equals stock behavior; 0 bypasses that image entirely; negative is the experimental "anti-reference" that pushes the model away from that ref.image1_face/hair/body/clothes/background- MediaPipe auto-mask regions. Tick "face" and only the face gets encoded as a ref. No more background leaking into your output.grow,feather, andignore_arearefine the mask.image1_start_percent/end_percent- that timestep gate. Defaults to 0→1 (always on).
Output is a single conditioning tensor - wire it into your KSampler's positive input and you're done.
Installing it
Via ComfyUI Manager, search "Reference Latent+" (pack title comfyui-ReferenceLatentPlus). Or the manual way:
cd ComfyUI/custom_nodes
git clone https://github.com/shootthesound/comfyui-ReferenceLatentPlus
Then restart ComfyUI. It appears under advanced/conditioning > Reference Latent+. The MediaPipe auto-mask feature is optional: pip install mediapipe into your ComfyUI venv and the selfie_multiclass model auto-downloads to models/mediapipe/ on first use. There's a ready Klein 9B example workflow in examples/.
Where people get burned
- No MediaPipe = silent no-op. Ticking a region does nothing if the package isn't installed - no error, the ref just isn't masked. Explicit
mask_Nwiring still works regardless. latent_zeroandlatent_noiseare off-distribution. No model trained on masked reference latents; at high mask coverage behavior is exploratory.pixel_grey(the default) stays in-distribution - treat it as the safe option.- Negative strength is experimental. Great for "make it not look like this," unpredictable otherwise.
reference_latents_methodis Flux-only. Other models ignore it harmlessly, so don't sweat the key not mattering on Wan.
The masking-of-ref-latents idea is genuinely novel - nobody else in the ecosystem does it, which means there's no community-validated baseline. Test the defaults on your own use case, then fiddle. That's the whole point of the node.
Inputs (56)
| Name | Type | Default | Description |
|---|---|---|---|
| conditioning | CONDITIONING | — | |
| vae | VAE | — | |
| image_1 | IMAGE | — | |
| max_megapixels | FLOAT | 1.00.1–4 | Caps each ref image by area. Downscales only — small images pass through. Lower = faster (fewer attention tokens). |
| mask_fill_mode | COMBO | pixel_grey | How masked-out regions are neutralised before the model attends to the ref. pixel_grey: replace masked pixels with 0.5 grey before VAE encode. In-distribution; the masked latent has soft uniform signal. latent_zero: encode full image, then zero the latent at masked positions. Constant K/V at those tokens (= layer bias) so attention distributes uniformly over them. Spiritual equivalent of 'transparent'. latent_noise: same as latent_zero but fills with Gaussian noise instead of zeros. Different attention shape — random K/V means no Q matches strongly, model weakly ignores those tokens. |
| image_2opt | IMAGE | — | |
| image_3opt | IMAGE | — | |
| image_4opt | IMAGE | — | |
| mask_1opt | MASK | Optional explicit mask for image 1. Overrides this image's auto-mask config below. | |
| mask_2opt | MASK | Optional explicit mask for image 2 (overrides auto-mask). | |
| mask_3opt | MASK | Optional explicit mask for image 3 (overrides auto-mask). | |
| mask_4opt | MASK | Optional explicit mask for image 4 (overrides auto-mask). | |
| image1_strengthopt | FLOAT | 0.85-5–50 | Per-image strength (signed). 1.0 = stock ReferenceLatent strength. 0.85 = empirical sweet spot. 0 = bypass this image entirely. Negative = anti-reference (model pulled away from this ref's features). |
| image1_faceopt | BOOLEAN | false | Face skin |
| image1_hairopt | BOOLEAN | false | Hair |
| image1_bodyopt | BOOLEAN | false | Body skin |
| image1_clothesopt | BOOLEAN | false | Clothes |
| image1_backgroundopt | BOOLEAN | false | Background (tick to use the background only — handy for environment refs) |
| image1_ignore_areaopt | COMBO | none | Exclude a side strip from the auto-mask. Useful when multiple subjects are in frame. |
| image1_featheropt | INT | 00–200 | Soften mask edges by N pixels (0 = sharp). 10-30 is usually enough. |
| image1_growopt | INT | 0-200–200 | Grow (>0) or shrink (<0) the mask by N pixels. Useful for tucking or extending the masked area beyond what MediaPipe detected. |
| image1_start_percentopt | FLOAT | 0.0000–1 | Fraction of denoising at which this image's ref starts applying. 0 = active from the very first step. |
| image1_end_percentopt | FLOAT | 1.0000–1 | Fraction of denoising at which this image's ref stops applying. 1 = active through the last step. For Flux2/Klein 9B, style/identity signal concentrates at the clean end of denoising — try start=0.6, end=1.0 to apply the ref only at the late (clean) timesteps and let the noisy/early timesteps freely follow your prompt's composition. |
| image2_strengthopt | FLOAT | 0.85-5–50 | Per-image strength (signed). 1.0 = stock ReferenceLatent strength. 0.85 = empirical sweet spot. 0 = bypass this image entirely. Negative = anti-reference (model pulled away from this ref's features). |
| image2_faceopt | BOOLEAN | false | Face skin |
| image2_hairopt | BOOLEAN | false | Hair |
| image2_bodyopt | BOOLEAN | false | Body skin |
| image2_clothesopt | BOOLEAN | false | Clothes |
| image2_backgroundopt | BOOLEAN | false | Background (tick to use the background only — handy for environment refs) |
| image2_ignore_areaopt | COMBO | none | Exclude a side strip from the auto-mask. Useful when multiple subjects are in frame. |
| image2_featheropt | INT | 00–200 | Soften mask edges by N pixels (0 = sharp). 10-30 is usually enough. |
| image2_growopt | INT | 0-200–200 | Grow (>0) or shrink (<0) the mask by N pixels. Useful for tucking or extending the masked area beyond what MediaPipe detected. |
| image2_start_percentopt | FLOAT | 0.0000–1 | Fraction of denoising at which this image's ref starts applying. 0 = active from the very first step. |
| image2_end_percentopt | FLOAT | 1.0000–1 | Fraction of denoising at which this image's ref stops applying. 1 = active through the last step. For Flux2/Klein 9B, style/identity signal concentrates at the clean end of denoising — try start=0.6, end=1.0 to apply the ref only at the late (clean) timesteps and let the noisy/early timesteps freely follow your prompt's composition. |
| image3_strengthopt | FLOAT | 0.85-5–50 | Per-image strength (signed). 1.0 = stock ReferenceLatent strength. 0.85 = empirical sweet spot. 0 = bypass this image entirely. Negative = anti-reference (model pulled away from this ref's features). |
| image3_faceopt | BOOLEAN | false | Face skin |
| image3_hairopt | BOOLEAN | false | Hair |
| image3_bodyopt | BOOLEAN | false | Body skin |
| image3_clothesopt | BOOLEAN | false | Clothes |
| image3_backgroundopt | BOOLEAN | false | Background (tick to use the background only — handy for environment refs) |
| image3_ignore_areaopt | COMBO | none | Exclude a side strip from the auto-mask. Useful when multiple subjects are in frame. |
| image3_featheropt | INT | 00–200 | Soften mask edges by N pixels (0 = sharp). 10-30 is usually enough. |
| image3_growopt | INT | 0-200–200 | Grow (>0) or shrink (<0) the mask by N pixels. Useful for tucking or extending the masked area beyond what MediaPipe detected. |
| image3_start_percentopt | FLOAT | 0.0000–1 | Fraction of denoising at which this image's ref starts applying. 0 = active from the very first step. |
| image3_end_percentopt | FLOAT | 1.0000–1 | Fraction of denoising at which this image's ref stops applying. 1 = active through the last step. For Flux2/Klein 9B, style/identity signal concentrates at the clean end of denoising — try start=0.6, end=1.0 to apply the ref only at the late (clean) timesteps and let the noisy/early timesteps freely follow your prompt's composition. |
| image4_strengthopt | FLOAT | 0.85-5–50 | Per-image strength (signed). 1.0 = stock ReferenceLatent strength. 0.85 = empirical sweet spot. 0 = bypass this image entirely. Negative = anti-reference (model pulled away from this ref's features). |
| image4_faceopt | BOOLEAN | false | Face skin |
| image4_hairopt | BOOLEAN | false | Hair |
| image4_bodyopt | BOOLEAN | false | Body skin |
| image4_clothesopt | BOOLEAN | false | Clothes |
| image4_backgroundopt | BOOLEAN | false | Background (tick to use the background only — handy for environment refs) |
| image4_ignore_areaopt | COMBO | none | Exclude a side strip from the auto-mask. Useful when multiple subjects are in frame. |
| image4_featheropt | INT | 00–200 | Soften mask edges by N pixels (0 = sharp). 10-30 is usually enough. |
| image4_growopt | INT | 0-200–200 | Grow (>0) or shrink (<0) the mask by N pixels. Useful for tucking or extending the masked area beyond what MediaPipe detected. |
| image4_start_percentopt | FLOAT | 0.0000–1 | Fraction of denoising at which this image's ref starts applying. 0 = active from the very first step. |
| image4_end_percentopt | FLOAT | 1.0000–1 | Fraction of denoising at which this image's ref stops applying. 1 = active through the last step. For Flux2/Klein 9B, style/identity signal concentrates at the clean end of denoising — try start=0.6, end=1.0 to apply the ref only at the late (clean) timesteps and let the noisy/early timesteps freely follow your prompt's composition. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| conditioning | CONDITIONING | — |