Coyotte's Palette Canvas
Paint your lighting before the sampler ever runs
- vae
- background
- gradient
- shape
- image
- latent
Want golden-hour light on demand without a paragraph of lighting prompt? Build it as a picture. PaletteCanvasGradient draws a color gradient (plus an optional geometric "light source") on a blank canvas, VAE-encodes it into a latent, and hands you that latent to start your sampler from. At a lowered denoise it acts as a lighting and mood map: the image keeps the canvas's color flow and illumination instead of inventing its own. It's not a relighter in the IC-Light sense - no light transport physics - it's composition steering, and for setting a scene's mood it's a genuinely cheap trick.
How it works
Under the hood it's img2img wearing a fake mustache. The node builds an RGB tensor at your width/height, fills it with the background color, then does two optional paint passes:
- Gradient - linear blend from
backgroundtogradientcolor alonggradient_angle(0° = right, 90° = up).dither(on by default) adds a tiny bit of noise so the smooth ramp doesn't band when the VAE squashes it. - Shape - a filled
circle,square,triangle, orrectanglein theshapecolor, positioned and scaled byshape_offset_x/yandshape_scale. The X axis is corrected for aspect ratio, so a circle stays circular at 896×1152, andshape_scale_x/ylet you stretch it into an elliptical window light or a neon strip.
If you plug a vae in, it runs vae.encode() on the canvas and returns the latent. That's the whole trick: you're starting the sampler from a synthetic image instead of pure noise, so at partial denoise the model keeps the color structure.
The inputs that actually matter
width/height- your output resolution (default 512; pick the aspect you're generating at).background+gradient+gradient_angle- the two colors define the whole palette sweep. Warm to cool = sunset; dark to light = rim light.shape+shape_type+shape_scale- the "light source". Bright circle on a dark field reads as a spotlight.dither- leave it on; it's what stops VAE banding.vae- optional, but this is the one that makes the whole trick exist. Without it, thelatentoutput is nothing and you've only got a picture.
Wiring it
Outputs are image and latent. The move is: latent → KSampler's latent_image input, prompt wired as usual, and set denoise to 0.87–0.95. Below that the canvas dominates composition; 0.93–0.95 is the sweet spot where the AI follows your light but still paints natural detail; nudge past 0.96 and the canvas is just a mood suggestion. At denoise 1.0 you're back to pure noise and it does nothing. The image output is useful if you want to preview the canvas or push it through other nodes first.
There's a drag-to-set gradient direction widget on the node - click-drag the angle ring instead of typing degrees.
Install
ComfyUI Manager → "Install Custom Nodes" → search Palette Canvas, or:
cd ComfyUI/custom_nodes
git clone https://github.com/c0yotte/ComfyUI-PaletteCanvas
Restart ComfyUI. That's it - no model downloads, no extra Python packages (its requirements.txt is literally a comment; it only uses torch/numpy that ship with ComfyUI), no API key. It's one of the most installable nodes you'll meet.
Gotchas
- Forget the VAE and you get nothing but a pretty gradient. The latent only exists when
vaeis connected - wire your checkpoint's VAE into the node or the sampler never sees your light map. - The defaults are ugly on purpose. You start with a red→blue gradient and a green circle; set real colors or you'll be confused by a garish first run.
- Watch your denoise. 1.0 ignores the canvas entirely; that's the #1 "why isn't this doing anything" report.
- The node prints shape offsets to the console - harmless debug noise.
Where people get burned is expecting Photoshop-level relighting from it. It won't relight a subject you already rendered; it sets the lighting before generation. For that, it's a compact, zero-dependency way to steer mood that beats begging your prompt for a sunset.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| width | INT | 5128–8192 | — |
| height | INT | 5128–8192 | — |
| use_gradient | BOOLEAN | false | — |
| use_shape | BOOLEAN | false | — |
| vaeopt | VAE | — | |
| backgroundopt | COLOR | #ff0000 | — |
| gradientopt | COLOR | #0000ff | — |
| shapeopt | COLOR | #00ff00 | — |
| shape_typeopt | COMBO | 4 options: circle, square, triangle, rectangle | |
| shape_scaleopt | FLOAT | 0.500.1–2 | — |
| shape_scale_xopt | FLOAT | 0.00-2.5–2.5 | — |
| shape_scale_yopt | FLOAT | 0.00-2.5–2.5 | — |
| shape_offset_xopt | FLOAT | 0.00-1–1 | — |
| shape_offset_yopt | FLOAT | 0.00-1–1 | — |
| gradient_angleopt | FLOAT | 00–360 | — |
| ditheropt | BOOLEAN | true | — |
| dither_strengthopt | FLOAT | 0.0200–0.05 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| latent | LATENT | — |