全屏交互式黑洞实时光线追踪。主体画面由单个 Fragment Shader 逐像素积分 Schwarzschild 零测地线(null geodesics) 生成:没有黑球、没有平面圆环贴片、 没有贴图/视频/截图伪造。事件视界、光子环、吸积盘的多次穿越、引力透镜、 Doppler 增亮、引力红移和程序化星空/银河全部来自射线微分方程的实时数值积分。
项目为原生 HTML/CSS/JavaScript + ES Modules + 本地 Three.js,无需构建。
使用任意静态文件服务器即可运行(必须通过 http(s) 访问,不能直接双击 index.html)。
# 推荐:Python 标准库
cd gargantua
python3 -m http.server 8000
# Windows 也可运行 start.bat,或:
py -m http.server 8000
# 或 Node
npx --yes http-server -p 8000 -c-1 .浏览器打开 http://127.0.0.1:8000。需要支持 WebGL2 的现代浏览器。
├── index.html # 入口、Import Map、HUD/面板/覆盖层
├── css/style.css # 全屏暗色电影 UI(响应式/移动端)
├── js/
│ ├── main.js # Three 渲染器、后处理、OrbitControls、状态/UI/截图
│ └── shaders.js # 全屏测地线积分 Fragment Shader(核心)
├── vendor/
│ ├── three.module.js # 本地 Three.js r185(无 CDN)
│ ├── three.core.js
│ ├── THREE.LICENSE.txt
│ └── addons/ # OrbitControls、EffectComposer、UnrealBloom 等
├── audio/ambient.wav # 34s 程序化合成氛围音乐(可选,M 开关)
├── package.json # 可选 npm scripts(无依赖)
├── start.sh / start.bat # 一键静态服务器
├── tests/headless-smoke.mjs # 无头浏览器视觉/交互冒烟测试
└── tools/build_standalone.py # 生成单文件 HTML(内联全部模块与音频)
# 生成单文件版本:GARGANTUA-standalone.html(约 6.7 MB,可直接双击打开)
python tools/build_standalone.py
# 完整目录可直接压缩为 zip,上传任意静态托管(Netlify Drop / GitHub Pages / Vercel)- 单位制
M = G = c = 1,Schwarzschild 半径r_s = 2,光子球r = 3。 - 相机射线按球对称性投影到过黑洞中心的轨道平面,使用 Binet 形式
u'' + u = 3u²(u = 1/r)做 自适应 RK4 积分;接近光子球时自动加密步长。 - 事件视界:
u ≥ 0.49(r ≤ 2.04M)判定,输出严格零辐射核心。 - 吸积盘是 真三维体积:径向密度剖面 × 随半径增长的标高 × 指数垂直分层 × 3D FBM 湍流 + 旋涡扰动。射线每步在体积内做发射/吸收积分,可自然实现 前层、后层与光子绕转后的多次盘穿越。
- 每个发射点使用黑洞吸积盘局部温度的黑体色(CPU 生成 256×1 Half-Float LUT),
并按
g = ν_obs/ν_em同时实现 Doppler 增亮/红移(视向速度不同导致 一侧偏蓝、一侧偏红)与引力红移。 - 背景天空为程序化恒星(等距柱天球网格 + 高斯点源)与倾斜银河旋臂; 逃逸射线使用偏转后的出射方向采样天空,因此恒星与银河被真实引力透镜化。
- 后处理链:HDR 渲染 → UnrealBloom → 轻微 RGB 色散 → OutputPass (ACES Filmic + sRGB)。暗角、动态胶片颗粒、饱和度在核心着色器内完成。
| 操作 | 功能 |
|---|---|
| 拖拽 / 单指旋转 | OrbitControls 轨道旋转 |
| 滚轮 / 双指捏合 | 变焦(限制 3.4M–42M) |
0–9 |
调试视图 |
Shift + 1–4 |
四个视角预设 |
C |
电影镜头循环 |
H |
HUD 开关 |
P |
参数面板 |
M |
氛围音乐 |
S |
截图下载 |
R |
重置 21 项参数 |
F |
全屏 |
Space |
暂停/继续盘面湍流时间 |
- Hero — 略带倾角的经典构图
- 光子环 — 接近临界碰撞参数的掠射视角
- 俯视 — 从极轴上方观察盘面与强引力透镜
- 掠视 — 接近盘面边缘的星际穿越式镜头
0 最终 · 1 绕转相位 · 2 盘体积密度 · 3 Doppler/红移 · 4 盘温度 ·
5 透镜化天空 · 6 体积发射 · 7 最近距 · 8 HDR 原始 · 9 UV
| # | 参数 | 范围 | 说明 |
|---|---|---|---|
| 1 | 盘内半径 | 3.2–6 M | 吸积盘内边缘 |
| 2 | 盘外半径 | 8–40 M | 吸积盘外边缘 |
| 3 | 盘厚度 | 0.15–2.5 | 体积盘标高 |
| 4 | 盘密度 | 0.2–3× | 体积消光/发射密度 |
| 5 | 盘温度 | 0.5–2× | 黑体谱温度倍率 |
| 6 | 湍流强度 | 0–2 | FBM 体积湍流幅度 |
| 7 | 湍流速度 | 0–3 | 湍流演化速度 |
| 8 | 湍流尺度 | 0.5–3× | 噪声空间频率 |
| 9 | Doppler 强度 | 0–3 | 相对论束流增亮指数 |
| 10 | 引力红移 | 0–2 | 物理频移强度 |
| 11 | 光子环积分 | 6–26 rad | 最大绕转相位 |
| 12 | 体积步数 | 24–150 | 沿射线体积采样预算 |
| 13 | 曝光 (EV) | −2…+4 | ACES 前 HDR 曝光 |
| 14 | Gamma | 0.6–2.6 | 输出响应曲线 |
| 15 | Bloom 强度 | 0–2.2 | HDR 泛光强度 |
| 16 | Bloom 阈值 | 0–2 | 泛光启动亮度 |
| 17 | 星点密度 | 0–3× | 程序化恒星亮度/密度 |
| 18 | 银河亮度 | 0–3× | 程序化银河亮度 |
| 19 | 色散 | 0–2 | RGB 轻微色散 |
| 20 | 暗角 | 0–2 | 电影暗角强度 |
| 21 | 胶片颗粒 | 0–1 | 动态胶片颗粒强度 |
| 档位 | 渲染倍率 | 体积步数 | 光子环相位 | Bloom | 适用 |
|---|---|---|---|---|---|
| Standard | ≤0.55× DPR | 42 | 12 rad | 0.04 / 1.80 | 移动端、集成显卡 |
| High | ≤0.85× DPR | 72 | 18 rad | 0.06 / 1.75 | 桌面默认 |
| Cinematic | ≤1.0× DPR | 116 | 24 rad | 0.05 / 1.85 | 独显/截图 |
移动端与粗指针设备自动选择 Standard 并限制像素比;Retina/高 DPR 由质量档的
DPR 上限控制。质量档、全部参数、视角、调试视图、相机、HUD、音乐开关会写入
localStorage(gargantua-state-v1),刷新/重载自动恢复。
适合无头浏览器、CI、定时海报渲染。示例:
http://127.0.0.1:8000/?screenshot=1920x1080&preset=ring&quality=cinematic&frames=40&download=1
参数:
screenshot=WxH(如1920x1080)或screenshot=W(高度取h参数)w,h— 无x形式时的宽高preset—hero | ring | overhead | grazingquality—standard | high | cinematicframes— 等待多少渲染帧后截图(默认 30)wait— 额外等待秒数(默认 0.25)download—1自动下载 PNG,0不下载(默认1)
页面完成截图后控制台输出:
GARGANTUA_SCREENSHOT_READY size=1920x1080 bytes=... preset=ring quality=cinematic
也可在控制台调用 window.GARGANTUA.capture(false) 获取 dataURL,或调用
setPreset / setQuality / setParam / setDebug / resize / resetParams / toggleMusic。
URL 截图模式强制 1:1 像素输出,不乘 DPR。
- 初始化失败:显示错误卡与「重试恢复」按钮。
webglcontextlost:阻止默认行为、暂停渲染并显示恢复覆盖层。webglcontextrestored:状态已在 localStorage 持久化,自动重载完成恢复。
audio/ambient.wav 为 34 秒程序化合成氛围音景(低通噪声气垫 + Dm9/C 和弦
长音 + 慢速 LFO),循环播放。若文件不可用或自动播放被浏览器拦截,会切换为
WebAudio 程序化合成;按 M 开关。
使用 Microsoft Edge(Chromium)无头模式 + SwiftShader WebGL2 运行
tests/headless-smoke.mjs 的实测结果(复现命令:
npm i --no-save playwright-core && npm run test:smoke):
| 场景 | 分辨率 | 结果 |
|---|---|---|
| Standard / Hero | 640×360 | avg 97.3,min 0.07,max 251.9,黑像素占比 10.7%,0 console error |
| Standard / 光子环 | 640×360 | avg 76.1,min 0,max 228.9,0 console error |
| Standard / 俯视 | 640×360 | avg 29.8,min 0,max 120.3,0 console error |
| Standard / 掠视 | 640×360 | avg 71.0,min 0,max 248.9,0 console error |
| Cinematic / Hero | 640×360 | avg 98.5,min 1.0,max 251.9,黑像素占比 6.5%,0 console error |
| High 普通交互 | 1280×720 视口 | 绘制缓冲 1088×612,avg 101.5,拖拽/预设/质量/参数/截图/刷新持久化均通过,0 console error |
验收判据:无控制台错误、无黑屏(每场景均有大量 >200 高亮像素且星空/盘面
非零像素占多数)、黑核存在且接近 0、质量档与视角切换不引发重编译错误。