(本文由 Codex 辅助整理。)

写《轨道双子星》的通关简评时,我留了一个没搞懂的问题:游戏明明是 3D 建模,为什么看上去那么像以前的动画片?当时我特别注意到画面里的噪点,猜它可能是三渲二的一种常用技巧。

没想到开发团队刚好把技术博客放出来了。《走进复古动漫风格游戏:探索〈Orbitals〉的渲染技术》由 Shapefarm 的 Johannes Varmedal 撰写,2026 年 9 月 3 日发布在 Unreal Engine 官网。能直接看到开发者讲怎么做,还附了可以左右拖动的渲染对比图,太合适了。

读完觉得只看文字不过瘾,我就让 Codex 做了一个能转动、能开关效果的小实验。折腾到最后,我反而觉得自己一开始抓错了重点:在这个简单模型上,三段色阶带来的二维感最明显,噪点是后来才调到合适位置的。

月面维修机器人渲染对比:左半边为普通 3D,右半边为三段色阶、钢笔描边和胶片颗粒效果

同一个模型,左边普通 3D,右边是我们调好的复古手绘效果。下面可以直接试玩。

Orbitals 官方分屏合作截图:两位角色穿行在岩壁、管道和橙色机械装置之间

Orbitals 的分屏合作场景,角色的色块和背景管道的受光各有各的画法。官方截图来自 Kepler Interactive,© Shapefarm KK。

角色、背景和胶片,各自做各自的事

官方文章把渲染拆成了几个层次。角色等前景元素用赛璐璐着色,每个资产可以指定三档颜色;背景使用绘画着色器,笔触纹理参与光照扩散,环境和光照保持静止。两者合成后,最后再加胶片颗粒、光晕、色差和模糊。原文

这让我有了一个更好用的观察方法。看机器人的头盔,就看亮面和阴影怎么分;看后面的石头、地面,就看颜色怎样随着受光慢慢变化;最后把视线放回整张画面,才看那些细颗粒。它们虽然都影响“像不像动画”,作用的位置却不同。

文章里还有一个让我印象很深的取舍:角色不向环境投射通常的计算阴影,接地感用简化的阴影贴花处理。我的理解是,前景和背景可以保留一点分层的感觉,不必把两种画法完全揉到一起。

于是实验里也保留了两套材质。机器人用明显的明暗色块,月面平台和石头保持更柔和的受光;脚底垫一个简单的椭圆阴影。光线滑块只影响角色,转动它时,背景不会跟着一起换灯。

先把小机器人放在这里

这只大头维修机器人是程序生成的,身体、头盔、手臂和小助手都由简单几何体拼起来。

可以先在同一个角度切换“普通 3D”和“干净赛璐璐”,再试“复古手绘”。“左右对照”会把同一幅画面分开,左边显示连续光照,右边显示当前效果,两边共用当前的动作节奏。“12 帧动作”可以单独开关。

电脑上拖动旋转、滚轮缩放;手机可以拖动画面,也可以用下面的“观察角度”滑块。如果正文里看着太小,单独打开实验会舒服一些。暂停以后再逐项切换,最容易看出差别。

色阶一开,变化就很明显

“普通 3D”模式下,头盔从亮到暗是连续渐变,眼睛和肩膀上还有小小的高光,很像一个摆在桌上的塑料玩具。模型和镜头都不动,只把明暗压成几块,感觉立刻变了。

实验里负责色阶的核心代码就两行:

1
2
float d = dot(normalize(vN), light);
vec3 c = d < 0.02 ? shade : (d < 0.57 ? base : lit);

vN 是表面朝向,light 是光照方向。算出来的值落在哪一段,就选阴影色、中间色或亮色。

我来回开关以后,给 Codex 的反馈是:

我觉得那种2D的感觉最主要是靠三段色阶,其他属于锦上添花。

关掉颗粒,机器人仍然很像卡通画面;关掉三段色阶,平滑的体积感马上又回来了。

