把光速降到每小时 5 公里,正好是一次快走的速度,这个世界会变成什么样?Dmitry Brant 写了一个叫 Relativity Park 的浏览器模拟器来回答这个问题:不需要下载,打开网页就是一个第一人称的公园,你走得比光还快。这个项目在 Hacker News 上拿到 300 多分,源码约 2400 行 JavaScript,零依赖,全部公开在 GitHub 上。

先说物理:快走就能超过光的世界
模拟器把光速设成 5 km/h,换算是 1.389 米每秒。在这个世界里,相对论效应不再是实验室里的修正项,而是走路就能撞上的日常。
Gamma 因子的定义是 1 除以根号下(1 减去 v²/c²)。当 c 等于 5 km/h,gamma 达到 2 只需要 4.33 km/h——比快走稍快一点。继续加速到 4.95 km/h,beta 达到 0.99,gamma 跳到 7.09:你手表上走 1 秒,世界时钟走 7 秒。模拟器把速度上限钉在 0.99999c,再往上就是纯数值 curiosity,画面已经没有任何可辨认的东西。
正前方的多普勒因子 D 等于根号下((1+β)/(1-β))。公园里的旋转木马、摩天轮、穿梭车都以 0.75c 运行,对着一辆迎面而来的 0.75c 物体,D 是 √7 ≈ 2.65。一颗反射 550 纳米绿光的表面迎面而来时,波长被压到 208 纳米,掉进深紫外,人眼根本看不见;退行时波长拉到 1455 纳米,进了近红外。这就是模拟器里"迎面的东西消失、身后的东西变暗红"的直接原因。
亮度变化更剧烈。相对论聚束(relativistic beaming)让辐射强度按 D 的四次方缩放,0.75c 迎面方向的亮度是静止时的 49 倍。模拟器的默认聚束指数就是 4.0,写在 app.js 的 beamExp 里。
渲染管线:洛伦兹变换搬进顶点着色器
这个模拟器在实现上最有分量的决定,是把整个相对论成像问题塞进了 WebGL2 的顶点着色器,每帧对每个顶点做一遍物理推演。
着色器注释里写明了三步流程。第一步,沿过去光锥回溯,找出"此刻到达我眼睛的这束光是什么时候离开物体的"——静止景物就是距离除以 c,运动物体则要解一个非线性方程。第二步,把从发光事件指向眼睛的零四向量(类光向量,长度恒为零)做洛伦兹 boost,变换到观察者的瞬时静止系。第三步最漂亮:boost 本身会对这个零向量做缩放,缩放比例就是多普勒因子,不需要任何额外公式。像差、洛伦兹收缩、Terrell 旋转全部从同一步变换里自然涌现,注释里特别指出 Terrell 旋转"其实不是旋转,是光延迟作用在收缩物体上的结果,在这里是免费的"。
运动物体的光行时求解用的是二分法兜底、牛顿法加速的混合方案,24 次迭代封顶。代码注释里留了一个真实的调试故事:早期版本在牛顿步收敛时用严格边界检查,把已经收敛的解扔掉,对一个远端从未移动过的区间继续二分,结果"解偏了好几秒,把网格撕成了尖刺"(tore the mesh into spikes)。修复方法是记录实际评估过的最优点、边界改成闭区间。这是数值方程组里典型的"边界条件与收敛判据打架"问题,写在 3D 渲染的语境里格外具体。
颜色不是调出来的:CIE 色匹配函数的实时积分
多普勒移色怎么做?绝大多数演示会拿 HSV 色轮转一转糊弄过去。这个项目没有:它把表面颜色当成真实光谱处理。
color.js 里的模型是:每个 sRGB 原色建模为高斯反射瓣(红 612nm、绿 549nm、蓝 464nm,带 0.22 的中性底),被一颗 5800K 的太阳照亮,然后对着 CIE 1931 标准观察者的三条色匹配函数做积分——配色函数用的是 Wyman、Sloan 和 Shirley 2013 年发表在 JCGT 的多瓣解析拟合。红移到最后变黑,注释说这是"诚实的":聚束因子在缩小,无线电波段没有可见的东西;蓝移到最后变白,这是一个选择,代码用可见波段外的能量占比把矩阵向白色混合,模拟"整个光谱涌进可见区"的过载感。
整套光谱链路在一个多普勒因子下坍缩成一个 3×3 矩阵,因为从光谱搬移、色匹配到 XYZ→sRGB 的全部变换对三个原色权重都是线性的。模拟器按 log D 把这个矩阵预计算成 512 行的查找表传给 GPU,D 的覆盖范围是 0.02 到 50。运行时每个像素做一次矩阵乘法加一次双线性插值,开销可以忽略。
两个写在注释里的工程事故
除了牛顿法那个,源码里还有第二个值得单独讲的事故:深度缓冲。
相对论场景的可见深度跨度极大——从手边几米到地平线外几公里。着色器用了对数深度缓冲,但注释解释了一个反直觉的细节:log2 是强弯曲函数,在三角形四个角之间插值它只在"浅三角形"时成立。高速物体的延迟图像在近距离时,同一个三角形的顶点可以横跨好几米的深度差,插值误差达到 NDC 空间的 7×10⁻³——大约是 24 位深度缓冲分辨率的十万倍——前后表面排序错乱,"远侧的楔形穿透了近处的侧翼"。修复是把深度解析从顶点挪到片元:视线空间里的 w 是线性的,透视校正插值能在每个片元上精确恢复它。
另一个是地面网格。地面是一个指数分级极坐标圆盘(半径 1.2 到 4000 米,最高 920 环 × 700 扇区),因为像差会把视野后方的放大率拉到 gamma(1+β) 倍——β=0.99 时是 14 倍——后方直线边缘弯得最凶,网格必须足够密。模拟器预构建了 5 个细节等级缓存起来,按 gamma 越过 1.6/3.0 自动升级、回落带滞回区间(1.45/2.7)防止抖动;注释解释 65 万顶点的圆盘重建要几百毫秒,"卡顿总发生在你正在加速的时候",所以只换不建。STL 雕塑(斯坦福兔子、斯坦福龙)同理:相对论变换逐顶点应用会把直边弯成曲线,"8 个顶点的立方体在 0.9c 时还是一个立方体,这是撒谎",装载器按最长边 0.22 米、6 万三角形预算做统一四分裂,保证共享边同步细分不出 T 形缝。
还有一行注释值得记:渲染器关掉了背面剔除(disable CULL_FACE),"Terrell 旋转会让你看到本指向别处的面"。这句话对应着相对论成像的底层事实:slow light 世界展示的从来都是光本身的历史:每一帧画面都由不同时刻发出的光子拼成。
对照组:MIT 2012 年的《A Slower Speed of Light》
把光速降到步行速度这个点子不是第一次出现。MIT Game Lab 2012 年出过《A Slower Speed of Light》,玩家扮演一个想"与光合一"的孩子,收集 100 颗球逐级降低光速,直到步行速度。它基于 Unity 引擎和配套开源的 OpenRelativity 工具包,当年的 American Journal of Physics 上还有团队发表的教学论文。
Relativity Park 的差异不在创意而在工程形态:零依赖、纯 WebGL2、浏览器即开即用;物理没有被做成引擎外挂的特效,成像过程直接在着色器层重建;颜色是算出来的光谱积分,不是美术资源。2024 年 TU Wien 的团队用飞秒激光脉冲和门控相机在真实实验里把等效光速压到 2 m/s,首次拍到了 Terrell 效应的照片(发表于 Communications Physics),这恰好验证了"慢光世界"的物理保真度——模拟器里你眼睛看到的东西,和实验室里相机拍到的东西,遵循同一套方程。
公园里的设施都是教学道具:摩天轮轴心横在走廊方向(正面迎向观察者),旋转木马的轨道中心和轴心静止不动,供你对照收缩的车厢与静止的骨架;测量标杆漆成半米一段的条纹,方便"数出"收缩;灯柱按世界时间每秒闪一次,走近时闪烁加快、远离时变慢,多普勒时移直接可感。界面上还留了一个 Galilean 模式,一键关掉像差回到伽利略视角,看看直觉在没有相对论的世界里会怎么出错。
代码在 github.com/dbrant/relativity,MIT 许可。作者 Dmitry Brant 是维基媒体基金会的 Android 首席工程师,也是数据恢复工具 DiskDigger 的作者。模拟器在线地址在 rivendell.dmitrybrant.com/relativity,源码里的注释密度值得单独一提:几乎每一段实现选择旁边都写着为什么不用另一种做法。
参考资料:
- Relativity Park 在线模拟器:rivendell.dmitrybrant.com/relativity
- 源码仓库:github.com/dbrant/relativity
- MIT Game Lab《A Slower Speed of Light》(2012)与 OpenRelativity 工具包
- Hornof et al., "A snapshot of relativistic motion: visualizing the Terrell-Penrose effect", Communications Physics 8, 161 (2025),实验完成于 2024 年
- Wyman, Sloan & Shirley, "Simple Analytic Approximations to the CIE XYZ Color Matching Functions", JCGT 2(2), 2013