SELECT project(...) as x, project(...) as y
FROM model, vertex, camera, transform
WHERE clockwise AND clipped IN BETWEEN -1 AND 1
[1]: https://static.laszlokorte.de/sql3d/A good reference for exactly what I mean would be the demoscene (both back then and now). You can watch a thousand of those and be totally underwhelmed, but every now and then you get one that totally blows your mind.
There's nothing wrong with seeking novelty, but there is something wrong being jaded about it.

A path tracer written entirely as ClickHouse SQL queries, rendering straight to a PNG
via ClickHouse's PNG output format. No UDFs and no external code โ a single SELECT
computes every pixel.
It renders the word ClickHouse as glassy, chrome lettering โ in the spirit of Andrew Kensler's famous Pixar business-card ray tracer โ and, in the scene above, sets it floating over a procedurally generated landscape, reflecting the terrain and casting shadows on the hills.
See also:
The whole renderer lives in one query:
numbers_mt(width * height * samples) produces one row per
(pixel, sample); samples are averaged with GROUP BY pixel, and the output columns
r, g, b (in [0, 1]) plus explicit x, y coordinate columns (pixel % width,
intDiv(pixel, width)) are written to the PNG output format. The explicit coordinates let
the writer place each pixel by its position, so the rows need no ORDER BY and the heavy
per-pixel work stays parallel across all cores.Tuple(Float64, Float64, Float64); dotProduct,
L2Normalize, tuplePlus, tupleMultiplyByNumber, โฆ do the linear algebra, wrapped in
short lambda aliases (va, vs, vm, vd, vn, vc, vref).arrayFold. Every ray is advanced exactly one mirror bounce per
fold step over range(maxDepth) โ a loop inside each row, so rows stay independent and
the render parallelizes across all CPU cores. (The first version used a WITH RECURSIVE
CTE instead โ see the queries below.)let-bindings via arrayMap. ClickHouse WITH lambdas are call-by-name, so passing a
value as a parameter re-expands the expression and blows up the query tree. Intermediates
are therefore bound by value with arrayMap(x -> body, [expr])[1], a one-element-array
"let".l, i, k, H,
u, the bar of e).C, c, o, u, s, e), ray-marched through their
signed-distance field; the openings of C/c/s/e are a box subtracted from the ring.i, plus a chrome "planet" that is a sphere minus a sphere.So the scene exercises boxes, cylinders, tori and spheres, with CSG union, difference (the planet and the letter openings) and a ray-marched distance field (the tori).
A height field z = amp ยท fBm(x, y), where fBm sums several octaves of lattice value-noise.
Camera rays are ray-marched against it โ the march skips the empty air (it starts where the
ray first drops to the terrain's maximum height) and linearly interpolates the surface
crossing, so it is both fast and free of step-banding. It is shaded with a height color ramp
(water โ sand โ grass โ rock โ snow), a warm sun plus cool sky-ambient model, marched shadows
(terrain self-shadow and the letters' cast shadows), and distance fog into the sky.
ClickBulb โ a desk lamp built entirely from spheres hops in, leaps behind the banner, rakes its light through the letter gaps, then pokes its head through to peer at you. Every frame is the same ClickHouse SQL query, run once per frame (full-quality video).
![]() |
![]() |
| Pixar homage โ the letters as a union of sphere primitives, chrome over a checkerboard. | CSG primitives โ the letters carved from cylinders, tori and spheres. |
![]() |
![]() |
| Perlin terrain โ a standalone ray-marched height field. | Combined โ ClickHouse over the terrain (the hero image above). |
Every file in queries/ is complete and self-contained, and parameterized: the
image size comes from ClickHouse's image-output settings (read in SQL with getSetting) and the
samples per pixel from a {SAMPLES:UInt32} query parameter โ one query renders any resolution.
Render one with:
clickhouse local --output_format_image_width 2560 --output_format_image_height 1200 \
--param_SAMPLES 8 --queries-file queries/clickhouse_terrain.sql > out.png
| Query | Scene | Resolution |
|---|---|---|
clickhouse_raytracer.sql |
Pixar homage, WITH RECURSIVE bounce loop |
640 ร 256 |
clickhouse_raytracer_loop.sql |
Same scene, arrayFold loop (parallel, faster) |
640 ร 256 |
clickhouse_raytracer_primitives.sql |
Letters carved from CSG primitives | 1280 ร 512 |
terrain.sql |
Perlin-noise terrain | 896 ร 504 |
clickhouse_terrain.sql |
ClickHouse over the terrain (hero image) | 2560 ร 1200 |
The queries are emitted by the Python generators in generators/; the scene and
bounce depth are baked at generation time, while image size and samples per pixel stay runtime
parameters of the emitted query. For example, to re-create the hero image:
python3 generators/gen_combined.py 2560 1200 8 2 > scene.sql # depth 2; W/H/samples are runtime
clickhouse local --output_format_image_width 2560 --output_format_image_height 1200 \
--param_SAMPLES 8 --queries-file scene.sql > scene.png
The sphere-banner generators (gen.py and the faster
gen_fold.py) take an optional 5th argument: the text to render. It is
laid out from the 7-row bitmap font in generators/font.py (uppercase AโZ,
digits, and common punctuation; the original mixed-case "ClickHouse" glyphs are preserved, so the
default render is unchanged), and the camera, light, and chrome sphere are recentered on the
banner automatically.
python3 generators/gen_fold.py 640 256 16 4 "HELLO SQL" > hello.sql
clickhouse local --output_format_image_width 640 --output_format_image_height 256 \
--param_SAMPLES 16 --queries-file hello.sql > hello.png
Preview a banner as ASCII art without rendering: python3 generators/font.py "HELLO SQL".
See the benchmark.
Inspired by Andrew Kensler's business-card ray tracer and Paul Heckbert's minimal ray tracers โ re-imagined as pure ClickHouse SQL.
Creative Commons Attribution-NonCommercial-ShareAlike 4.0, the same license as ClickBench.