Kirino 的游戏宝藏
← 返回第 022 期
游戏观察

看不见的六十帧与字节为零的对照表,Esteban Estrada 如何用 look sheet,把《Guildhall》整座王国的优化钉成不可见的胜利

如果说浏览器里跑一座活着的王国,行业默认常常是「先把画面拧好看,卡了再关阴影、砍远景、让 LOD 在镜头前啪地换人,新闻稿再写已针对移动端优化」,那么 2026 年十月十八日,Esteban Estrada 在 codestz.

我的收藏 ↗

如果说浏览器里跑一座活着的王国,行业默认常常是「先把画面拧好看,卡了再关阴影、砍远景、让 LOD 在镜头前啪地换人,新闻稿再写已针对移动端优化」,那么 2026 年十月十八日,Esteban Estrada 在 codestz.dev 上摊开的那篇《Invisible Wins: 60 FPS for a Whole Kingdom, Even on a Phone》,几乎是在当众改写这套默认账单。作品叫 Guildhall,跑在 WebGL 浏览器标签页里,目标写得很直:在 M1 Pro 上稳住六十帧,在手机上也要顺。本稿未长期试玩成品,以下场面与数字均来自作者公开实验笔记与演示站资料。

一座一万二千文件的岛,会变成二千八百一十三块地砖,约三万零五十二件部件:房子、树、篱笆、庄稼、一座城堡。上面还有按作息走动的人群、带浪的海、天空,以及拖着所有阴影走过一天的太阳。它不是「能开就算赢」的演示。作者在二〇二六年十月十二日写进决策文件的那一行,比任何帧率口号都更硬:Performance must not change what you see——性能不得改变你看见的东西。

贯穿本稿的意象,是 look sheet,也是「看不见」。它听起来像验收工具名,落到制作伦理上,却是一组可核验的承诺。先让画面在像素级对得上,再谈哪一刀省了时间。省下来的必须留下台账,改的是耗时,镜头里的王国仍字节一致。

Guildhall 一万二千文件岛的重端场面

一、默认逻辑:优化等于改画面,帧率够了就算赢

行业默认逻辑其实很干净,也因此很偷懒。

三维网页项目一旦从桌面下沉到手机,团队通常会打开一张熟悉的菜单:降低设备像素比、缩短阴影距离、关掉级联、把远处网格换成粗糙壳、把「看起来贵」的后处理砍半。玩家也学会了用同一套语汇阅读优化——他们会说「能接受」「远景糊一点没关系」「手机开中配就行」。这种默契让「看得见的降级」变成可被原谅的行业语法。

Guildhall 偏偏是最难被这套语法容纳的作品之一:整岛尺度、日夜阴影随太阳转动、人群日程、天气与演出程序、还要在浏览器里维持六十帧。它最初对准的是「一整座王国」的体验预算。把这样的作品塞进标签页,行业直觉几乎会自动指向「远景换样、阴影变糙、LOD 在缩放时跳一下」。

V1 恰好踩进了那个坑。镜头拉近拉远,世界会可见地换人:东西弹出,每个距离略有不同的样子。于是在任何性能提交之前,作者先把规则钉死。那一行让工作难得多,也好得多。它意味着,一项改动只有在看不见时才算数。要证明「看不见」,你需要数字和图片,而不是意见——包括作者自己的意见。

分叉点就在这里。默认问的是,帧率不够时砍什么观感。他们改问的是,帧率不够时,哪些实现必须换成更省、却在画面上仍字节一致的方式;以及,哪些听起来稳赢的点子,测量之后其实该退回。

二、砸碎脚本:实验室协议,以及机器先于场景

性能容易声称,难证明。听起来稳赢的点子,往往不是。作者带着一份经验清单进来:细节层次、缓存阴影、更轻的远阴影、远处簇的宏壳、把人群移出远阴影、剔除极小阴影投射体、远处更便宜的水。每一项都是真技术。但清单只是猜测清单。有的会赢,有的几乎不花钱,有的会悄悄改你看见的东西。

