Scene 到底是什么?别再把它当“容器”这么简单
一、Scene 到底是什么?别再把它当“容器”这么简单
在 three.js 里,Scene 常被一句话带过:
Scene 是一个容器,用来放物体、灯光和相机。
这句话没错,但非常不够。
更准确地说:
Scene 是 three.js 世界的“根节点(Root)”,是一次渲染的完整上下文。
它承担了三件非常核心的事情:
- 组织层级结构(Scene Graph)
- 决定哪些对象参与渲染
- 作为 Renderer 渲染时的入口
当你调用:
renderer.render(scene, camera)
实际上发生的是:
- 从
scene这个根节点开始 - 深度遍历整个对象树
- 找出可见的 Mesh、Light、Fog、Background
- 结合 camera 进行一次完整的绘制流程
👉 Scene = 一次渲染世界的“宇宙起点”
二、Scene Graph:three.js 的“世界观”
Scene 的底层,本质是一个树形结构(Scene Graph)。
Scene
├── Group
│ ├── Mesh
│ └── Mesh
├── Light
└── Camera(可选)
1️⃣ Scene 继承关系
Object3D
└── Scene
这意味着:
-
Scene 本身也是一个
Object3D -
它拥有:
- position / rotation / scale
- children
- add / remove / traverse 等方法
但有一点很关键:
Scene 的 transform(位置、旋转)几乎不会被用到
你不会把整个世界再平移一遍,对吧?
2️⃣ add 到 Scene 的对象,都会被“接管”
scene.add(mesh)
这一步意味着:
- mesh 成为 scene 的子节点
- mesh 的世界坐标 = 父节点变换 × 自身变换
- renderer 在渲染时会自动遍历到它
⚠️ 注意:
只有挂在 scene 下的对象,才有可能被渲染
这也是为什么很多初学者会遇到:
“我 mesh 明明创建了,但怎么什么都没显示?”
90% 的原因:忘了 add 到 scene
三、Scene 里到底能放什么?
1️⃣ Mesh(最常见)
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
这是你看到“东西”的根本来源。
2️⃣ Light(灯光)
灯光一定要在 scene 里,否则不会生效:
const light = new THREE.DirectionalLight(0xffffff, 1)
scene.add(light)
很多人灯光没效果,本质原因是:
- 灯光创建了
- 但没 add 到 scene
3️⃣ Camera(可选)
技术上讲,相机不一定要加到 scene:
renderer.render(scene, camera)
camera 是单独传进去的。
但在一些场景下,把 camera 放进 scene 是非常有用的:
scene.add(camera)
比如:
- 相机要跟随某个物体
- 相机作为某个 Group 的子节点
- 做“第一人称 / 第三人称”结构
4️⃣ Group(强烈推荐使用)
Scene 里不要直接堆一堆 Mesh。
正确的工程化做法是:用 Group 管理结构。
const car = new THREE.Group()
car.add(body)
car.add(wheel1, wheel2)
scene.add(car)
好处非常多:
- 整体移动 / 缩放 / 旋转
- 逻辑结构清晰
- 后期动画、交互非常好写
四、Scene 的常用属性(被忽略但很重要)
1️⃣ background:背景
scene.background = new THREE.Color(0x000000)
或者用贴图:
const texture = new THREE.TextureLoader().load('bg.jpg')
scene.background = texture
💡 背景不是 DOM,也不是 CSS,而是 WebGL 世界的一部分。
2️⃣ fog:雾效(提升空间感神器)
scene.fog = new THREE.Fog(0x000000, 10, 100)
雾效的作用:
- 提升纵深感
- 遮挡远处细节
- 大场景性能优化(视觉层面)
新手很少用,但一用就“质感暴涨”
3️⃣ environment:环境贴图(PBR 场景必备)
scene.environment = envMap
在使用 MeshStandardMaterial / MeshPhysicalMaterial 时,环境贴图会直接影响金属、反射、质感。
五、Scene 的生命周期与性能意识
1️⃣ Scene 不应该频繁 new
❌ 错误做法:
function render() {
const scene = new THREE.Scene()
renderer.render(scene, camera)
}
✔ 正确做法:
const scene = new THREE.Scene()
function animate() {
requestAnimationFrame(animate)
renderer.render(scene, camera)
}
Scene 通常是长生命周期对象。
2️⃣ 清理 Scene(很重要)
当你做:
- 页面切换
- 场景重建
- 模型替换
一定要注意释放资源:
scene.traverse(obj => {
if (obj.isMesh) {
obj.geometry.dispose()
obj.material.dispose()
}
})
否则:
- GPU 显存泄漏
- 页面越用越卡
- 刷新才能恢复
六、一个“工程级”的 Scene 组织示例
const scene = new THREE.Scene()
// 背景 & 雾
scene.background = new THREE.Color('#111')
scene.fog = new THREE.Fog('#111', 10, 80)
// 灯光组
const lights = new THREE.Group()
lights.add(new THREE.AmbientLight(0xffffff, 0.4))
lights.add(new THREE.DirectionalLight(0xffffff, 1))
scene.add(lights)
// 物体组
const world = new THREE.Group()
scene.add(world)
// 模型
const cube = new THREE.Mesh(
new THREE.BoxGeometry(),
new THREE.MeshStandardMaterial({ color: 'orange' })
)
world.add(cube)
这种结构的优点:
- Scene 只负责“世界”
- lights / world 职责清晰
- 后期扩展非常轻松
七、初中级开发者常见误区总结
❌ 把 Scene 当数组一样乱塞对象
❌ 所有 Mesh 都直接 add 到 scene
❌ 不用 Group,后期动画一团乱
❌ 忽略 fog / background / environment
❌ 不清理 Scene,显存慢慢爆掉
八、你真正需要记住的三句话
1️⃣ Scene 是 three.js 世界的根节点
2️⃣ 渲染从 Scene 开始,一切结构都源于 Scene Graph
3️⃣ 写 three.js 项目,Scene 设计 ≈ 架构设计
更多推荐


所有评论(0)