第一次用 Three.js 搭场景,踩明白的三件事

第一次打开 Three.js 文档时,我以为要学的是「怎么画 3D」。几周之后才明白,真正要学的是三件更朴素的事:坐标、光、相机。

场景是一棵树

Three.js 的一切都挂在场景图上。桌子是一个 Group,桌面和桌腿是它的子节点;移动桌子,桌上的一切跟着走。这个心智模型建立之后,代码突然就顺了——建模不是画画,是搭积木。

const desk = new THREE.Group();
desk.add(top, legFL, legFR, legBL, legBR);
scene.add(desk);

真正会出问题的是原点。指针要绕轴心转,抽屉要沿自己的前后方向滑,这些都要求物体的原点在正确的位置上,而不是几何中心。这一条后来直接写进了我给建模脚本定的命名契约里。

光比几何体重要得多

同一个立方体,平光下是纸板,侧光下是石膏,暖色点光下就成了木头。新手(比如当时的我)总在几何体上较劲,其实材质感的八成来自光照。

后来加了环境贴图才算真的入门。在那之前,黄铜材质怎么调都是塑料——金属需要有东西可以反射,没有环境就没有金属。

按需渲染卡了我半天

场景是静态的,没必要每秒渲染 60 次,所以我做了按需渲染:只有画面真的变了才请求一帧。

结果调试时反复遇到「改了参数但画面不动」。原因很简单:任何视觉变化都必须显式调用 invalidate(),而我总有地方漏掉。后来把所有会改变外观的入口都收敛到少数几个方法里,问题才消失。

顺带一提,光照过渡时每帧重建阴影贴图会卡顿。节流到 150 毫秒一次之后,肉眼看不出差别,帧率稳住了。

下一步

第一个场景做完,最大的收获是知道了下一个场景该从哪开始:先想清楚观众坐在哪,再决定桌上放什么。