【免费下载链接】nothing-to-watch
An experimental webgl gallery that can visualize tens of thousands of film posters as a voronoi diagram
nothing-to-watch 是一个实验性 WebGL 画廊项目,能把数万张电影海报实时渲染成交互式的 Voronoi(泰森多边形)力导向图谱。为了在不同硬件上保持稳定帧率,它采用了一套完整的GPU 检测分级 + FPS 动态降级策略:先用 detect-gpu 探测显卡档位,再根据运行时的 FPS 采样自动调低画质。这篇文章带你拆解这套 WebGL 性能优化机制,并整理出一份实用的性能调优清单。
一、先给设备"分级":GPU 检测与四档设备体系
在加载任何重负载内容之前,nothing-to-watch 会先判断当前设备属于哪一档。四档体系定义在 consts.ts 中:
| 档位 | 代号 | 典型设备 |
|---|---|---|
| 📱 Mobile | DEVICE_CLASS.mobile | 手机 |
| 🥔 Potato(低配) | DEVICE_CLASS.low | 小屏笔记本、平板 |
| 😐 Mid-range(中端) | DEVICE_CLASS.mid | 中端独显桌面机 |
| 💪 High-end(高端) | DEVICE_CLASS.high | 高端独立显卡 |
判定逻辑在 device-class.ts 的estimateDeviceClass中,优先级如下:
- 移动端优先:用 UA 解析判断是否为手机,直接归入 mobile 档;
- 小屏/平板降档:命中小屏媒体查询或平板特征时,归入 low 档;
- 桌面端探测 GPU:调用 detect-gpu 的
getGPUTier(),映射为——- 第 3 档 →
high - 第 2 档 →
mid - 其他 →
low
- 第 3 档 →
分级结果会展示给用户,并允许手动修正,入口在 device-class-widget.tsx。
二、分级如何映射到画质:预设与海报数量上限
设备档位不是摆设,它会直接决定两个关键参数:渲染预设(Preset)和海报格子数量(Cell Limit),映射规则集中在 core-settings-widget.tsx。
渲染预设
预设定义在 presets/ 目录下,每个预设对应不同的着色器与模拟配置:
- Mobile(mobile.ts):仅 5000 个格子,关闭后期特效,禁用多线程模拟,使用 KTX 压缩纹理——专为移动 GPU 打造;
- Minimal(minimal.ts):默认预设,50000 格子,走最轻的渲染路径,推荐给 low 档设备;
- Depth(depth.ts):开启后期深度着色器与多分辨率纹理动态加载,仅推荐给 high 档设备。
海报数量上限
CELL_LIMIT提供从 5,000 到 100,000 的 5 档选择,每个档位都标注了推荐设备等级:
- low 档 → 最多推荐 25,000
- mid 档 → 50,000
- high 档 → 100,000(标记为不主动推荐)
设备越强,允许渲染的海报越多;设备越弱,格子数量越低,这是控制 WebGL 填充率与内存的第一道闸门。
三、FPS 监控器:动态调质的"心跳传感器"
静态分级只解决了"起步"问题,运行时性能还要靠 FPS 监控器实时兜底。核心实现在 performance-monitor.ts:
- 采样:每 250ms 统计一次帧率,维护 10 个滚动平均值;
- 动态阈值:根据探测到的屏幕刷新率设定上下界(高刷屏为 60~100,普通屏为 50~60),给判断留出"安全带",避免误触发;
- 升降档:当超过 75% 的样本低于下界时触发
onDecline(降质),高于上界时触发onIncline(升质),每次以 0.1 的步长在 0~1 之间调整性能因子factor; - 防抖与兜底:单帧间隔超过 500ms 视为休眠/节流,样本直接作废;反复抖动超过阈值后触发
onFallback,锁定固定基线防止画质震荡。
监控器通过 ticker.ts 挂到 Voroforce 引擎的渲染循环上,每个 tick 调用onTick(),并在页面切换可见性时重置样本,保证统计干净。
四、低帧率自动降级:用户无感知的"保流畅"流程
当 FPS 持续走低,low-fps-alert.tsx 会接管体验:
- 订阅
performanceMonitor的onDecline事件; - 一旦触发,冻结渲染循环并弹出 "Low FPS detected" 提示窗;
- 自动把设备预估档位下调一级(high → mid → low),同时提供一键降配置面板;
- 设置面板应用后自动刷新页面,以更低预设和更少格子重启;
- 内置 30 秒冷却时间与弹出次数上限(已是最低配置时上限降为 1 次),避免反复打扰。
这套"检测 → 提醒 → 降级 → 冷却"的闭环,让弱设备用户不用手动折腾也能获得可接受的帧率。
五、纹理压缩与多分辨率图集:省显存的关键
除了分级和降级,nothing-to-watch 在资源层面也下了功夫,配置见 media.ts:
- 压缩纹理格式:默认使用 DDS/KTX 格式的 GPU 压缩纹理(如 ASTC/ETC2 类),比原始 RGBA 大幅降低显存占用与带宽;
- 三级分辨率图集:海报被预烘焙进网格纹理图集(Texture Atlas),分为 low / mid / high 三个版本——缩略远景用低清层,拉近后才加载高清层;
- 按需加载版本:Depth 等预设会在模拟步骤中根据单元格邻接度动态请求更高分辨率的海报层(见 depth.ts 中的
requestMediaVersions),只把显存花在看得见的地方; - 批量分块加载:JSON 数据与媒体资源分块加载,避免一次性压垮网络与内存。
六、WebGL 性能调优技巧清单
结合 nothing-to-watch 的实践,这里整理一份可直接借鉴的清单:
- ✅启动即分级:UA + 媒体查询 + detect-gpu 三层探测,别只靠一种信号;
- ✅让档位驱动参数:设备等级直接映射到格子数量、预设、纹理版本,而非散落各处;
- ✅运行时 FPS 采样要有"安全带":基于刷新率设动态阈值 + 滚动均值 + 防抖,避免画质来回抖动;
- ✅自动降级要有冷却:设置 30 秒冷却与弹出次数上限,降级动作对用户保持克制;
- ✅纹理用 GPU 压缩格式:KTX/DDS + 多级图集,显存与带宽双节省;
- ✅细节按需加载:根据视角邻接度决定加载哪一版分辨率,远景永远用低清层;
- ✅移动端单独开小灶:关闭多线程模拟、禁用后期特效、降低交互自由度(如限制缩放范围,见 mobile.ts);
- ✅页面隐藏时暂停:利用可见性 API 重置统计并延迟暂停(
handleVisibilityChange在 config.ts 中启用),省电省卡。
写在最后
nothing-to-watch 的流畅并非来自某一项黑科技,而是"静态分级定起点、动态监控兜底线、资源策略控开销"三层配合的结果。对于任何想在不同设备上稳定跑 WebGL 的项目来说,这套GPU 检测分级 + FPS 自适应降级的思路都值得直接抄作业。
参考文件:device-class.ts、performance-monitor.ts、low-fps-alert.tsx、consts.ts、media.ts
【免费下载链接】nothing-to-watch
An experimental webgl gallery that can visualize tens of thousands of film posters as a voronoi diagram
相关推荐
Doctor Dignity性能优化技巧:如何让医疗AI在移动设备上流畅运行
Doctor Dignity性能优化技巧:如何让医疗AI在移动设备上流畅运行 Doctor Dignity是一款能够通过美国医疗执照考试的离线医疗AI,支持跨平
OpenClaw `openclaw dns` 命令实战:基于 Tailscale + CoreDNS 的广域设备发现(DNS-SD)完整指南
OpenClaw openclaw dns 命令实战:基于 Tailscale + CoreDNS 的广域设备发现(DNS SD)完整指南 openclaw d
mGBA性能优化技巧:如何在低端设备上实现全速运行
mGBA性能优化技巧:如何在低端设备上实现全速运行 mGBA是一款高度优化的Game Boy Advance模拟器,专门为在低端硬件上实现全速运行而设计。如果你
硬件仿真嵌入式
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考