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

Three.js场景(Scene)技术详解

Three.js是WebGL的流行封装库,用于在浏览器中创建复杂的3D场景。场景(Scene) 作为Three.js的核心容器,承载了所有可见元素(物体、灯光、相机等)。本文将深入探讨场景的各个方面,包括创建、管理、优化及高级应用。

一、场景基础概念

1.1 什么是场景,场景的作用

  • 容器角色:所有3D对象(网格、灯光、相机)必须添加到场景中才能被渲染。
  • 坐标系管理:维护全局坐标系,所有子对象的位置、旋转、缩放均相对于场景原点。
  • 环境控制:管理背景颜色/纹理、雾效、环境光等全局效果。

1.2 创建场景

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,具备树形层级结构:

在这里插入图片描述

scene.children = [camera, mesh1, light1, group1, ...];

2.2 操作场景对象

  • 添加/移除对象
scene.add(mesh); 
scene.remove(camera);

Scene中可以添加、移除哪些内容

类型说明
Mesh网格模型,基本的立方体、球体、模型等
Light各种灯光,比如环境光、点光源、平行光
Camera相机(一般不会直接添加到场景)
Group分组管理对象
Sprites精灵(2D 图标)
Particle Systems粒子系统
Helpers辅助线、坐标轴助手等
Audio三维声音
TransformControls变换控制器
  • 层级遍历
scene.traverse((obj) => {
  if (obj instanceof THREE.Mesh) {
    obj.material.color.set(0xff0000);
  }
});
  • 查找对象
const mesh = scene.getObjectByName('hero');
  • 使用JSON格式返回场景数据
scene.toJSON()
  • 使用dispose清除WebGLRenderer内部所缓存的场景相关的数据
scene.dispose()

2.3 场景属性详解

属性类型说明
backgroundColor/Texture/CubeTexture场景背景
environmentTexture环境贴图(影响PBR材质)
fogFog/FogExp2雾化效果
overrideMaterialMaterial强制所有物体使用相同材质
autoUpdateBoolean默认值为true,渲染器会检查每一帧是否需要更新场景及其中物体的矩阵。设为false时,得手动维护场景中的矩阵。
2.3.1 background设置
//颜色
scene.background = new THREE.Color(0x000000);
//纹理贴图(天空盒)
const textureLoader = new THREE.TextureLoader();
scene.background = textureLoader.load('sky.jpg');
2.3.2 environment环境贴图设置
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雾化设置
const fog = new THREE.Fog(0x000000, 1, 100); // 参数分别为颜色(十六进制)、开始距离、结束距离
scene.fog = fog;
2.3.4 overrideMaterial强制所有物体使用相同材质
scene.overrideMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
2.3.5 autoUpdate设置渲染器是否需要手动维护场景中的矩阵
scene.autoUpdate = true;

三、场景与渲染流程

3.1 渲染循环

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera); // 关键渲染调用
}

3.2 多场景切换

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; // 默认开启
  1. LOD(细节层级)
const lod = new THREE.LOD();
lod.addLevel(highDetailMesh, 50);
lod.addLevel(lowDetailMesh, 100);

4.2 内存管理

// 彻底移除对象
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 后期处理集成

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 场景检查器

import { GUI } from 'dat.gui';

const gui = new GUI();
gui.add(scene, 'visible').name('显示场景');
gui.addColor(scene, 'background').name('背景颜色');

5.2 性能监控

import Stats from 'stats.js';

const stats = new Stats();
document.body.appendChild(stats.dom);

function animate() {
  stats.update();
  // ...渲染逻辑
}

六、实战案例:动态场景加载

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) {
    // 实现淡入淡出等过渡效果
  }
}

附录:完整示例

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实现高质量反射

更多three.js、cesium.js开源案例,请移至https://gitee.com/giser2017/threejs-cesium-webgpu-vue-js

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值