Git City技术栈拆解:Next.js 16 + React Three Fiber + Supabase如何渲染上千栋3D建筑
【免费下载链接】git-cityYour GitHub profile as a 3D pixel art building in an interactive city项目地址: https://gitcode.com/gh_mirrors/gi/git-city
Git City 把每个 GitHub 开发者变成一座 3D 像素建筑,组成一座可自由飞行的互动城市:贡献越多楼越高、仓库越多楼越宽、最近活跃则窗户亮灯。这篇文章拆解它的技术栈——Next.js 16负责页面与 API 路由,React Three Fiber(Three.js)用一次绘制调用渲染上千栋建筑,Supabase承担 PostgreSQL 数据、认证与实时推送。
技术栈分工:三大件各管什么
| 层 | 技术 | 职责 |
|---|---|---|
| 前端框架 | Next.js 16(App Router) | 页面路由、API Routes、SSR 与缓存 |
| 3D 渲染 | Three.js + @react-three/fiber + drei | WebGL 场景、实例化网格、后处理 |
| 数据/认证 | Supabase(PostgreSQL + RLS + Realtime) | 开发者数据、GitHub OAuth、行级安全 |
| 样式 | Tailwind CSS v4 + Silkscreen 像素字体 | 复古像素风 UI |
版本依赖可以在 package.json 中确认:next 16.2.3、@react-three/fiber ^9.5、@supabase/supabase-js ^2.97、three ^0.183。
数据层:Supabase 如何把开发者喂给 3D 城市
城市的数据流是一条清晰的三步管道:
- API 聚合:route.ts 这个 Next.js API Route 用
Promise.all并行查询developers、purchases、raid_tags等十余张表,把排行榜数据一次取回,并附带Cache-Control: s-maxage=300让 CDN 缓存 5 分钟。 - 客户端缓存:cityCache.ts 用模块级单例在页面内导航时保持数据存活,5 分钟过期,避免每次切页都重新拉全城数据。
- 双客户端策略:supabase.ts 里浏览器端用 anon key(受行级安全 RLS 约束),服务端写操作用
getSupabaseAdmin()走 service role 绕过 RLS——这是 Supabase 项目的标准安全姿势。
数据库共 117 个顺序迁移文件,从 001_initial_schema.sql 到 117_earn_rules_english_descriptions.sql,全部可在supabase/migrations/目录逐条阅读。
渲染核心:InstancedMesh 一次画完上千栋楼
这是整个项目最有学习价值的部分。普通做法是每栋楼一个 React 组件,上千栋意味着上千个 draw call,GPU 直接卡死。Git City 的做法是把几乎所有楼合并进一个instancedMesh:
- 单一几何体:所有楼共享一个单位立方体
SHARED_BOX_GEO,每栋楼靠 instanceMatrix 缩放位移,避免了几百份几何体分配(见 Building3D.tsx 注释)。 - 自定义 GLSL 着色器:InstancedBuildings.tsx 的顶点着色器为每栋楼附加
aUvFront、aTint、aLive等自定义属性,让一栋实例网格也能表现"每楼不同颜色、不同亮灯率、升起动画"。 - 像素级抠雾:片元着色器对超出雾距的碎片直接
discard,省掉不可见楼的片元着色开销。
纹理图集与 LOD:楼各不相同又不爆显存
上千栋楼如果各用一张贴图,显存和纹理单元立刻爆炸。项目用了两张巧牌:
- 2048×2048 窗户图集:一整张 Canvas 生成的图集切成 6 个"亮灯率"横带(20%~95%),每栋楼只改变量的 UV 偏移就能拿到独一无二的窗灯图案(Building3D.tsx)。
- 空间网格 LOD:CityScene.tsx 维护一个
cellSize=200的空间索引,只有靠近相机的楼才挂皇冠、光环、霓虹等特效组件(Building3D.tsx 中的二十余种建筑特效按需装配),远处的楼保持精简几何。
性能模式:GPU 自动检测与动态分辨率
🏃 移动端跑不动 3D 城市怎么办?perfMode.ts 给出了一套完整的自适应方案:
- 用
@pmndrs/detect-gpu把用户 GPU 型号匹配到自托管的基准库(public/gpu-benchmarks/下按 Adreno/AMD/Apple/GeForce/Intel 等厂商分类的 JSON); - 检测期间先用内存/CPU 核数启发式猜测,避免首帧白屏;
- 低端模式下调低 DPR(CityCanvas.tsx 中
dpr = lowPerf ? 0.75 : 1.25)并关闭 Bloom 等重后处理; - 若加载画面里实测帧率仍低,再自动降级到 low——"实测信号永远胜过跑分"。
主题系统(Midnight/Sunset/Neon/Emerald 四套)与 Bloom、SMAA 后处理同样定义在 CityCanvas.tsx 中,切换主题即切换整套天空、雾、光照与楼体配色。
本地运行 Git City:最快启动方法
无需远程 Supabase 项目,本地即可跑通(详见 README.md):
git clone https://gitcode.com/gh_mirrors/gi/git-city cd git-city && npm install supabase start # 本地拉起 Postgres/Auth/Storage 并应用全部迁移 npm run dev # 打开 localhost:3001本地未配置 GitHub OAuth 时,点击登录会进入内置 dev 登录页,输入任意用户名即可生成你的楼——这条 route.ts 在生产环境自动禁用。
关键文件速查:从源码继续深挖
| 想学什么 | 看哪里 |
|---|---|
| 实例化渲染 + 自定义着色器 | src/components/InstancedBuildings.tsx |
| 纹理图集生成 | src/components/Building3D.tsx |
| 场景组装、后处理、主题 | src/components/CityCanvas.tsx |
| 空间网格 LOD | src/components/CityScene.tsx |
| GPU 性能自适应 | src/lib/perfMode.ts |
| 数据聚合 API | src/app/api/city/route.ts |
| Supabase 双客户端 | src/lib/supabase.ts |
| 完整数据库演进史 | supabase/migrations/ |
🧱 总结:Git City 的性能秘诀不在单点优化,而在分层协作——Supabase 把数据压成一次批量请求,Next.js 用缓存削峰,Three.js 用实例化把上千栋楼压成一次绘制,GPU 检测再把画质适配到每台设备。这套"数据聚合 + 实例渲染 + 自适应画质"的组合拳,是学习大规模 Web 3D 应用非常有价值的完整样本。
【免费下载链接】git-cityYour GitHub profile as a 3D pixel art building in an interactive city项目地址: https://gitcode.com/gh_mirrors/gi/git-city
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考