第八章 雨夜、像素与五千里外的声音

4月30日凌晨,雨还在下。

李君宪的台灯是宿舍唯一的光源,在潮湿的空气里晕开一团暖黄。屏幕上,两行代码已经对峙了二十分钟:

if (player.idleTime > 10.0f) { // 玩家静止超过10秒

world.timeScale = 5.0f; // 世界时间流速×5

interiorLight.freeze(); // 室内光影冻结

} else {

world.timeScale = 1.0f;

interiorLight.syncWithWorldTime();

}

逻辑很简单。但“室内光影冻结”这个函数,怎么写?

他试了三个方案:一是直接停止室内所有光源的计算,但这样室内会变成一片死黑,没有“凝固感”,只有“熄灭感”。二是记录玩家静止瞬间的光影状态,然后锁定贴图,但窗外的动态影子还在动,内外就撕裂了。三是陈末建议的:用双层渲染,室内层用静态快照,室外层正常更新,中间用遮罩过渡。

第三个方案最合理,但实现起来也最复杂。需要重写整个场景的绘制管线,而距离陈末承诺的“5月10日完成渲染模块”只剩十天。

李君宪揉了揉发涩的眼睛,看向窗外。雨丝在路灯的光晕里斜斜划过,像无数道银线。他忽然想起张明远笔记里的话:“冲淡者,非静止也,乃动中之静。譬如坐看云起,云动而心不动。”

他重新看向代码。

也许不该是“冻结”,而是“抽离”。让玩家从世界的正常流速中暂时抽离出来,成为一个观察者。室内不是不动,是以另一种节奏在动——极慢,慢到几乎静止。而窗外,是快的,是流变的。

他删掉那两行,重新写:

if (player.enterIdleState()) {

timeSystem.splitTimeline(); // 分裂时间轴

// 室内时间轴:流速 0.1

// 窗外时间轴:流速 5.0

// 中间过渡带:渐变

}

邮件提示音打断了他。是叶晚,凌晨两点三十七分发的。

“君宪哥,林薇姐,苏语姐,陈末哥:我试了新的茶杯画法。裂纹只用了一个像素的深浅变化,但加了一点‘釉面反光’——在裂纹最深处旁边,点了一个几乎看不见的亮像素。这样看起来,裂纹像是被摩挲了很多年,边缘光滑了。不知道对不对。图在附件。另外,我画了一套‘磨损’的素材:桌面的划痕、灶台的烟渍、门槛的凹陷。每种都做了三个程度的磨损:轻、中、重。可以随机组合,让每次游戏开局的场景都有些微不同。如果觉得可行,我可以继续画其他物品。”

附件里是十张32x32的像素图。李君宪一张张点开。茶杯的裂纹确实有了“经年”的质感。划痕不是简单的白线,而是带着木头纹理的断裂感。烟渍最绝:不是均匀的黑,是深浅不一的灰,有些地方浓得像是积了多年油垢,有些地方淡得像刚擦过但没擦干净。

他回复:“很好。就用这个方向。磨损素材的想法很棒,能增加世界的‘生活感’。你继续画,但注意休息,别熬太晚。”

发送。一分钟后,叶晚回复了,快得像在等:“没事,我不困。我妈睡了,我正好画画。”

这句话让李君宪停顿了一下。他想起张明远说的,叶晚母亲身体不好。凌晨两点多,她母亲睡了,她一个人在画画。那个“家”的场景,在夜色里浮现:也许是一间老房子,一盏小台灯,一个女孩在屏幕前,用像素重建记忆中的磨损。

他关掉邮件,打开QQ群。林薇半小时前发了条消息:

“光影分层方案我画了示意图。核心是‘窗框’作为分界线。窗框内,一切物体的投影都锁定在玩家进入静止状态的那一瞬间。窗框外,影子正常快速移动。但分界线不能太硬,需要3-5个像素的渐变过渡,模拟光线在窗棂处的散射。图发群文件了。”

他下载图片。是手绘的示意图,用铅笔打了细致的网格,标注了光影角度和渐变范围。最下面有一行小字:“此方案需程序支持动态遮罩,陈末看看是否可行?”

陈末在下面回复了,时间是一分钟前:“可行。我可以用模板缓冲区做遮罩。但需要美术提供窗框区域的精确遮罩图,带Alpha通道。林薇你能出吗?”

林薇:“能。明天给。”

苏语在凌晨一点发了条语音消息,李君宪点开。先是窸窸窣窣的摩擦声,然后是极轻的、带着气声的女声:“我录到了老木门的声音。在琴房仓库找到一扇废门,轴都锈了。推的时候,声音是‘吱——嘎——’,尾音很长,有颤音。我做了降噪,保留了那种‘涩’感。但觉得太真实了,反而有点突兀。是不是应该再做一点抽象处理?比如只保留头尾两个音,中间拉长,做成‘吱…………嘎……’的感觉?我做了两个版本,发群文件了。另外,陶罐盖子的声音没找到合适的罐子,我用瓷杯盖扣在玻璃碗上模拟,声音太脆了。明天去旧货市场看看。”