配色也不能忽略。同样是三档颜色,阴影用什么颜色、亮面有多暖,会直接影响观感。这一版用的是偏暖的头盔和橙色身体,阴影稍微偏冷。

动作可以一顿一顿,线条别抖过头

小助手上下浮动时,切换“12 帧动作”最容易看出区别。开启后,它会短暂保持一个位置,再跳到下一个位置;镜头仍然可以连续转动。这个 demo 做法很直接:把用于计算姿态的时间按十二分之一秒取整。

Orbitals 把特效和非骨骼动画的动态赛璐璐元素按 12 fps、偶尔 6 fps 更新,角色动画单独制作,镜头渲染保持至少 30 fps。原文 我们就让机器人的各部件和小助手一起按 12 帧动起来。

第一版的扰动有点大。单看某一张还好,动起来以后,轮廓和阴影边界显得太忙。我把幅度降到 21%,已经能感觉到每张画略有不同,再多反而碍眼。

官方对线条的处理也有条件:用表面编号与深度生成线条,再控制粗细、断线和扭曲;只有角色或摄像机运动时才更新这些扰动。原文 我很喜欢这个“什么时候重画”的想法。站着不动时保留那张画,发生运动时再换一张,至少比让每个边缘一直闪来闪去更接近我要的感觉。

后来我又提了一个要求:描边能不能带一点手绘钢笔的笔触?于是用程序给线条补了粗细变化、局部收细和少量断墨。这就带上了我自己的口味。

背景笔触,我们第一次做错了

这次最值得记下来的返工在背景上。

最初 Codex 给地面和石头铺了很密的程序纹理,远看有点粗糙,行星表面还出现了很明显的花纹。它把这个叫作“背景笔触”,但我看着总觉得不对:怎么又像一层噪点?原博客最后还有专门的胶片处理啊。

我让它回去看文章里的渲染图片,尤其是“我们的环境着色器”下面那组绿色管道场景。把分隔线拉到两边,观察同一根管道的受光变化,比再解释一遍 shader 有用得多。我看到的是较宽、较柔和的明暗变化,管道表面整体仍然很干净。 这个观察,也和原文所说的用笔触纹理控制光线扩散对得上。对比图在官方文章中

新版把那些密集纹理去掉,换成一张固定的、稀疏的宽笔触遮罩。遮罩主要改变中间调的受光过渡,亮部和深暗部保留得更干净;它不会随着动画每帧换一套。现在看石头和行星,能感觉到一点画出来的色块,但不再满眼都是碎纹理。

改到这里,我终于觉得方向对了。

然后我又让它把胶片颗粒稍微加重一点。

我不喜欢石头表面像磨砂纸,却很喜欢整张画面带一点被拍到胶片上的颗粒感。把它们拆成独立开关以后,反馈就具体多了:背景少一点,胶片多一点。

想看清这次区别,可以先关掉“胶片质感”和“亚克力磨砂”,单独开关“背景笔触”,再把胶片打开。噪声还会用于轻微扰动线条和阴影边界,但那和覆盖整张图像的胶片颗粒,也不是同一种用途。

又试了一层亚克力磨砂

后来我又想,能不能给画面加一点亚克力的质感?于是我们在最后叠了一层固定的细噪声,再加少量柔化和乳白色。我把磨砂强度拖到 50%,感觉正好,便把它留作了默认值。机器人仍然有清楚的色块和线条,但画面像隔着一块薄薄的磨砂板。

这个效果让我想起 Windows 11 的界面。查了一下,微软的 Acrylic 材质确实用到了噪声:它把半透明、模糊、排除混合、颜色叠层和噪声组合起来,让平面界面有磨砂玻璃的质感。Acrylic 在 2017 年的 Windows 10 里就已经用上了,Windows 11 又把它调得更明亮、更通透,常见于菜单和浮出面板。Windows 材质说明里还介绍了 Mica:它是取色于桌面壁纸的不透明底层材质。

