从零开始学习three.js(14):一文详解three.js中的场景Scene

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 场景优化策略

  1. 分组渲染 :Three.js 支持多个场景并行渲染,比如:
  • 不同的区域
  • 镜头切换
  • 小地图(主视角 + 小窗口) const group = new THREE.Group(); group.add(mesh1, mesh2); scene.add(group);
  1. 视锥体剔除: mesh.frustumCulled = true; // 默认开启

  2. 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()

七、最佳实践总结

  1. 层级管理:使用Group组织复杂场景
  2. 及时清理:切换场景时释放资源
  3. 性能优先:控制Draw Call数量(合并几何体)
  4. 合理使用雾效:提升场景深度感知
  5. 环境贴图:优先使用HDR实现高质量反射
相关推荐
小桥风满袖3 小时前
Three.js-硬要自学系列12 (各种贴图的综合应用)
前端·css·three.js
databook6 小时前
『Plotly实战指南』--样式定制基础篇
python·数据分析·数据可视化
Mintopia8 小时前
Three.js 与物理引擎配合学习指南
前端·javascript·three.js
烛阴18 小时前
Vec--OpenGL的顶点基础
前端·webgl
马玉霞1 天前
threejs加载stl模型在uniapp中的应用(打包安卓)
three.js
小桥风满袖1 天前
Three.js-硬要自学系列10 (创建纹理贴图、自定义顶点UV坐标)
前端·css·three.js
该怎么办呢1 天前
webgl入门实例-11模型矩阵 (Model Matrix)基本概念
线性代数·矩阵·webgl
该怎么办呢1 天前
webgl入门实例-11WebGL 视图矩阵 (View Matrix)基本概念
数码相机·矩阵·webgl
Mintopia1 天前
场景层级基础概念
前端·javascript·three.js