cellshade

cellshade · effects · schema v1

Cel-shader (toon / retro-video-game) video PROCESSOR. Takes a video input and emits a cel-shaded version: the colour is QUANTIZED to a retro N-bit palette and the salient CONTOURS are inked in as BLACK outline strokes (a reused EDGES Sobel pass). STATELESS per frame — the look moves/transforms live with the source. Pipeline: (1) quantize the colour to the chosen bit depth; (2) run a 3×3 Sobel on the input's Rec. 601 LUMINANCE (the exact EDGES algorithm — same normalisation, THRESHOLD gate, THICKNESS dilation) to get a 0/1 edge mask; (3) ink the mask as black lines over the quantized colour: color = mix(quantizedColor, vec3(0.0), edge). BITS is a 5-step DISCRETE knob (the param is the step INDEX 0..4; the card shows the bit value + colour count, and the matching CV input uses a discrete cvScale so it snaps to the 5 steps) mapping to RETRO TOTAL COLOR-DEPTH: 1-bit=2 colours, 2-bit=4, 4-bit=16 (default), 8-bit=256, 16-bit=65536. The quantization is done WELL, per-depth: the LOW depths (1/2/4-bit = 2/4/16 colours) use LUMA-BAND quantization — convert RGB→HSV, keep HUE + SATURATION (gently posterized for the 16-colour budget), quantize only BRIGHTNESS (V) into a few bands, reconstruct RGB — so the result reads as hand-painted flat tonal bands (the cel look) rather than the channel-clipped rainbow a naive per-channel RGB floor produces; 8-bit uses the authentic console RGB 3-3-2 allocation (8 R / 8 G / 4 B levels = 256) and 16-bit the RGB 5-6-5 allocation (32 R / 64 G / 32 B = 65536). THRESHOLD (0..1, default 0.2) gates which contours get inked — raise it to ink only the strongest edges, lower it for more outline. THICKNESS (1..8 px, default 2) dilates the ink stroke wider (morphological MAX, same as EDGES). THRESHOLD / THICKNESS / BITS each have a matching CV input (port id == param id). IN takes RGB; OUT is video — patch a source (CAMERA / VIDEOBOX / SHAPES / a generator) → IN, OUT → OUTPUT or a video mixer; sweep BITS for the colour-depth retro step, THRESHOLD/THICKNESS to tune the ink.

cellshade is a cel-shader: it remakes the incoming video as a flat, toon/retro-game look by quantizing the colour to a small palette and inking the salient contours as solid black outlines. It quantizes two ways depending on the chosen bit depth — low depths (2/4/16 colours) posterize in HSV: brightness is collapsed into a few flat tonal bands while hue and saturation are kept (fully at 2/4 colours, gently stepped at the 16-colour budget) for the hand-painted cel look, whereas the 8-bit and 16-bit steps use the authentic console RGB 3-3-2 and 5-6-5 per-channel allocations for the SNES-era hi-colour look. A reused Sobel edge pass (same gate and width as the EDGES module) finds the luminance contours and composites them as black ink over the quantized colour. It is stateless per frame, so the effect tracks the live source with no feedback; pick a low bit depth for painterly cel art or a high one for retro hi-colour, then dial Thresh/Thick to control how heavily it inks.

the faceplate

cellshadeinvideothresholdcvthicknesscvbitscvoutvideoaudiocvgatepitch
4 inputs · 1 outputs · 3 params

inputs

idcablewhat it does
invideoThe RGB video source to cel-shade. Its colour is quantized and its luminance contours are inked as black outlines; with no input the output is solid black.
RGB video stream
thresholdcvCV input that modulates Thresh, sweeping the edge gate linearly over its full 0..1 range — higher CV inks fewer, stronger contours.
control voltage (CV); modulates threshold (additive offset — ±1 CV sweeps the full range, centered on the knob)
thicknesscvCV input that modulates Thick, sweeping the ink stroke width linearly over its 1..max px range — higher CV makes the black outlines wider.
control voltage (CV); modulates thickness (additive offset — ±1 CV sweeps the full range, centered on the knob)
bitscvCV input that modulates Bits using a discrete cvScale, so the CV snaps to the 5 colour-depth steps (1/2/4/8/16-bit) rather than sweeping continuously.
control voltage (CV); modulates bits (integer buckets — CV selects a discrete step)

outputs

idcablewhat it does
outvideoThe cel-shaded video frame: the quantized retro-palette colour with black ink strokes drawn over the detected contours.
RGB video stream

params

idlabelrangedefaultcurve
thresholdThresh0..1linear
thicknessThick1..?pxlinear
bitsBits0..?discrete

controls

controlwhat it does
BitsBits — a 5-step discrete control selecting colour depth: 1-bit (2 colours), 2-bit (4), 4-bit (16), 8-bit (256, RGB 3-3-2), 16-bit (65536, RGB 5-6-5). Default is 4-bit/16 colours; the card shows the current bit value and colour count. Low steps give a flat luma-band cel look, high steps the hi-colour console look.
ThickThick — ink stroke width in pixels (1..max, default 2, shared with EDGES). It dilates the edge mask, so higher values make the black outlines wider; 1 is a thin single-pixel line.
ThreshThresh — the edge gate (normalized Sobel gradient magnitude, 0..1, default 0.2, shared with EDGES). Lower inks more/weaker contours; higher inks only the strongest edges, fewer lines.

source

cellshade.ts on GitHub.

Generated from packages/web/src/lib/{audio,video}/module-registry.ts · repo