所以在动手优化之前,他先写合同与计划,再把长测量与实现交给更大的模型 Fable 5.1 按计划执行,自己决定什么进主干。合同读起来更像实验室规程,而不像任务单。固定机位:六个相机姿势——英雄、中景、广角、十九点三十灯笼、热闹的正午广场、海面低飞——分别在四千与一万二千文件规模上各跑三轮,机器上别的事都关掉。台账:每次改动追加各姿势的 before → after;增益小于测量噪声的改动退回。挡住你的不变量:look sheet(五个缩放 × 多个时刻,前后对照)、无弹出的缩放扫过、阴影永不陈旧或跳动。一次提交只进一种技术,各自带数字,好追溯赢,也好丢掉输。安静机器、真机、人类检查点:基准时不开别的浏览器;真机手机核对;中途本人看台账与 look sheet;结束时,没写过这些代码的代理再跑一遍。

测量首先发现的,不是慢着色器,是机器本身。

Mac 上的 GPU 计时器会撒谎。ANGLE 叠 Metal 时,`EXT_disjoint_timer_query_webgl2` 读的是每个命令缓冲的墙钟时间,要二三十帧才解析完,自身还大约吃掉每帧一点三毫秒。于是计时器改成可选,成本用减法量:关掉某部分再加载,对比页面。一个忙碌标签页会把帧时拉到约三倍。「安静」基准里每个姿势约三十四毫秒;作者自己的 Chrome 还开着一座活着的 Guildhall,其 GPU 进程占九到十八个百分点 CPU。关掉以后,同一提交读出九点七 / 十二点二毫秒(p50 / p95)。什么都没退化。手机甚至能赢过笔记本:在作者的小米上,岛可以跑在六十帧以上,Mac 反而更慢,因为代理的无头浏览器在分 GPU。从此每次基准都先用 `ps` 查别的浏览器,并记进台账。

这是经验给你的那种规则:在优化场景之前,先隔离机器。否则你优化的是噪声。

性能轮次三 look sheet:正午最近缩放

三、帧预算里的具体刀:实例、阴影、着色器、工人、字节

帧最终落在哪里,作者按重要性顺序拆开。每一格都是一课。

静态件全部进一个 three.js `BatchedMesh`。几何共享一套缓冲,整岛一次 multi-draw,整帧大约三十五次绘制调用——也因此当时还不值得切 WebGPU:瓶颈不在 draw call。真正贵的,在 Metal 上,是实例数,不是三角数。每次通道前,three 的批次要走遍每个实例做视锥测试、塞绘制列表并上传;大约一万八千实例时,那次遍历就是账单。作者换成自己的 `LodBatchedMesh`:LOD 档位住在同一缓冲里;两档之间列两次并带抖动码,在约二到二点八 CSS 像素带里交叉淡入;远处簇换成一个壳实例;相机与实例未变时复用上一帧列表。关掉 LOD(`?lod=0`),广角慢二十三到二十五毫秒。但它只在差大约一个像素以内的地方换,而且会淡。

阴影跟着太阳,却不必每次重走整岛。太阳三条级联:近处约三十米宽、约二点三厘米一纹素,中档一百米,以及盖住全镇的一条。相机静止时都不重渲;太阳一转四分之一度(`SHADOW_TURN = 0.25°`),三条一起重画。日在跑时约每秒三十次级联重渲,台账给出作者没料到的数:大约吃掉英雄视角三十帧每秒(笔记本画像八十五到五十六,手机一百零五到五十八)。更粗的转角能少画,但阴影会可见地跳,规则说不。第四轮让侧通道各自缓冲,避免级联重渲后在静止相机上再走约一万八千实例并重传。第五轮保留全镇级联列表(任何太阳角都罩整岛,建一次直到有实例变化),并加约三十二 × 三十二剔除格;遍历仍按实例序,列表同序同内容,有测试证明。日在跑 CPU p95(×4 节流)笔记本二十二点四到十九点八毫秒(第四轮),英雄十九点三到十六点二(第五轮),手机英雄十八点五到十六点二;第五轮每一行掉二点三到三点四毫秒。作者也写出没做到的事:转太阳那一帧 GPU 仍要画三条级联,笔记本广角没动。

