当前位置: 首页 > news >正文

第一部分-Three.js基础入门——02. 场景

02. 场景(Scene)

1. 概述

场景(Scene)是 Three.js 中所有 3D 对象的容器,类似于电影拍摄中的舞台。所有物体、光源、辅助对象都需要添加到场景中才能被渲染。

┌─────────────────────────────────────────────────────────────┐ │ 场景 (Scene) │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ 网格 │ │ 光源 │ │ 相机 │ │ │ │ (Mesh) │ │ (Light) │ │ (Camera) │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ 辅助对象 │ │ 粒子系统 │ │ 组 │ │ │ │ (Helper) │ │ (Points) │ │ (Group) │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ 场景属性 │ │ ├── background: 背景色/纹理 │ │ ├── fog: 雾效 │ │ ├── environment: 环境贴图 │ │ └── children: 子对象列表 │ │ │ └─────────────────────────────────────────────────────────────┘

2. 创建场景

2.1 基础场景

import*asTHREEfrom'three';// 创建场景constscene=newTHREE.Scene();// 设置背景颜色scene.background=newTHREE.Color(0x111122);// 设置背景纹理consttextureLoader=newTHREE.TextureLoader();constbgTexture=textureLoader.load('path/to/texture.jpg');scene.background=bgTexture;

2.2 场景属性

// 场景名称(用于调试)scene.name='MainScene';// 场景可见性scene.visible=true;// 场景中的对象列表console.log(scene.children);// 场景中的对象数量console.log(scene.children.length);// 自动更新矩阵scene.matrixAutoUpdate=true;

3. 添加与移除对象

3.1 添加对象

import*asTHREEfrom'three';constscene=newTHREE.Scene();// 创建立方体constgeometry=newTHREE.BoxGeometry(1,1,1);constmaterial=newTHREE.MeshStandardMaterial({color:0x44aa88});constcube=newTHREE.Mesh(geometry,material);// 添加到场景scene.add(cube);// 添加多个对象constsphereGeometry=newTHREE.SphereGeometry(0.5,32,32);constsphereMaterial=newTHREE.MeshStandardMaterial({color:0xff6600});constsphere=newTHREE.Mesh(sphereGeometry,sphereMaterial);sphere.position.set(1.5,0,0);scene.add(sphere);constcylinderGeometry=newTHREE.CylinderGeometry(0.5,0.5,1,32);constcylinderMaterial=newTHREE.MeshStandardMaterial({color:0x44aaff});constcylinder=newTHREE.Mesh(cylinderGeometry,cylinderMaterial);cylinder.position.set(-1.5,0,0);scene.add(cylinder);

3.2 移除对象

// 通过引用移除scene.remove(cube);// 通过名称查找并移除cube.name='myCube';constfoundCube=scene.getObjectByName('myCube');if(foundCube){scene.remove(foundCube);}// 移除所有对象while(scene.children.length>0){scene.remove(scene.children[0]);}// 清理内存(重要!)cube.geometry.dispose();cube.material.dispose();scene.remove(cube);

3.3 查找对象

// 按名称查找constobject=scene.getObjectByName('myCube');// 按类型查找constcubes=scene.children.filter(child=>child.isMesh);// 按位置查找constobjectsAtPosition=scene.children.filter(obj=>obj.position.x===0&&obj.position.y===0);

4. 场景背景

4.1 纯色背景

// 十六进制颜色scene.background=newTHREE.Color(0x000000);// RGB 颜色scene.background=newTHREE.Color(0.1,0.2,0.3);// 颜色名称scene.background=newTHREE.Color('skyblue');

4.2 纹理背景

// 单张纹理consttextureLoader=newTHREE.TextureLoader();constbgTexture=textureLoader.load('path/to/background.jpg');scene.background=bgTexture;// 立方纹理(天空盒)constcubeTextureLoader=newTHREE.CubeTextureLoader();constskyboxTexture=cubeTextureLoader.load(['px.jpg','nx.jpg',// 右、左'py.jpg','ny.jpg',// 上、下'pz.jpg','nz.jpg'// 前、后]);scene.background=skyboxTexture;scene.environment=skyboxTexture;// 环境反射

4.3 渐变色背景

// 使用 CanvasTexture 实现渐变背景constcanvas=document.createElement('canvas');canvas.width=512;canvas.height=512;constctx=canvas.getContext('2d');// 创建渐变constgradient=ctx.createLinearGradient(0,0,canvas.width,canvas.height);gradient.addColorStop(0,'#1a1a2e');gradient.addColorStop(0.5,'#16213e');gradient.addColorStop(1,'#0f3460');ctx.fillStyle=gradient;ctx.fillRect(0,0,canvas.width,canvas.height);constgradientTexture=newTHREE.CanvasTexture(canvas);scene.background=gradientTexture;

5. 雾效

5.1 线性雾

