Nodes/Jovi_GLSL/BLEND LINEAR (JOV_GL)
ComfyUI Node

BLEND LINEAR (JOV_GL)

The boring crossfade node you'll actually reach for

By Amorano·Created 2 years ago·Updated about a year ago· 20
BLEND LINEAR (JOV_GL)
  • imageA
  • imageB
  • RGBA
  • RGB
  • MASK
blend_amt0.50
FRAGMENT// name: BLEND LINEAR // desc: Simple linear blend between two images. Will stretch/shrink images to fit. // category: COMPOSE uniform sampler2D imageA; // | MASK, RGB or RGBA uniform sampler2D imageB; // | MASK, RGB or RGBA uniform float blend_amt; // 0.5; 0; 1; 0.01 | Scalar blend amount void mainImage( out vec4 fragColor, vec2 fragCoord ) { vec2 uv = fragCoord / iResolution.xy; vec4 col_a = texture(imageA, uv); vec4 col_b = texture(imageB, uv); fragColor = mix(col_b, col_a, blend_amt); }

There's nothing glamorous about a linear blend. You have image A, image B, and a slider that goes from one to the other. That's the whole node - and it's exactly why you'll keep grabbing it. When you're wiring up a workflow that crossfades between two renders, eases from a base image into an edited pass, or builds a transition for a video frame sequence, a one-input crossfade beats rigging up a blend mode chain every time.

How it works

Like everything in Jovi_GLSL, this is a GLSL fragment shader running on your GPU. For each pixel it samples both images at the same UV coordinate and returns mix(imageB, imageA, blend_amt) - a straight, mathematically honest crossfade with no gamma fiddling and no blend-mode surprises. The description notes it "stretches/shrinks images to fit," which is worth knowing: if A and B don't match in resolution, the node rescales them to the same canvas rather than erroring out or cropping. For a pack of GPU shaders that's a small mercy, because mismatched inputs are usually where these nodes fall over.

The inputs

  • imageA and imageB - either can be RGB, RGBA, or a MASK. Feed it two masks and you get a blended mask out.
  • blend_amt - 0 to 1, default 0.5. At 0 you get imageB, at 1 you get imageA. Yes, the direction feels slightly backwards the first time you touch it - at the default 0.5 it doesn't matter.

Outputs are the standard pack trio: RGBA (full channels, alpha honored), RGB (alpha stripped, for picky consumers), and MASK (single channel). Since the blend is per-channel, you can also use this as a crude opacity pass: feed the same image into both slots and the slider becomes an opacity control.

Install

Same story as the rest of the pack - install once, use all the nodes:

Via ComfyUI Manager, search Jovi_GLSL. Or manually:

cd ComfyUI/custom_nodes
git clone https://github.com/Amorano/Jovi_GLSL.git
cd Jovi_GLSL
pip install -r requirements.txt

Restart ComfyUI. The requirements include PyOpenGL, glfw, and opencv-contrib-python, and the pack depends on cozy_comfyui (from git, so it moves with upstream). No models, no keys. You'll find the nodes under the JOVI_GLSL 🌈 menu, with this one in the COMPOSE submenu.

Gotchas

Honest crossfades can look flat on images with very different brightness - that's a property of linear mixing, not a bug. And because the shader just samples whatever's under each UV, animating blend_amt frame to frame for a video crossfade works but won't do anything clever about mismatched aspect ratios. Feed it the standard batch workflow and it's a perfectly serviceable transition node.

CategoryJOV_GL 🌈/COMPOSE

Inputs (4)

NameTypeDefaultDescription
imageAoptIMAGEMASK, RGB or RGBA
imageBoptIMAGEMASK, RGB or RGBA
blend_amtoptFLOAT0.500–1Scalar blend amount
FRAGMENToptSTRING// name: BLEND LINEAR // desc: Simple linear blend between two images. Will stretch/shrink images to fit. // category: COMPOSE uniform sampler2D imageA; // | MASK, RGB or RGBA uniform sampler2D imageB; // | MASK, RGB or RGBA uniform float blend_amt; // 0.5; 0; 1; 0.01 | Scalar blend amount void mainImage( out vec4 fragColor, vec2 fragCoord ) { vec2 uv = fragCoord / iResolution.xy; vec4 col_a = texture(imageA, uv); vec4 col_b = texture(imageB, uv); fragColor = mix(col_b, col_a, blend_amt); }

Outputs (3)

NameTypeDescription
RGBAIMAGEFull channel [RGBA] image. If there is an alpha, the image will be masked out with it when using this output.
RGBIMAGEThree channel [RGB] image. There will be no alpha.
MASKMASKSingle channel mask output.