卡顿也不在预期处。超过二十五毫秒的帧,追到着色器第一次使用时链接。ANGLE 叠 Metal 上,普通程序三十到五十毫秒,重的可达数百毫秒;并行编译扩展还会过早报告就绪。作者量过两秒宽限期,仍有三十五毫秒卡一下。于是世界会用到的程序都在加载遮罩下链接,演出程序钉住不丢;批次预热改成带真实属性的一三角替身。一万二千文件岛上,超过二十五毫秒的帧从十降到一;揭示前编译的程序从四十到三十二。

世界在 worker 里建。第二轮,生活计划(谁住哪、谁走哪条路、几点)也进 worker,计划字节相同,有测试证明。首帧后最长主线程任务:四千文件从一千九百九十九毫秒到三百二十三,一万二千从三千七百六十七到四百九十五。然后还剩约二点四秒卡顿,既不是 CPU 活,也不是着色器。轨迹显示:批次在几何仍按片拷贝时就被画了;每次 `bufferSubData` 打进上一帧还在画的缓冲,ANGLE/Metal 会把整块约一百三十兆再拷一遍。修法几乎无聊:批次藏到几何齐了再一次上传。批次构建从四点八到五点一秒落到一点一到一点四秒,整岛从十点五秒到四点五秒。这一项不在任何人的清单上,包括作者自己。它来自读轨迹,并追问:为什么一个 GL 调用会在 GPU 没事可做时等待。

传输侧,Vercel 压文本与 JS,却原样送 `.glb`。角色骨架单独三点一四兆。构建把库 GLB 全部 gzip,页面用浏览器自带 `DecompressionStream` 解;看字节头 `1f 8b`,不看文件名。首载一镇,线上下载九点二五到五点二四兆,GLB 七点八九到四点零二,角色骨架三点一四到零点八六,请求四百一十二到三百一十一。

第二轮末尾一串小提交各自计量:白天关掉的灯、共享调色板材质、去掉与 SMAA 叠在一起的画布 MSAA、少造每帧垃圾。不封顶、四千文件英雄 p50/p95 从八点九 / 十一点七到六点三 / 八点一;一万二千文件英雄九点零 / 十二点四到六点三 / 八点三。帧时大约掉百分之二十五到三十五。画面相同。

第三轮管的是头几秒。以前开镇,Studio 壳下会闪一下苍白空画布;现在内联启动遮罩从第一帧就画,再淡入世界自己的遮罩,捕获里找不到首绘后的空白帧。生活 worker 约在一秒开始规划,计划落在批次还在建的时候。冷启动、开垂直同步、三轮中位:四千文件揭示四点九到三点七秒,一万二千七点一到五点一秒。揭示里有六百毫秒是遮罩自己的淡出,作者留下,因为淡出是那一时刻的一部分。

导航后约五百零四毫秒:空画布与启动遮罩前后对照

四、节奏先于画质,以及诚实的否决表

「顺」的最后一课,是节奏先于任何画质下调。帧率在六十、四十、三十之间跳,往往比稳住的三十更糟。舞台按第 n 次垂直同步绘制;跳过的同步不画、也不跑钩子;一切动画跑在真实流逝时间上,所以三十帧时什么都不会变慢。自动模式连续两秒坏才降档,连续八秒稳才升;升不住就加倍等待,避免扑腾。设置 → Motion 可选 Auto、Smooth 30 或 Max。模拟手机(三九〇 × 八四四,DPR 三,CPU ×6)上,帧时从三十三点四 / 四十一点零毫秒到十六点七 / 十八点四:在一百二十赫兹面板上稳住六十。只有连三十节奏都撑不住,质量梯才一档一档降:`TIERS` 从全貌(dprFloor 一点五、阴影图二〇四八、lodBias 一、粒子二百五十六)走到最低(零点七五 / 一〇二四 / 二点五 / 六十四)。手机默认低一档,弱 GPU 低两档,Auto 在二十秒平静后爬回全貌。作者的 M1 上,档位几乎不动帧(岛在那里无论阴影分辨率都偏 GPU 受限)——这正是梯子坐在节奏后面、而不是前面的理由。

每轮收束方式相同。look sheet:同一座岛、同一冻结时钟,正午、十六点三十、十九点三十各五个缩放,前后捕获,逐像素差分。第三轮十五张全部匹配,平均差零点零零零 / 二百五十五:字节对字节。第四、五轮唯一差异,是最近缩放上一块会在同构建两次捕获间出没的扁片,与改动无关。四十八帧的动日条带也字节一致。那就是门槛:画面动了,优化就不进主干。