// 线性雾:距离越远越模糊// 参数:颜色、开始距离、结束距离scene.fog=newTHREE.Fog(0x111122,10,30);// 动态更新scene.fog.color.setHex(0x223344);scene.fog.near=5;scene.fog.far=25;

5.2 指数雾

// 指数雾:密度指数增长// 参数:颜色、密度scene.fog=newTHREE.FogExp2(0x111122,0.05);// 密度越大,雾越浓scene.fog.density=0.08;

5.3 移除雾效

// 设置为 null 移除雾scene.fog=null;

6. 场景组织

6.1 使用 Group 分组

// 创建组constgroup=newTHREE.Group();// 添加物体到组constcube1=newTHREE.Mesh(geometry,material);cube1.position.set(-1,0,0);constcube2=newTHREE.Mesh(geometry,material);cube2.position.set(1,0,0);group.add(cube1,cube2);scene.add(group);// 移动整个组group.position.y=1;group.rotation.y=Math.PI/4;// 遍历组内对象group.children.forEach(child=>{console.log(child.position);});

6.2 对象层级

// 父子关系constparent=newTHREE.Object3D();constchild=newTHREE.Object3D();parent.add(child);// 子对象的位置是相对于父对象的parent.position.set(1,0,0);child.position.set(1,0,0);// child 的世界坐标是 (2, 0, 0)// 获取世界坐标constworldPosition=child.getWorldPosition(newTHREE.Vector3());

6.3 辅助对象

// 坐标轴辅助器constaxesHelper=newTHREE.AxesHelper(5);scene.add(axesHelper);// 网格辅助器constgridHelper=newTHREE.GridHelper(20,20,0x888888,0x444444);scene.add(gridHelper);// 平面辅助器constplaneHelper=newTHREE.PlaneHelper(newTHREE.Plane(newTHREE.Vector3(0,1,0),0),5,0xff0000);scene.add(planeHelper);// 相机辅助器constcameraHelper=newTHREE.CameraHelper(camera);scene.add(cameraHelper);// 光源辅助器constlight=newTHREE.DirectionalLight(0xffffff,1);light.position.set(5,5,5);scene.add(light);constlightHelper=newTHREE.DirectionalLightHelper(light,0.5);scene.add(lightHelper);

7. 场景遍历与优化

7.1 遍历所有对象

// 递归遍历场景functiontraverseScene(object,callback){callback(object);object.children.forEach(child=>{traverseScene(child,callback);});}traverseScene(scene,(obj)=>{if(obj.isMesh){console.log('Mesh:',obj.name,obj.position);}});// 使用 Three.js 内置方法scene.traverse((obj)=>{if(obj.isMesh){obj.material.color.setHex(0xff0000);}});

7.2 性能优化

// 隐藏/显示对象(不渲染,但仍在场景中)cube.visible=false;// 禁用阴影cube.castShadow=false;cube.receiveShadow=false;// 批量添加(避免多次渲染)constobjects=[cube,sphere,cylinder];scene.add(...objects);// 清理场景functionclearScene(){scene.traverse((obj)=>{if(obj.isMesh){obj.geometry.dispose();if(obj.material){if(Array.isArray(obj.material)){obj.material.forEach(m=>m.dispose());}else{obj.material.dispose();}}}});while(scene.children.length>0){scene.remove(scene.children[0]);}}

8. 完整示例:多物体场景

import*asTHREEfrom'three';import{OrbitControls}from'three/examples/jsm/controls/OrbitControls.js';// 创建场景constscene=newTHREE.Scene();scene.background=newTHREE.Color(0x0a0a2a);scene.fog=newTHREE.FogExp2(0x0a0a2a,0.01);// 创建相机constcamera=newTHREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);camera.position.set(5,5,10);camera.lookAt(0,0,0);// 创建渲染器constrenderer=newTHREE.WebGLRenderer({antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);renderer.shadowMap.enabled=true;document.body.appendChild(renderer.domElement);// 轨道控制constcontrols=newOrbitControls(camera,renderer.domElement);controls.enableDamping=true;// 添加物体constgeometry=newTHREE.BoxGeometry(1,1,1);constmaterial=newTHREE.MeshStandardMaterial({color:0x44aa88,metalness:0.5,roughness:0.3});constcube=newTHREE.Mesh(geometry,material);cube.castShadow=true;cube.receiveShadow=true;scene.add(cube);constsphereGeometry=newTHREE.SphereGeometry(0.8,32,32);constsphereMaterial=newTHREE.MeshStandardMaterial({color:0xff6600,metalness:0.2,roughness:0.4});constsphere=newTHREE.Mesh(sphereGeometry,sphereMaterial);sphere.position.set(2,0,0);sphere.castShadow=true;scene.add(sphere);// 添加地面constplaneGeometry=newTHREE.PlaneGeometry(10,10);constplaneMaterial=newTHREE.MeshStandardMaterial({color:0x336699,side:THREE.DoubleSide});constplane=newTHREE.Mesh(planeGeometry,planeMaterial);plane.rotation.x=-Math.PI/2;plane.position.y=-1;plane.receiveShadow=true;scene.add(plane);// 添加光源constambientLight=newTHREE.AmbientLight(0x404040);scene.add(ambientLight);constdirectionalLight=newTHREE.DirectionalLight(0xffffff,1);directionalLight.position.set(5,10,7);directionalLight.castShadow=true;scene.add(directionalLight);constfillLight=newTHREE.PointLight(0x4466cc,0.5);fillLight.position.set(-2,2,3);scene.add(fillLight);// 辅助对象constaxesHelper=newTHREE.AxesHelper(5);scene.add(axesHelper);constgridHelper=newTHREE.GridHelper(20,20);scene.add(gridHelper);// 动画functionanimate(){requestAnimationFrame(animate);// 旋转物体cube.rotation.x+=0.005;cube.rotation.y+=0.01;sphere.rotation.x+=0.008;sphere.rotation.y+=0.008;controls.update();renderer.render(scene,camera);}animate();// 窗口适配window.addEventListener('resize',onWindowResize,false);functiononWindowResize(){camera.aspect=window.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);}

