Nodes/Jovi_GLSL/FILTER RANGE (JOV_GL)
ComfyUI Node

FILTER RANGE (JOV_GL)

Keep only the pixels inside a color range — a cheap chroma-key-ish mask maker

By Amorano·Created 2 years ago·Updated about a year ago· 20
FILTER RANGE (JOV_GL)
  • image
  • start
  • end
  • RGBA
  • RGB
  • MASK
FRAGMENT// name: FILTER RANGE // desc: Select pixels from start color through end color. Maintains alpha/mask. // category: FILTER uniform sampler2D image; // | RGB(A) image uniform vec3 start; // 0,0,0; 0; 1; 0.01; rgb | Start of the Range uniform vec3 end; // 1,1,1; 0; 1; 0.01; rgb | End of the Range void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord / iResolution.xy; vec4 color = texture(image, uv); bool isInside = all(greaterThanEqual(color.rgb, start)) && all(lessThanEqual(color.rgb, end)); fragColor = vec4(vec3(isInside ? 1.0 : 0.0), color.a); }

Sometimes you don't need a fancy segmentation model. You need "give me everything that's roughly this color, and nothing else." That's this node: you define a color range with a start point and an end point, and it keeps exactly the pixels that fall inside that box, turning everything else black. It's crude compared to a real background-removal or segmentation pass, but it's instant, it runs on the GPU, and for clean, flat-color subjects it's often all you need.

How it works

Per pixel, the shader checks whether the RGB values are inside the box defined by start and end - every channel must be greater than or equal to start and less than or equal to end. Inside pixels become white, outside pixels become black, and crucially the input's alpha is carried through untouched, so any existing mask or transparency survives. Each color is a VEC3 in normalized 0–1 space, so white is (1, 1, 1) and black is (0, 0, 0).

That "keeps alpha" behavior is the detail that makes it usable in a real workflow: you can run it on an RGBA image and the filter only touches color, not transparency.

The inputs

  • image - RGB, RGBA, or MASK input.
  • start - the low corner of the color box, default black (0, 0, 0).
  • end - the high corner, default white (1, 1, 1). With the defaults, every pixel is inside the box, so the output is all white - which is a decent hint that you're expected to change these.

Outputs are the pack standard: RGBA, RGB, and MASK. The MASK output is the one you'll almost always want - a pure 0/1 selection you can feed straight into compositing, inpainting, or a ControlNet-style conditioning path.

Install

One-time pack install. Via ComfyUI Manager, search Jovi_GLSL; or:

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

Restart ComfyUI. The pack's standard dependencies apply (PyOpenGL, glfw, opencv-contrib-python, cozy_comfyui from git) and it needs an OpenGL context. No models, no keys. It lives in JOVI_GLSL 🌈 → FILTER.

Where people get burned

This is a hard box filter, not a fuzzy chroma key. There's no feathering and no spill handling, so real-world footage with soft shadows and camera noise will give you jagged, speckled selections - that's expected, not a bug. It shines on synthetic renders, UI elements, logos, and other flat-color material. If your subject has gradients, widen the range until the noise comes back, then tighten it again; the GPU makes iteration cheap, so just drag and look.

CategoryJOV_GL 🌈/FILTER

Inputs (4)

NameTypeDefaultDescription
imageoptIMAGERGB(A) image
startoptVEC30,0,0Start of the Range
endoptVEC31,1,1End of the Range
FRAGMENToptSTRING// name: FILTER RANGE // desc: Select pixels from start color through end color. Maintains alpha/mask. // category: FILTER uniform sampler2D image; // | RGB(A) image uniform vec3 start; // 0,0,0; 0; 1; 0.01; rgb | Start of the Range uniform vec3 end; // 1,1,1; 0; 1; 0.01; rgb | End of the Range void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord / iResolution.xy; vec4 color = texture(image, uv); bool isInside = all(greaterThanEqual(color.rgb, start)) && all(lessThanEqual(color.rgb, end)); fragColor = vec4(vec3(isInside ? 1.0 : 0.0), color.a); }

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.