把鼠标轨迹变成包浆:一次反直觉的技术选择
2026-10-18 · 桌面开发 / 渲染
我想做一个桌面挂件:两颗核桃放在屏幕角落,你正常工作,它跟着你的鼠标慢慢变红、变润。 听起来简单,做起来第一件事就是选渲染方案。
第一版:序列帧
最直觉的方案是序列帧。用 Blender 把模型按角度渲染成一圈图片,鼠标横向移动就切换帧, 纵向移动就切换俯仰行。这个方案在很多老桌面宠物里都用过,实现最简单。
于是我渲了 36 个角度 × 9 个俯仰,324 张图。问题立刻出现了:
- 每张图颜色都不太一样,切换时明显"跳"
- 角度之间不连贯,转动像在跳帧
- 想加一个"包浆变色"就得把 324 张图重新渲 5 遍
序列帧的本质是把"状态"烘焙进图片。状态一多,组合爆炸。
第二版:实时 3D
换成 three.js 之后,模型只有一份(两万面,2 MB 左右), 颜色、粗糙度、清漆全部是运行时参数。包浆从"白茬"到"玉化"只是把这几个参数从 A 插值到 B, 不需要任何额外图片。
这一步做完,之前所有问题都消失了:
- 旋转是连续的,不再跳帧
- 颜色是同一套材质算出来的,不可能不一致
- 加一个新阶段只要改几个数字
代价:性能
3D 不是免费的。空闲时它以 4–5 fps 渲染(呼吸动画),鼠标靠近时才提到 60 fps。 实测空闲占用大概是单核的 1% 左右,内存 350 MB 上下——对一个 Electron 应用来说可以接受。
中间踩过一个坑:把贴图 UV 的旋转写在了每帧循环里。
// 错:每帧都让贴图重新上传,1 MB 的图每帧传一次
for (const frame of frames) {
material.map.rotation = angle;
material.map.needsUpdate = true; // ← 这里
}
正确做法是只在"这一颗核桃换了"的时候写一次。改完之后空闲 CPU 立刻降下来。
结论
如果一个视觉效果需要"很多状态",别烘焙成图片,做成参数。 序列帧看起来省事,但它把复杂度搬到了资产管理和一致性上,后面会加倍还回来。
相关项目:盘它