Whisker: Random Cube Grid Generator
Random cube grids — with the coordinates as JSON you can actually act on
- cube_image
- cube_coordinates
A procedural white-on-black grid of squares is a five-minute numpy script, so the thing that makes RandomCubeGrid worth installing is not the image. It's the second output. Alongside the rendered cube_image it emits a JSON string of {x, y, size} coordinates for every cube it placed - which is what turns a pretty pattern into something a downstream node can actually build on.
Where's that useful? Any workflow where you need cube positions and the visual: game-tile layouts, pixel-art composition frames, puzzle or shelf arrangements, or feeding coordinates into a "block grid"-style generator you're wiring up yourself. The README pitches it exactly that way - the JSON is designed to pair with downstream generator nodes, not to sit there looking pretty.
How it works
You give it a grid in units (grid_width × grid_height), and it places white squares at random spots with per-row and per-column gaps chosen randomly between min_*_gap and max_*_gap. Each cube's size is a random fraction of the grid unit, between min_cube_size and max_cube_size. density is the probability a given slot gets a cube at all. output_resolution sets the longest side in pixels and the other side follows the grid's aspect ratio.
The genuinely clever part is the edge handling. first_col_start_row/first_col_end_row and last_col_start_row/last_col_end_row constrain where cubes can appear in the first and last columns, so you can frame the grid - a top border, a bottom border, whatever you need. The first_last_density_toggle decides whether density and gap randomness apply to those edge columns too, or whether they're forced to fill completely.
The inputs that actually matter
seed--1means randomize every run; set a positive number to lock the layout.density- 0 to 1. Low values scatter a few cubes; 0.5 default fills about half the slots.min_cube_size/max_cube_size- cube size in grid units. Equal values give you a uniform grid of equal squares; a spread gives you the organic "random cube" look.output_resolution- the longest side in pixels. This is also your quality lever: cubes are just rectangles of solid white, so the practical limit is how big you need the sheet.
The gotcha that will bite you
cube_coordinates is a STRING, not a list - it's a JSON array serialized as text. ComfyUI won't let you wire a string into a node expecting a list. You'll need a text/JSON viewer node (ShowText and friends) to read it, or a JSON-parsing node to convert it into a structure another custom node can consume. Figure that out before you build the workflow around the coordinates, not after.
Both outputs are always produced - cube_image (a 3-channel IMAGE, white on black) and cube_coordinates.
Installing it
It ships in the Whisker pack:
cd ComfyUI/custom_nodes
git clone https://github.com/nerdywhiskers/ComfyUI-Whisker-Nodes.git
pip install -r ComfyUI-Whisker-Nodes/requirements.txt
or search "ComfyUI-Whisker-Nodes" in ComfyUI Manager and restart. It's under Add Node → whisker-nodes. No models, no downloads, no hidden dependencies - this one runs on numpy and torch alone. If your first result feels off, the odds are the seed or density, not the node.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| grid_width | INT | 101–100 | — |
| grid_height | INT | 51–100 | — |
| output_resolution | INT | 51264–4096 | — |
| min_cube_size | FLOAT | 0.50.1–1 | — |
| max_cube_size | FLOAT | 1.00.1–1 | — |
| first_col_start_row | INT | 30–100 | — |
| first_col_end_row | INT | 70–100 | — |
| last_col_start_row | INT | 20–100 | — |
| last_col_end_row | INT | 80–100 | — |
| min_col_gap | INT | 10–10 | — |
| max_col_gap | INT | 31–10 | — |
| min_row_gap | INT | 10–10 | — |
| max_row_gap | INT | 31–10 | — |
| density | FLOAT | 0.500–1 | — |
| first_last_density_toggle | COMBO | 2 options: enabled, disabled | |
| seed | INT | -1-1–999999 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| cube_image | IMAGE | — |
| cube_coordinates | STRING | — |