Nodes/Jovi_GLSL/PIXELATE (JOV_GL)
ComfyUI Node

PIXELATE (JOV_GL)

Pixelate that actually holds up — blocky retro without the shimmer

By Amorano·Created 2 years ago·Updated about a year ago· 20
PIXELATE (JOV_GL)
  • image
  • RGBA
  • RGB
  • MASK
amount32.0
FRAGMENT// name: PIXELATE // desc: Pixelate input image // category: COLOR uniform sampler2D image; // | RGB(A) image uniform float amount; // 32;0;255;0.1 | Pixel data range allowed void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord / iResolution.xy; float d = 1.0 / amount; float ar = iResolution.x / iResolution.y; float u = floor( uv.x / d ) * d; float v = floor( uv.y / d ) * (ar / amount); fragColor = texture( image, vec2( u, v ) ); }

Pixelation is one of those effects every image editor does badly by default: it averages or resamples in a way that smears rather than reads as "retro blocky." This node does the classic shader version - it snaps the sample coordinates to a grid before sampling, so each block is a clean, flat sample of the original at that spot. No smearing, no bleed, just honest Minecraft-chic blocks. It's a one-input, one-knob node, and it's the most straightforward way to get that look inside a ComfyUI workflow instead of bouncing out to another tool.

How it works

The shader divides the UV by a cell size derived from amount, floors the result to snap onto a grid, and samples the image at the snapped coordinates. Because it's a pure per-pixel GPU operation, it re-renders instantly as you drag the slider, which makes it great for dialing in exactly how aggressive the effect is. The amount input (default 32, range 0–255) is the block size in pixels - bigger number, bigger blocks. The aspect ratio is handled internally, so blocks stay square-ish rather than stretching into rectangles.

The inputs

  • image - RGB, RGBA, or MASK input.
  • amount - the block size, default 32. This is the entire creative control, and honestly that's the right design for this effect.

Outputs are the pack standard: RGBA, RGB, and MASK. The MASK output is surprisingly useful - pixelating a mask gives you chunky "stepped" selections that read as deliberate graphic design rather than accidental noise.

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. Standard pack deps (PyOpenGL, glfw, opencv-contrib-python, cozy_comfyui from git), needs an OpenGL context. No models, no keys. Under **JOVI_GLSL 🌈 → COLOR`.

Gotchas

The amount tooltip says "Pixel data range allowed," which is a copy-paste from the posterize node - it's a block size, not a range. And a tip for the look people actually want: pixelate after you've done your heavy color work, because downsampling wipes out fine detail and there's no undo inside a single node. Also, at extreme amounts (way above your image's resolution) you get a handful of giant blocks, which is either a fun poster look or a sign you overshot.

CategoryJOV_GL 🌈/COLOR

Inputs (3)

NameTypeDefaultDescription
imageoptIMAGERGB(A) image
amountoptFLOAT32.00–255Pixel data range allowed
FRAGMENToptSTRING// name: PIXELATE // desc: Pixelate input image // category: COLOR uniform sampler2D image; // | RGB(A) image uniform float amount; // 32;0;255;0.1 | Pixel data range allowed void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord / iResolution.xy; float d = 1.0 / amount; float ar = iResolution.x / iResolution.y; float u = floor( uv.x / d ) * d; float v = floor( uv.y / d ) * (ar / amount); fragColor = texture( image, vec2( u, v ) ); }

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.