作者最喜欢的台账段落,是诚实的否定。第四轮清单上许多「稳赢」点子,测量说不:小于一纹素的阴影剔除——全镇级联里几乎没有亚纹素投射体,两纹素就会让可见阴影点消失,不建;把人群移出远级联——本来就不投任何级联,无事可做;跳过岛下的水、远处更便宜的水——建了量了两次,广角与英雄帧时不动,真要省远水就得更早淡浪,丢掉;更轻的远级联软化、把级联重渲摊到多帧、太阳转时少重画——要么成本不变,要么看得见,不建或拒绝。他接受的一点:一万二千文件岛从最广角看,在笔记本画像上仍重。决策文件里的笔记:「12k is too big and crazy。」演示尺度的岛是顺的;他宁可直说,也不装运一座更糊的王国。

主题在此收束得更清楚:体验定义问题、规则与验收;AI 执行得快。打字几乎都是模型做的。作者写合同与计划,委托长测量与实现,决定什么进主干。执行快,是因为规则清楚。来自经验的部分是:在第一笔提交前写下「性能必须看不见」;在信任何一个数字前隔离机器;读轨迹并追问缓冲拷贝为何在空闲 GPU 上等待;当 look sheet 说不时,让它否决自己的点子。

收束:独立等于愿意为「看不见」付验收

把这篇十月十八日的笔记放回 2026 年秋天的浏览器游戏现场,它首先打击的是一种隐蔽的制作惯性。大家默认优化等于改画面,默认帧率口号可以压过像素证据,默认「修完能玩」就够了,很少有人追问修完以后的王国是否仍是同一座。Esteban Estrada 把另一条路径摊开。合同可以土到六个固定机位与三轮重复。验收可以硬到平均差零点零零零 / 二百五十五。否决表可以把「稳赢」点子公开钉死。AI 可以快,人必须决定船开不开。

对小团队,这组材料尤其刺耳,也尤其有用。你未必有一万八千实例的 BatchedMesh,也未必有 Fable 5.1。你一定有自己的「默认已经够用」清单。某次优化只看平均帧,不看安静机器。某�� LOD 在缩放时跳一下,却写成「玩家注意不到」。某次阴影为了帧率改成可见步进。某次预热对着空几何编了个永远不画的变体。某次「省水」量完前后一样,却仍想留在主干里装胜利。Guildhall 的公开作业把成本写得很土。look sheet 可以黑成零。台账可以一行一项。贵的是愿意在进主干前付那次人类检查点,以及愿意在决策文件里承认:一万二千从最广角看仍然太疯。

可执行的提示很短。

  • 在第一笔性能提交前,先写一句否决权规则:哪些观感一旦变形,优化就不算赢;把「看不见」写进决策文件,而不是写进事后辩解。
  • 固定机位、多轮、安静机器、真机,四者至少落地一套;增益小于噪声的改动退回,不要靠体感宣布胜利。
  • 一次提交只进一种技术,各自带 before → after;会改画面的剔除与软化,先做 look sheet 或字节差分,黑了再合。
  • 节奏先于画质梯:宁可稳住的三十,也不要在六十与三十之间扑腾;梯子只在三十也撑不住时动,并记录它否决了哪些「稳赢」点子。

一万二千文件、约三万件、三十五次绘制、零点零零零 的差分、以及一句「12k is too big and crazy」。在演示站仍开着、代码与台账仍公开之前,制作人已经把审计标准说死了:不是「能不能跑到六十」,而是「跑到六十之后,你看见的还是不是同一座王国」。

小光

来源与延伸阅读

Esteban Estrada(2026-10-18)Invisible Wins: 60 FPS for a Whole Kingdom, Even on a Phone

Esteban Estrada(2026-10-18)Feet That Don't Skate: Why 'It Looks Right' Is the Hardest Requirement

演示站 https://guildhall.codestz.dev

登录后,留下你的阅读足迹。

在个人页查看自己的点赞和收藏,换设备也能继续。

登录