Three.js场景(Scene)技术详解
Three.js是WebGL的流行封装库,用于在浏览器中创建复杂的3D场景。场景(Scene) 作为Three.js的核心容器,承载了所有可见元素(物体、灯光、相机等)。本文将深入探讨场景的各个方面,包括创建、管理、优化及高级应用。
一、场景基础概念
1.1 什么是场景,场景的作用
- 容器角色:所有3D对象(网格、灯光、相机)必须添加到场景中才能被渲染。
- 坐标系管理:维护全局坐标系,所有子对象的位置、旋转、缩放均相对于场景原点。
- 环境控制:管理背景颜色/纹理、雾效、环境光等全局效果。
1.2 创建场景
ini
import * as THREE from 'three';
// 创建场景(可配置背景色或环境光)
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000); // 设置黑色背景
scene.environment = texture; // 设置环境贴图(PBR渲染用)
二、场景结构与层级
2.1 Scene对象结构
Scene继承自THREE.Object3D
,具备树形层级结构:

ini
scene.children = [camera, mesh1, light1, group1, ...];
2.2 操作场景对象
- 添加/移除对象:
csharp
scene.add(mesh);
scene.remove(camera);
Scene中可以添加、移除哪些内容
类型 | 说明 |
---|---|
Mesh | 网格模型,基本的立方体、球体、模型等 |
Light | 各种灯光,比如环境光、点光源、平行光 |
Camera | 相机(一般不会直接添加到场景) |
Group | 分组管理对象 |
Sprites | 精灵(2D 图标) |
Particle Systems | 粒子系统 |
Helpers | 辅助线、坐标轴助手等 |
Audio | 三维声音 |
TransformControls | 变换控制器 |
- 层级遍历:
javascript
scene.traverse((obj) => {
if (obj instanceof THREE.Mesh) {
obj.material.color.set(0xff0000);
}
});
- 查找对象:
ini
const mesh = scene.getObjectByName('hero');
- 使用JSON格式返回场景数据:
scss
scene.toJSON()
- 使用dispose清除WebGLRenderer内部所缓存的场景相关的数据:
scss
scene.dispose()
2.3 场景属性详解
属性 | 类型 | 说明 |
---|---|---|
background |
Color/Texture/CubeTexture | 场景背景 |
environment |
Texture | 环境贴图(影响PBR材质) |
fog |
Fog/FogExp2 | 雾化效果 |
overrideMaterial |
Material | 强制所有物体使用相同材质 |
autoUpdate |
Boolean | 默认值为true,渲染器会检查每一帧是否需要更新场景及其中物体的矩阵。设为false时,得手动维护场景中的矩阵。 |
2.3.1 background设置
arduino
//颜色
scene.background = new THREE.Color(0x000000);
ini
//纹理贴图(天空盒)
const textureLoader = new THREE.TextureLoader();
scene.background = textureLoader.load('sky.jpg');
2.3.2 environment环境贴图设置
arduino
const cubeTextureLoader = new THREE.CubeTextureLoader();
const environmentMap = cubeTextureLoader.load(
[ 'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png' ]
)
scene.environment = environmentMap;
2.3.3 fog雾化设置
ini
const fog = new THREE.Fog(0x000000, 1, 100); // 参数分别为颜色(十六进制)、开始距离、结束距离
scene.fog = fog;
2.3.4 overrideMaterial强制所有物体使用相同材质
ini
scene.overrideMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
2.3.5 autoUpdate设置渲染器是否需要手动维护场景中的矩阵
ini
scene.autoUpdate = true;
三、场景与渲染流程
3.1 渲染循环
scss
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera); // 关键渲染调用
}
3.2 多场景切换
ini
const scene1 = new THREE.Scene();
const scene2 = new THREE.Scene();
// 使用条件判断切换场景
if (level === 2) {
renderer.render(scene2, camera2);
} else {
renderer.render(scene1, camera1);
}
四、高级场景管理技巧
4.1 场景优化策略
- 分组渲染 :Three.js 支持多个场景并行渲染,比如:
- 不同的区域
- 镜头切换
- 小地图(主视角 + 小窗口) const group = new THREE.Group(); group.add(mesh1, mesh2); scene.add(group);
-
视锥体剔除: mesh.frustumCulled = true; // 默认开启
-
LOD(细节层级) : const lod = new THREE.LOD(); lod.addLevel(highDetailMesh, 50); lod.addLevel(lowDetailMesh, 100);
4.2 内存管理
scss
// 彻底移除对象
function disposeObject(obj) {
obj.traverse(child => {
if (child.geometry) child.geometry.dispose();
if (child.material) {
Object.values(child.material).forEach(val => val?.dispose?.());
}
});
scene.remove(obj);
}
4.3 后期处理集成
ini
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
const composer = new EffectComposer(renderer);
composer.addPass(renderPass);
composer.addPass(bloomPass);
// 在动画循环中使用
composer.render(scene, camera);
五、场景调试工具
5.1 场景检查器
csharp
import { GUI } from 'dat.gui';
const gui = new GUI();
gui.add(scene, 'visible').name('显示场景');
gui.addColor(scene, 'background').name('背景颜色');
5.2 性能监控
javascript
import Stats from 'stats.js';
const stats = new Stats();
document.body.appendChild(stats.dom);
function animate() {
stats.update();
// ...渲染逻辑
}
六、实战案例:动态场景加载
javascript
class SceneManager {
constructor() {
this.currentScene = null;
}
async loadScene(sceneConfig) {
const newScene = new THREE.Scene();
// 异步加载模型
const model = await loadGLTF(sceneConfig.modelPath);
newScene.add(model);
// 场景过渡动画
this.transitionScenes(this.currentScene, newScene);
this.currentScene = newScene;
}
transitionScenes(oldScene, newScene) {
// 实现淡入淡出等过渡效果
}
}
附录:完整示例
javascript
import * as THREE from 'three'
// 创建场景
const scene = new THREE.Scene()
scene.background = new THREE.Color(0xcccccc)
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.z = 5
// 创建渲染器
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
// 创建一个立方体
const geometry = new THREE.BoxGeometry()
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
const cube = new THREE.Mesh(geometry, material)
scene.add(cube)
// 动画循环
function animate() {
requestAnimationFrame(animate)
cube.rotation.x += 0.01 cube.rotation.y += 0.01
renderer.render(scene, camera)
}
animate()
七、最佳实践总结
- 层级管理:使用Group组织复杂场景
- 及时清理:切换场景时释放资源
- 性能优先:控制Draw Call数量(合并几何体)
- 合理使用雾效:提升场景深度感知
- 环境贴图:优先使用HDR实现高质量反射