9. 总结

要点说明
场景创建new THREE.Scene()
背景设置scene.background
雾效scene.fog
添加对象scene.add(object)
移除对象scene.remove(object)
查找对象scene.getObjectByName()
对象分组Group
场景遍历scene.traverse()
内存清理dispose()方法

http://www.jsqmd.com/news/723244/

相关文章:

  • GR-RL框架:几何推理与强化学习融合的机器人精密操作方案
  • 专业行业深度测评:磁悬浮展示架厂家榜单出炉,华瑞亚克力磁悬浮展示架、LED灯箱亚克力展示架源头厂家实力在线 - 栗子测评
  • PPTist:免费开源在线PPT制作工具的完整指南
  • 别再被SRIO IP的时钟搞晕了!手把手教你理清log_clk、phy_clk和gt_clk的关系(附Vivado配置避坑指南)
  • BOSS直聘反爬虫机制分析:我的自动打招呼机器人是如何被“温柔”限制的
  • Tessy单元测试避坑指南:指针赋值详解(含函数指针、void*及Target Passing设置)
  • 告别编译踩坑:手把手教你用CMake在Ubuntu 22.04上搞定Live555最新版
  • 2026年3月伸缩棚生产厂家推荐,膜结构/景观棚/停车棚/大型膜结构/体育看台/小区停车棚,伸缩棚厂商口碑推荐 - 品牌推荐师
  • M5Stack ATOMS3 Lite开发板评测与物联网应用实践
  • llama.cpp CUDA Graphs优化:大模型推理性能提升1.2倍
  • VS Code Copilot Next 自动化工作流配置终极手册(2026 Q1实测版):微软内部未公开的4个Context Token优化参数首次披露
  • Arm Zena计算子系统的勘误分类与管理机制解析
  • 按劳分配自动分红程序,颠覆资本优先分红,劳动贡献上链,按贡献自动分配收益,人人公平。
  • 给系统实验新手的make menuconfig保姆级教程:以NJU-ICS-PA的NEMU配置为例
  • CMake项目实战:如何优雅地重定义__FILE__宏,让日志只显示纯文件名?
  • NVIDIA驱动死活装不上/卸不掉?别急着重装系统,先试试修复这个Windows服务
  • 35岁程序员的5条退路:哪条路风险最低、收益最高
  • 焊杯连接器技术解析与应用指南
  • 2026年防锈涂料公司推荐指南,工业涂料/特种涂料/高效导电漆/水性气凝胶涂料 - 品牌策略师
  • Seed-VC语音克隆终极指南:5分钟实现零样本实时语音转换
  • 从FileNotFoundError到Pathlib:用现代Python优雅处理文件路径
  • 金融AI对抗性验证框架:提升决策准确性与可解释性
  • 别再只会chmod 777了!Nginx 403错误的5个排查姿势,从日志到SELinux保姆级指南
  • 想看懂展示架行业门道,亚克力磁悬浮展示架厂家怎么甄别,华瑞磁悬浮展示架、LED灯箱亚克力展示架源头厂家为您详解 - 栗子测评
  • 可视化编排多智能体工作流:AgentOrchestra的设计原理与实战指南
  • 塑料包装定制避坑技巧,PE 塑料袋厂家推荐合集,朗越内膜袋批发厂家、定制厂家、方底袋立体袋源头厂家实力在线 - 栗子测评
  • RAG变轻了,Corpus2Skill:告别检索,直接导航企业知识库
  • 浅谈响应式编程在企业级前端应用 UI 开发中的实践
  • 逆中心化社交审核程序,颠覆平台删帖封号,用户投票决定,内容合规,拒绝一言堂。
  • 蚂蚁AI应用开发一二面面经