工作十五年
一篇迟到了半年的总结
2011 年 2 月 22 日,我第一天去畅游实习。
十五年整那天是 2026 年 2 月 22 日,我什么都没写。十周年那天我也什么都没写——2021 年 2 月 22 日,这个博客上最新的一篇还停在 2019 年 9 月。
今天我把 2010 年以来公开和私下写过的东西全部归到了一起,站点上一共 108 篇,最早一篇是 2010 年 5 月 13 日,标题里还带着感叹号,说渲染系统初步竣工。
一路读下来,才觉得应该把这一篇补上。
先放两张图


这两张图最近一篇里刚用过,这里再用一次,因为它其实是在重复十五年前的一个动作。
2011 年 10 月那篇工作半年总结,也是两张对比图开头:毕设结束时的 gkENGINE,和半年后的 gkENGINE。那次的跨度是六个月,我当时的形容是”天翻地覆”。
现在这两张跨了十五年。
但有件事读完全部文章才看清楚:这十五年里真正把图拉开的,只有开头四年和最近两年。中间那段,图不会变。
第一段,四年四家公司(2011–2015)
五周年那篇里我谢了四个人:畅游的张哥、永航的 p 叔、中视典的李大师哥,还有当时刚到任的老大。今天再看,那四年学到的东西有一个共同点——全都是被人逼出来的,或者被自己在晚上逼出来的。
畅游那半年,白天做动画系统和项目支持,晚上把 gkENGINE 整个重构了一遍,从 OGRE like 的思路里拽出来,拆成六个能并行编译的 DLL 模块。当时的原话是”一直这样的话,有些平淡”。二十三岁的人写这种话有点狂,但那次重构确实是真做了。
永航只待了半年多,p 叔骂过我几次。软件渲染器是那半年写的,八万根发丝的模拟和渲染是那半年做的,“开发之前先做设计”这个习惯也是那半年养成的。
中视典两年多,三个人从头 code 出了 OpenVRP,一年后开了一场发布会。
然后是 2015 年春节,我把 gkENGINE 开源了。三个月后我拿到了深圳的 offer。
这件事后面还会原样重复一次,所以先在这里说清楚:
gkENGINE 开源不是一个技术事件,是一个把我重新接回技术圈的事件。当时我写的是”一切,源于 gkENGINE 的开源发布”。它让我看见了自己”掩藏在内心的不开心”:接近一年没碰尖端技术,裤衩 T 恤换成了西裤衬衫,每周一两天出差见客户。
一个业余项目最大的作用,是给你一面镜子。
第二段,八年(2015–2023)
腾讯是我待得最久的地方,八年。这八年博客上几乎是空的,所以我想先说清楚,它不是一段空白。
从深圳到成都,从 Unity 到 UE,手机上的项目一个接一个。给展示角色做描边、假实时阴影和 GPU 加速的伤害数字;AR 那阵子做 MatCap 角色渲染,用陀螺仪模拟实景光照;MOBA 上写帧同步的启发式 A* 和局部规避,为 MOBA 的固定视点专门定制 CSM 来压 DrawCall,然后是一轮又一轮中低端机型的内存和 Fragment 专项,保证海外能顺利发出去;再往后是 BR 项目的全平台并行 CI、蓝图静态编译检查、用 GeometryScript 做程序化 Blockout。中间还做过一段无限地形的 LOD 预研,噪声加水力热力侵蚀那一整套。
每一件拿出来都够写一篇。八年里我一篇都没写。
原因很朴素:没精力。
2019 年那篇里我记过当时的作息,9-10-6。这种作息下,回到家能坐下来把一件事重新想清楚、写成一篇文章的余量是没有的。不是”没时间”——一天挤一小时总挤得出来;是脑子已经空了,白天做完一整天判断,晚上只想瘫着。
写作需要余量。它不是把做完的事复述一遍,是重新想一遍,这一步往往比做本身更耗。
devlog 里其实是有痕迹的。零星记过一些技术点,有几个还专门开了文章,但一多半只开了个头。
站点上现在还留着这些残骸。2016 年 10 月那篇讲 Unity5 纹理压缩的,正文是三个标题——“uGUI 下的高质量透明纹理压缩”、“Android 纹理压缩模式之坑”、“自定义 sprite packer”——底下一个字都没有。同年 4 月那篇 Non-Uniform-Scale 的坑,前面把问题查得清清楚楚:Unity 为了保证 normal 正确会偷偷复制一份 mesh 做 scale,原本 3MB 的模型数据能涨到 7 到 9MB。然后我写下”解决这个问题,刻不容缓!“,就断在这里了。十年过去,那句”刻不容缓”再没有下文。还有一篇标题叫「2015 年总结」的,正文是两个空的分隔符。
今天回读,可惜的不是这几篇没写完。是那几年里大量挺精彩的优化思路和问题定位过程,当时都觉得”以后有空再整理”,然后就没有以后了。它们现在只剩一个标题,或者连标题都没剩下。
所以那八年我留下的东西几乎全在项目里,没有一件在我自己这儿。项目上线过好几个,职级也升了,是当时说的”十分认可”。但系统做完归项目,项目下线就什么都不剩,游戏最后也不会有 staff。
这后来成了我离开的理由之一。不是唯一的,也不是当时最响的那个,但它是最后没法忽略的那个:一个人如果连续几年的产出全部沉在别人的仓库里,他的成长是查不到的——别人查不到,他自己也查不到。
2019 年之后好过一些。过程生成地形、寻路、四平台 CI、UE5 的异步解压、大世界烘焙工作流、Perforce——今年我把这些从私人 devlog 里陆续补写成了文章。补的时候才意识到,它们当时不是不值得写,是我当时没有把写下来当成一件必须做的事。
2023 年 5 月我换了一家公司,做的还是基础设施:多人协作的地形编辑、Perforce 的协同瓶颈、把打包时间压下来。这段还在进行中,就不多说了。
最后说这件事的另一半:最近两年做 gkNextEngine,情况整个反过来了。
每一个技术点都在仓库里。改了什么在 commit 里——那次核心重构,每个阶段搬走了多少行直接写进 commit message;为什么这么改在 plan 和分层文档里;连写给自己和 agent 看的 AGENTS.md 也在仓库里。我不需要再额外找一个晚上”把它写下来”,因为写代码的时候就已经在写下来了。
然后它是开源的。推出去之后,这些东西不再只依赖我的硬盘,也不再依赖我记得。
开源是个好东西。这话我十年前也会说,但那时说的是”能让别人看到我”。现在我更在意另外半句:它让我自己也能回头看到我。
第三段,把自己重新放回不会的位置(2024 至今)
去年我引过 zeux 的一句话,说他的渲染水平停在了”PS3 末期到 PS4 初期”。我当时的原话是”这简直是我的嘴替”。
我的渲染知识停在了 DX11。硬件光追、bindless、基于样本的那一整套,通通错过了。在那之前我还敢说自己是图形程序员,那时候我已经听不太懂别人在说什么了。
契机很俗:2024 年我买了一台 M3 Max。然后是 2024 年 5 月 7 日,我在 RayTracingInVulkan 上落下自己的第一条 commit,叫 “add living room, tweak obj loader”。
两年过去,那个仓库长成了 gkNextEngine。
这两年的具体内容我已经写了不少篇——全 Bindless、GPU-Driven、实时路径追踪、和一堆 code agent 一起写引擎、让 LLM 写 OpenSCAD 而不是直接吐网格、把本地 LLM 放进运行时——这里不重复。
我只想说这件事本身的形状:它和 2011 年那次晚上重构 gkENGINE,是同一件事。
隔了十五年,触发条件一模一样:发现自己看不懂了,并且不接受这一点。
十五年之后我比较确定的几件事
一、能带走的只有两样,判断力和仓库
我做过的商业项目,大部分已经下线了,有些连截图都找不到。
十五年下来,能打开、能 clone、能直接拿给别人看的,只有 gkEngine 和 gkNextEngine 这两个仓库。
我不是说公司项目没价值。那八年的性能优化、崩溃定位、中低端机型适配,是我今天判断力的主要来源,个人项目给不了这种量级的真实问题。我是说:判断力长在人身上,成果长在仓库里,两者都不长在公司的服务器上。
二、跃迁从来不是被安排的
2011 年那次是自己晚上重构,2012 年那半年是被骂出来的,2015 年那次是因为自己把引擎开源了,2024 年那次是因为自己买了台电脑。
组织给的是舞台、约束和大量真实问题,这些非常重要。但把自己推上下一个台阶的那一脚,十五年里没有一次是别人踢的。
三、要定期把自己放回”我什么都不会”的位置
这是我最晚才想明白的一条。
2015 到 2023,我一直在做熟练的事,而且越做越熟练。熟练本身没问题,问题是熟练会伪装成成长。
一个还算好用的信号:去听一场行业分享,有多少词你需要回去查。这个数如果连续几年是零,通常不是因为你都懂了,是因为你不在场了。
四、写下来是唯一对抗遗忘的基础设施
十五年下来我试过两种记录方式,忙起来的时候只有一种还活着。
一种是专门坐下来写一篇。它是额外工作,要占掉一个完整的晚上,所以它第一个被牺牲——前面那些只剩标题的残稿就是账单。
另一种是让记录成为副产品。commit message、plan、文档、脚本、跑出来的数,写它们的时候我不是在”做记录”,是在把手上这件事做完。它们不额外索取余量,所以再忙也不会断。
差别不在记忆力,也不在自律,在于记录这件事有没有搭在你反正都要做的动作上。
顺便,这也是我今年做另一件事的原因:把博客从 Jekyll 搬到 Astro,44 个历史 URL 一个字节不改地接住,2010 年至今的东西全部归到一起。十五年的外链和搜索权重,我不想丢。
五、AI 改变的是可行边界,不是打字速度
十五年前一个人写引擎,瓶颈是产能。一晚上只有一条思考链,卡住两小时,这两小时就没了。
现在瓶颈是判断。几个 agent 能同时铺开几条线,回来给你几份看起来都合理的方案,你得决定哪个留下来。backlog 反而更长了,因为突然有太多东西看起来都做得完。决定不做什么,变成了比实现更难的事。
至于”以后不需要懂代码”,我不同意。AI 把技术判断的杠杆放大了:判断对,几十个文件一起往对的方向走;判断错,它也能用很高的质量把错误的架构铺满整个仓库。
被放大的是判断,不是被取代。
六、关于那个 Great Game
2015 年我写过 “WE ARE MAKING A GREAT GAME!”,2016 年我写过”我背弃了我的梦想,但我绝不会丢掉它”。
十年过去,我没有在任何一家公司里把它做成。
但这个念头一次都没断过。2023 年初我给自己列过两条路,一条是做独立游戏,一条是做游戏开发的教程系列。当时选了看起来更容易起步的那条,理由是”总要先动起来”。真正想做的一直是第一条。
现在仓库里有十几个游戏子项目。对外我一般说它们是用来逼引擎回答真实问题的——输入怎么统一、脚本生命周期怎么和 C++ 对齐、场景重载之后谁还持有旧指针。这是真话,但不是全部。它们同时也是排练。
十年前我以为差的是一个机会、一个团队、一次立项。现在我知道差的是另外两样:一个我完全说了算的载具,和一段完整的时间。
载具我已经在造了。
2016 年那篇的结尾我写的是”也许,这种梦想的东西,真的需要以后,再找到这些天才的人,用最纯粹,独立的方式来完成吧”。十年后我大概只改一个词:不一定要找到那些天才的人。
下一个五年,以及下一个二十年
五周年那篇的结尾我引了一句话:
The only way to do great work is to love what you do.
十年后我还是同意,但要补一个更实际的注脚:热爱不会自动持续,它需要被反复放回一个能看见进展的地方。
十五年里我掉线过两次。一次在 2014 年前后,一次在 2017 到 2019。两次都不是因为不爱了,是因为进展消失了。而两次找回来的方式一模一样:找一个只属于自己的、能看见进展的项目,把它做起来。
我给 gkNextEngine 定过三条工程原则:尽量用新技术,不为旧项目留兼容路径;拥抱强大的第三方库,非必要不造轮子;保持代码库小体积,易读性优先。而我给它写下的目标只有三个词:
Just for fun.
这三个词是认真的,但它说的是做法,不是终点。
它的意思是:技术选型不为了赢过谁,管线不为了兼容谁而留退路,做什么不需要任何人批准。gkEngine 当年是带着证明欲的——要像 CryEngine,要拿得出手,要有人知道。这一层现在没有了。
终点是有的,而且很具体:我要它最后能承载一款我完全自由开发的独立游戏。
不是给别人用的通用引擎,不追用户量,也不打算和 UE、Unity 比什么。它只需要在那一天到来的时候,是一个我闭着眼睛都知道每一处该怎么改的地方——想加一个机制就直接加,卡住了就下潜到引擎层解决,中间不隔任何一个我改不动的黑盒。
那一天大概在 FIRE 之后。
行业里 40 岁那道坎,我从 2023 年就开始算。当时算的是焦虑,现在不太是了——我更愿意把它当成一个交割日:交出去的是稳定的收入和被别人安排的时间,换回来的是一段完整的、不用向任何人报备的开发期。
我很清楚那时候要干什么,而且已经清楚很多年了。所以这个仓库不是消遣,是那件事的前置条件。现在做的每一次重构、每一个 demo、每一条 CI,都是在给那段时间做准备。
所以下一个五年,我的 flag 只有一条,因为只有这一条完全由我说了算:
gkNextEngine 一直更新下去。
SDL 的 Sam Lantinga 从 1998 年写到现在,二十多年没停。我希望 2046 年还能打开这个仓库,改一行,编过,跑起来——那时候它最好已经不只是一个引擎了。
一直写到真的写不动那天。
二十周年那篇,2031 年 2 月 22 日。这次我尽量不迟到。