我们的磨砂噪声固定在屏幕坐标上,转动机器人时,能感觉到画面在这层细纹理后面移动;胶片颗粒则随着播放不断变化。可以关掉“胶片质感”,单独开关“亚克力磨砂”,再拖动强度滑块看区别。我喜欢 50% 这一档,细颗粒能看见,颜色也还保得住。

后来,把它拆成了 Anime Style for Three.js

9 月 19 日更新。 小机器人调到满意以后,我又想:这套效果能不能换到别的 Three.js 模型上?于是把材质、描边和后期拆开,做成了一个开源小库,叫 Anime Style for Three.js(原名 Three Ink)。仓库里也放了一份给 AI agent 用的 skill,说明怎么接到已有场景里、保留动画,以及怎么开关和释放这些效果。

只拿一个暖色机器人测试,还是太容易自我感觉良好。新的风格实验室加了山地、峡谷、长廊和几何体,还找了带骨骼动画的贴图人物、低模人物和表情机器人。左右共用相机和动作姿态,换成宝蓝、朱砂、冰紫或黑白,就能看出原来的观感有多少来自配色。

结果也挺直观:山坡和大块岩壁上的宽笔触比较好认,建筑平面上的变化轻一些;低模人物的头发、脸和关节一压色阶,块面会更明确。原模型的法线和贴图仍然很重要,shader 并不能替模型决定一切。

描边不能把斜面当成阴影

测试人物时,我发现一个有点好笑的问题:镜头压低以后,地面的钢笔描边突然变成一片很宽的黑带,还带着棋盘状的纹路。我甚至问 Codex,这是不是在模仿原博客里的阴影处理?

并不是,是 bug。原来的判断只看相邻像素的深度差。视角接近地面时,同一块平面上的深度变化也很大,就被误认成了一整片边界。修复后先扣掉表面连续的深度变化,再保留真正的轮廓和遮挡线。那片黑带终于消失了。

阴影也可以画得更像动画

既然说到了阴影,我们又回去看了原博客。这次补了三种可以单独开关的处理:角色脚下用抽象的扁平色块接地,轮廓背后加一点片层偏移影,暗部轮廓附近再混入少量亮色。角色原来拉得很长的计算投影关掉以后,前景和背景的分层感反而更明显。

Anime Style for Three.js 动画阴影对照:左侧机器人投出长阴影,右侧改为抽象接地色块,并加入轻微片层偏移影和暗部反光

两边都是三渲二。左边保留普通计算投影,右边换成动画阴影;模型来自 Quaternius / Don McCurdy,CC0。

打开阴影对照实验,可以先关掉颗粒和磨砂,再分别切换“抽象接地影”“片层偏移影”和“暗部反光”。接地色块目前放在平舞台上,换成起伏地形时还需要让它贴合地面。

描边修复和这几种阴影已经放进 v0.3.0。代码、中文接入说明和 agent skill都在公开仓库里。最初那个小机器人的实验仍然留在上面;想换模型、比较配色和背景笔触,可以去玩新的实验室。

换一种二维目标,做法也会变

调研时我还问了业界先进方案怎么做。后来觉得直接排一个“三渲二技术榜”不太合适。比如 Arc System Works 的《Guilty Gear Toon Line Control Techniques》,就花了很多篇幅处理轮廓线的控制,包括把负责光照和描边的法线分开,以及去掉不该出现的线。我们这里主动加了一点断墨,别的画面里,多出来或断掉的那根线可能正是要修掉的问题。

我现在更想先问:目标是哪一种动画?想要干净利落的线稿,就应该让线条干净;想要老动画的摄影质感,再去调颗粒和轻微模糊。效果全开也不会自动变高级。

对 Orbitals,我更佩服的是这些规则最后能在整个游戏里配合起来。最初的小实验只有一个场景,改一下立刻就能检查。真的做成游戏,还得让各种角色、动作、场景和镜头维持同一种画风,并且让美术能持续做内容。

下次在游戏里看到类似画面,我大概会先盯着角色的阴影色块,再看它怎么动,最后才去看那些让我最早产生好奇的颗粒。