Three.js作为WebGL的高效封装库,其核心场景(Scene)对象是构建3D应用的起点。本文将从场景的基础创建到高级应用,结合代码实践与设计思想,全面解析场景的奥秘。
一、场景基础:三维世界的容器
1.1 场景的创建与基本结构
import * as THREE from 'three';
// 创建基础场景
const scene = new THREE.Scene();
scene.name = "MainScene"; // 可命名便于调试
// 典型场景构成
const elements = {
meshes: [], // 网格对象
lights: [], // 光源系统
cameras: [], // 观察视角
helpers: [], // 辅助工具
environment: null // 环境设置
};
1.2 场景图(Scene Graph)体系
Three.js 采用树状结构管理场景元素:
// 创建层级结构
const parentGroup = new THREE.Group();
parentGroup.name = "Building";
const wallMesh = new THREE.Mesh(geometry, material);
const roofMesh = new THREE.Mesh(geometry, material);
parentGroup.add(wallMesh, roofMesh);
scene.add(parentGroup);
// 遍历场景元素
scene.traverse((obj) => {
if (obj instanceof THREE.Mesh) {
obj.material.needsUpdate = true;
}
});
二、场景环境配置
2.1 光源系统搭建
// 环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// 方向光
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(5, 5, 5);
scene.add(dirLight);
// 点光源矩阵
const pointLight = new THREE.PointLight(0xff0000, 10, 5);
pointLight.position.set(5, 5, 5);
scene.add(lightsGrid);
2.2 背景与环境贴图
// 纯色背景
scene.background = new THREE.Color(0x87CEEB);
// 全景环境贴图
new THREE.CubeTextureLoader()
.setPath('textures/skybox/')
.load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
(texture) => {
scene.background = texture;
scene.environment = texture; // 物理材质反射
});
2.3 雾效实现
// 线性雾
scene.fog = new THREE.Fog(0xcccccc, 10, 50);
// 指数雾
scene.fog = new THREE.FogExp2(0xcccccc, 0.1);
// 在材质中启用雾效
material = new THREE.MeshStandardMaterial({
color: 0xff0000,
fog: true
});
三、高级场景管理
3.1 多场景渲染
// 创建多个场景
const mainScene = new THREE.Scene();
const uiScene = new THREE.Scene();
function render() {
renderer.clear();
// 主场景渲染
renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);
renderer.render(mainScene, mainCamera);
// UI场景渲染
renderer.setScissorTest(true);
renderer.setScissor(10, 10, 200, 100);
renderer.render(uiScene, uiCamera);
renderer.setScissorTest(false);
}
3.2 分屏实现
function render() {
// 左半屏
renderer.setScissor(0, 0, sliderPos, height);
renderer.render(sceneLeft, camera);
// 右半屏
renderer.setScissor(sliderPos, 0, width-sliderPos, height);
renderer.render(sceneRight, camera);
}
四、性能优化策略
- 视锥剔除:自动跳过视锥体外物体
- LOD系统:根据距离切换模型精度
- 空间分区:八叉树/四叉树管理
4.1 可见性裁剪
// 使用视锥体剔除
const frustum = new THREE.Frustum();
const matrix = new THREE.Matrix4().multiplyMatrices(
camera.projectionMatrix,
camera.matrixWorldInverse
);
frustum.setFromProjectionMatrix(matrix);
scene.traverse((obj) => {
if (obj.geometry) {
const inView = frustum.intersectsSphere(obj.geometry.boundingSphere);
obj.visible = inView;
}
});
4.2 几何体合并
const mergeGeometry = (geometries, material) => {
const merged = new THREE.BufferGeometry();
const positions = [];
const colors = [];
geometries.forEach(geo => {
positions.push(...geo.attributes.position.array);
colors.push(...geo.attributes.color.array);
});
merged.setAttribute('position',
new THREE.BufferAttribute(new Float32Array(positions), 3));
merged.setAttribute('color',
new THREE.BufferAttribute(new Float32Array(colors), 3));
return new THREE.Mesh(merged, material);
};
4.3 调试工具
- 场景浏览器:
scene-explorer库可视化场景树 - 坐标系辅助器:
scene.add(new THREE.AxesHelper(10));
- 性能监控:
stats.js监控FPS/内存
5.2 性能指标
| 优化方向 | 典型措施 | 性能提升 |
|---|---|---|
| Draw Call | 合并几何体 | 30-50% |
| 纹理内存 | 压缩纹理+Mipmap | 20-40% |
| 着色器复杂度 | 简化光照计算 | 15-25% |
| 动画更新 | 分帧更新不同物体 | 10-30% |
更多three.js、cesium.js开源案例,请移至gitee.com/giser2017/t…