← 返回信息流
AI 资讯Hacker News·8 小时前

Ray Tracer in SQL

AI 深度解读

背景

在数据库领域,ClickHouse 以其极致的 OLAP 查询性能著称,通常用于海量数据分析。然而,一个极具实验性质的项目展示了 ClickHouse 的另一面:完全用 ClickHouse SQL 实现路径追踪(Path Tracing)渲染器,无需用户自定义函数(UDF),无需外部代码,仅靠一条 SELECT 语句就能逐像素计算并直接输出 PNG 图像。

该项目灵感来源于 Andrew Kensler 著名的 Pixar 名片光线追踪器(用 C++ 写成,代码精简到可印在名片上)以及 Paul Heckbert 的极简光线追踪器。作者将其重新构想为纯 ClickHouse SQL 实现,渲染了玻璃质感、铬合金风格的 "ClickHouse" 字样,漂浮在程序生成的地形之上,反射地表并在山丘上投下阴影。

核心内容

整体架构

整个渲染器由一条 SQL 查询构成,核心思路是将像素映射为数据行

  • numbers_mt(width * height * samples) 为每个(像素, 采样)组合生成一行数据
  • 通过 GROUP BY pixel 对多次采样取平均,得到最终像素颜色
  • 输出列 r, g, b(范围 [0, 1])配合显式 x, y 坐标列(pixel % widthintDiv(pixel, width))写入 ClickHouse 的 PNG 输出格式
  • 显式坐标让写入器按位置放置像素,因此行无需 ORDER BY,重计算工作可跨所有 CPU 核心并行

3D 数学与光线追踪

  • 向量运算:向量表示为 Tuple(Float64, Float64, Float64),线性代数操作(点积、L2 归一化、向量加减、标量乘法等)通过短 lambda 别名实现(vavsvmvdvnvcvref
  • 光线反弹循环:使用 arrayFold 实现,每次折叠步骤将光线推进一次镜面反弹,循环在每一行内部执行,保持行间独立,渲染可跨所有 CPU 核心并行。早期版本使用 WITH RECURSIVE CTE 实现
  • let 绑定:由于 ClickHouse 的 WITH lambda 采用传名调用(call-by-name),传参会导致表达式重复展开、查询树膨胀。因此使用 arrayMap(x -> body, [expr])[1] 实现按值绑定(one-element-array "let")

场景几何体

场景综合运用了多种几何体与 CSG(构造实体几何)操作:

  • 圆柱体(Cylinders):用于直线笔画(likHue 的横杆)
  • 圆环(Tori):用于圆形字母(Ccouse),通过有符号距离场(SDF)进行光线步进(ray-marched);C/c/s/e 的开口通过从环中减去一个盒子实现
  • 球体(Spheres)i 上的点,以及一个铬合金"行星"(球体减去球体)
  • 方向盒子/平行六面体(Oriented boxes / parallelepipeds):用于平面笔画

整体场景涵盖了盒子、圆柱体、圆环、球体,以及 CSG 并集、差集和光线步进距离场。

地形与着色

  • 高度场z = amp · fBm(x, y),其中 fBm 对多个八度的晶格值噪声求和
  • 光线步进:相机光线对高度场进行光线步进,从光线首次降至地形最大高度处开始,跳过空白空气,线性插值求交,既快速又无步进带状伪影
  • 着色模型:高度颜色渐变(水 → 沙 → 草 → 岩石 → 雪)、暖色太阳光加冷色天空环境光、步进阴影(地形自阴影与文字投射阴影)、向天空的距离雾

ClickBulb 动画

一个完全由球体构成的台灯(ClickBulb)会在场景中跳跃,从横幅后方探出,光线穿过字母缝隙,然后探头看向观众。每一帧都是相同的 ClickHouse SQL 查询,逐帧运行(全质量视频)。

参数化与生成

  • queries/ 目录下的每个文件都是完整且自包含的,
查看原文 →github.com