Paints a picture using every 24-bit colour exactly once: a 4096×4096 image with 16,777,216 pixels, one per colour. It starts with the colours in order and only ever swaps pixels, so each colour stays unique. A swap is kept when it brings the image closer to a target picture, and over billions of swaps the picture appears. Inspired by allrgb.com.
It's a Godot 4.7 project with no native code. The solvers run as fragment shaders on the GPU, so it works the same on the desktop and in a browser (WebGL 2).
For a complete description of the project, visit the project's webpage.
| Folder | What lives there |
|---|---|
| project/ | The Godot project: the scene, scripts, shaders, fonts, the default target and the headless test scripts. |
| tools/ | web_preview.sh, which exports the web build and serves it on the local network, and export_desktop.sh, which builds the zipped Linux and Windows downloads into export/, and screenshots.sh, which captures the website's images from the real window into export/screenshots/. |
- A pass pairs every pixel with one partner, at its index XOR a random mask, after a random wrapping shift so no fixed grid forms. Each pair is its own partner's partner, and both pixels reach the same decision, so the image stays a permutation of every colour. One pass tries about 8 million swaps.
- Ping-pong: two viewports take turns, each drawing the next pass from the other's image. Pixels are read with
texelFetchinto 8-bit-per-channel viewports, with no filtering or colour conversion, so colours are exact. - The methods, each judging a swap by the sum of both pixels' errors before and after:
- RGB Error: squared distance in red, green and blue.
- HSV Error: hue, saturation and value, weighted so value counts most and hue least. Hue wraps round as a circle, and counts only as much as the greyer of the two colours is saturated.
- Area Averaging (RGB) and (HSV): compare the average of each 3×3 window a swap touches with the target's. A pass only swaps pixels 4 apart, so no window holds two swaps and every decision is exact, and the error can only fall. HSV averages points in the HSV cone, so hues average round the circle.
- The target's 3×3 window averages are worked out once per target into a half-float image, and Area Averaging (HSV) converts the image to cone points once per pass.
- Counters: about once a second a shader sums the pixels that changed in one pass, and their distance from the target, in 32×32 blocks, and only those block sums are read back.
- Godot 4.7.2 (the editor binary). CMake looks for it on
PATHand in~/Desktop. If it's somewhere else, pass-DGODOT_EXECUTABLE=/path/to/godotwhen configuring. - CMake 3.28+ and Ninja, only to run the tests.
- xvfb (
xvfb-run) for the tests that render. Headless Godot has no real renderer, so those run with OpenGL on a virtual display.
cmake --preset dev
ctest --preset dev| CTest name | What it proves |
|---|---|
godot_import |
A fresh checkout imports. |
godot_smoke |
The real main scene loads and themes itself, and a SubViewport reads back exactly. |
godot_framing |
Framing renders the square into the target the right way round, a quarter turn moves it clockwise, and the square stays inside the picture. |
godot_solver |
On a 64² image, every method keeps every colour exactly once, never raises its error and at least halves it. The GPU's swap count matches the CPU's, and saved results load back exactly while broken ones are refused. |
project/tools/bench.gd times each method's passes at 4096² on the real display, with V-Sync off:
~/Desktop/Godot_v4.7.2-stable_linux.x86_64 --path project -s tools/bench.gd -- 600~/Desktop/Godot_v4.7.2-stable_linux.x86_64 --path project # run it
~/Desktop/Godot_v4.7.2-stable_linux.x86_64 -e --path project # or open it in the editorIt starts paused, with the colours in order and the bundled garden photo as the target. It needs about 200 MB of GPU memory.
Controls:
- Load image… picks a new picture. Frame target switches the view to the picture behind a dashed square: drag to move it, the wheel or a pinch to scale, and the slider or Rotate 90° (R) to turn it. Fit (F) fills the square with the picture's middle. The square becomes the target.
- Method picks the solver, with a description under it. Size picks 4096² (every 24-bit colour) or 2048², which holds every colour with 7 bits of red, 8 of green and 7 of blue in a quarter of the memory; phones start at 2048². Reset pixels starts again from every colour in order.
- Save result… (Ctrl+S) saves a PNG; only PNG keeps every colour exact. Load result… carries on from a saved one, after checking it holds every colour once.
- Playback, at the view's top left: Pause (Space), then Slow (10 passes a second), Fast (one a frame) and Max (V-Sync off) (1 to 3). While paused, the step buttons (1 to 3) run 1, 10 or 100 passes.
- Show (V cycles) picks Result, Target or Error. Error is brightness alone: black matches the target, white is furthest off. The thumbnail at the bottom left cycles through the same three with a click.
- Counters show passes, swaps in the last measured pass, an estimate of all swaps and swaps a second, and Mismatch, the mean distance from the target's colours out of the greatest possible.
- Left or middle drag, a one- or two-finger drag or the arrow keys pan. The wheel, a pinch, + and -, or the buttons at the view's bottom right zoom, and F or the last of them fits the image. The image can't be panned or zoomed out of sight.
- The handle halfway down the view's left edge hides and shows the controls. Below 640 pixels wide they float over the view, folded away at first, and below 900×560 the whole UI shrinks to fit, down to 60%.
- Help (H) lists every control, including touch. More by TroyDev, at the bottom of the controls, is hidden by
?embedded=1. The theme follows troydev.co.uk's light and dark colours and fonts: dark unless the system or browser prefers light.
Fonts: Lusitana by Ana Paula Megda and Lato by Łukasz Dziedzic, under the SIL Open Font License (see project/assets/fonts/).
Each item is one commit, which ticks its box.
- README with this list.
- Web export and a phone layout. A single-threaded web export for troydev.co.uk, loading pictures and results through the browser.
?embedded=1hides More by TroyDev, and?theme=dark|lightpicks the theme. In a narrow window, the side panel floats over the view. - Linux and Windows exports, zipped for the website's downloads.
- Screenshots for the website. Light and dark pairs from the real window, a thumbnail, each method's result at 2048², and maybe a clip of a run converging.
Later:
- A 2048² half size for phones and small GPUs.
- A Windows icon and metadata (rcedit under wine).
- Graphs of mismatch and swaps over time.
Known bugs:
- Area Averaging (HSV) leaves blue, teal and purple patches over green parts of the target, such as the hedges, while the rest looks right.
