Three.js的学习(2)—— Three.js 的一些关键特性

文章同步更新于我的个人博客:松果猿的博客,欢迎访问获取更多技术分享。

同时,您也可以关注我的微信公众号:松果猿的代码工坊,获取最新文章推送和编程技巧。
记录本人three.js的学习之路

在 上一篇文章【Three.js的学习(1)】里,我们已经创建了一个基本的场景。

下面我们对three.js每个特性做一个大致的了解

1. 场景(Scene)

场景是一个容器对象,可以包含物体、摄像机、灯光和渲染器。

操作 代码 说明
创建场景 const scene = new THREE.Scene(); 创建一个3D场景容器
获取场景中的对象 scene.getObjectByName('cube'); 通过名称查找场景中的对象
遍历场景对象 scene.traverse(function(obj) {}); 遍历场景中的所有对象
添加雾效果 scene.fog = new THREE.Fog(0x000000, 1, 1000); 为场景添加雾化效果
克隆场景 scene.clone(); 创建场景的副本
检查对象是否在场景中 scene.children.includes(object); 判断对象是否存在于场景中
获取场景对象数量 scene.children.length; 获取场景中对象的数量
更新场景矩阵 scene.updateMatrix(); 更新场景的变换矩阵
移除单个对象 scene.remove(mesh); 从场景中移除指定的3D对象
移除多个对象 scene.remove(mesh1, mesh2, mesh3); 同时移除多个指定的对象

2. 几何体(Geometry)

几何体定义了物体的形状和结构,例如立方体、球体、圆柱体等。

几何体类型 描述 创建方法
立方体(Box) 一个六面体,每个面都是矩形。 var geometry = new THREE.BoxGeometry(width, height, depth);
球体(Sphere) 一个圆形的三维几何体。 var geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments);
圆柱体(Cylinder) 一个直的圆柱体。 var geometry = new THREE.CylinderGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded);
圆环体(Torus) 一个甜甜圈形状的几何体。 var geometry = new THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments, arc);
平面(Plane) 一个无限大的平面。 var geometry = new THREE.PlaneGeometry(width, height);
圆(Circle) 一个二维圆形。 var geometry = new THREE.CircleGeometry(radius, segments, thetaStart, thetaLength);

创建几何体后,通常需要与材料(Material)一起使用来渲染几何体,如下所示:

javascript 复制代码
// 创建一个立方体几何体
var geometry = new THREE.BoxGeometry(1, 1, 1);

// 创建一个材料
var material = new THREE.MeshBasicMaterial({color: 0x00ff00});

// 创建网格(Mesh),网格由几何体和材料组成
var cube = new THREE.Mesh(geometry, material);

// 将网格添加到场景中
scene.add(cube);

主要的方法属性

属性 描述
vertices 包含几何体所有顶点的数组。
faces 包含几何体所有面的数组。
faceVertexUvs 包含几何体所有面的纹理坐标的数组。
boundingBox 几何体的轴对齐边界框(Axis-Aligned Bounding Box),用于快速剔除和碰撞检测等。
boundingSphere 几何体的包围球,用于快速剔除和碰撞检测等。
方法 描述
clone() 创建当前几何体的一个副本。
dispose() 释放几何体的内存,包括所有的属性数组。
computeVertexNormals() 计算顶点法线,用于平滑光照。
merge() 将参数中的几何体合并到当前几何体中。
rotateX() 绕X轴旋转几何体。
rotateY() 绕Y轴旋转几何体。
rotateZ() 绕Z轴旋转几何体。
translate() 平移几何体。
scale() 缩放几何体。
center() 将几何体居中于原点。

赋值方法

属性/方法 描述 代码示例
直接赋值 直接创建一个新的 Vector3 实例并赋值给对象的属性。 javascript<br>sphere.position = new THREE.Vector3(0, 0, 0);<br>sphere.rotation = new THREE.Vector3(0.5 * Math.PI, 0, 0);<br>sphere.scale = new THREE.Vector3(2, 0, 0);<br>
单个赋值 直接对 Vector3 对象的 xyz 属性进行赋值。 javascript<br>sphere.position.x = 0;<br>sphere.rotation.x = 0.5 * Math.PI;<br>sphere.scale.x = 2;<br>
通过方法赋值 使用 Vector3 对象的 set 方法来赋值。 javascript<br>sphere.position.set(0, 0, 0);<br>sphere.rotation.set(0.5 * Math.PI, 0, 0);<br>sphere.scale.set(2, 0, 0);<br>

3. 摄像机(Camera)

在 Three.js 中,摄像机(Camera)是用于定义场景视图和投影方式的对象。以下是一些常用的摄像机类型及其属性和方法的概述:

透视摄像机(PerspectiveCamera)

透视摄像机模拟人眼的视觉效果,即远处的物体看起来更小。

正交摄像机提供无透视的视图,即物体的大小不会随着距离变化。

javascript 复制代码
PerspectiveCamera( fov, aspect, near, far )
属性/方法 描述 使用方法
fov 视野角度,以度为单位。 camera.fov = 75;
aspect 摄像机的宽高比,通常是窗口或渲染器的宽度除以高度。 camera.aspect = window.innerWidth / window.innerHeight;
near 摄像机的近裁剪面,较小的值可以提高性能,但可能导致渲染问题。 camera.near = 0.1;
far 摄像机的远裁剪面,较大的值可以包含更多的场景,但可能影响性能。 camera.far = 1000;
updateProjectionMatrix 更新摄像机的投影矩阵。 camera.updateProjectionMatrix();
lookAt 使摄像机的前方指向指定的点。 camera.lookAt(scene.position);

正交摄像机(OrthographicCamera)

javascript 复制代码
OrthographicCamera( left, right, top, bottom, near, far )
属性/方法 描述 使用方法
left 摄像机视图的左边界。 camera.left = -10;
right 摄像机视图的右边界。 camera.right = 10;
top 摄像机视图的上边界。 camera.top = 10;
bottom 摄像机视图的下边界。 camera.bottom = -10;
near 摄像机的近裁剪面。 camera.near = -10;
far 摄像机的远裁剪面。 camera.far = 1000;
updateProjectionMatrix 更新摄像机的投影矩阵。 camera.updateProjectionMatrix();
lookAt 使摄像机的前方指向指定的点。 camera.lookAt(scene.position);

摄像机的共同方法

除了特定类型的摄像机属性外,还有一些方法是所有摄像机类型共有的:

属性/方法 描述 使用方法
position 摄像机的位置。 camera.position.set(x, y, z);
rotation 摄像机的旋转。 camera.rotation.set(x, y, z);
scale 摄像机的缩放。 camera.scale.set(scaleX, scaleY, scaleZ);
updateMatrix 更新摄像机的矩阵。 camera.updateMatrix();
updateMatrixWorld 更新摄像机的世界矩阵。 camera.updateMatrixWorld(true);

使用摄像机

以下是如何在 Three.js 中创建和使用摄像机的示例:

javascript 复制代码
// 创建一个透视摄像机
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

// 设置摄像机的位置
camera.position.set(0, 0, 5);

// 将摄像机的前方指向场景的中心
camera.lookAt(new THREE.Vector3(0, 0, 0));

// 创建渲染器并添加到 DOM
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 渲染场景
function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}

animate();

在这个示例中,我们创建了一个透视摄像机,设置了它的位置和方向,并在渲染循环中使用它来渲染场景。

4. 光源(Light)

光源类型

光源类型 代码示例 说明
环境光 const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); 提供全局光照,不产生阴影。第一个参数为颜色,第二个参数为强度。
点光源 const pointLight = new THREE.PointLight(0xffffff, 1, 100); 从一个点向各个方向发光,可以产生阴影。第一个参数为颜色,第二个参数为强度,第三个参数为距离。
平行光 const directionalLight = new THREE.DirectionalLight(0xffffff, 1); 从一个方向发光,可以模拟太阳光,产生阴影。第一个参数为颜色,第二个参数为强度。
聚光灯 const spotLight = new THREE.SpotLight(0xffffff, 1); 从一个点向特定方向发光,形成锥形光束。第一个参数为颜色,第二个参数为强度。可以设置角度、距离等属性。
半球光 const hemisphereLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 1); 从上半球发光,产生柔和的光照效果。第一个参数为上半球颜色,第二个参数为下半球颜色,第三个参数为强度。
区域光 const rectAreaLight = new THREE.RectAreaLight(0xffffff, 1, width, height); 从一个矩形区域发光,适合用于室内场景。

常用属性和方法

  • 位置 :通过 light.position.set(x, y, z) 设置光源的位置。
  • 强度 :通过 light.intensity 属性设置光源的强度。
  • 颜色 :通过 light.color.set(0xff0000) 设置光源的颜色。
  • 阴影 :通过 light.castShadow = true 启用光源的阴影效果。需要设置阴影属性,如 light.shadow.mapSize.widthlight.shadow.mapSize.height
  • 衰减 :点光源和聚光灯可以设置衰减属性,如 light.distancelight.decay

示例代码

javascript 复制代码
// 创建场景
const scene = new THREE.Scene();

// 创建环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);

// 创建点光源
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(10, 10, 10);
scene.add(pointLight);

// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5);
scene.add(directionalLight);

// 创建聚光灯
const spotLight = new THREE.SpotLight(0xffffff, 1);
spotLight.position.set(0, 10, 0);
spotLight.angle = Math.PI / 6; // 设置光束角度
scene.add(spotLight);

5. 材质**(Material)**:

基本材质类型

材质类型 代码 特点
基础材质 new THREE.MeshBasicMaterial() 不受光照影响,均匀着色
lambert材质 new THREE.MeshLambertMaterial() 对光照有反应,漫反射
Phong材质 new THREE.MeshPhongMaterial() 高光效果,可以模拟金属、塑料等
标准材质 new THREE.MeshStandardMaterial() 基于物理的渲染(PBR),真实感更强
法线材质 new THREE.MeshNormalMaterial() 使用法线向量着色

材质常用属性

javascript 复制代码
const material = new THREE.MeshStandardMaterial({
    // 颜色
    color: 0xff0000,  // 红色
    
    // 透明度
    opacity: 0.5,
    transparent: true,
    
    // 纹理
    map: textureLoader.load('texture.jpg'),
    
    // 高光
    shininess: 100,  // Phong材质特有
    
    // 粗糙度和金属感(标准材质)
    roughness: 0.5,  // 0-1之间,表面粗糙程度
    metalness: 0.5,  // 0-1之间,金属感
    
    // 环境贴图
    envMap: envMap,
    
    // 是否显示线框
    wireframe: false
});

纹理贴图示例

javascript 复制代码
// 创建纹理加载器
const textureLoader = new THREE.TextureLoader();

// 加载纹理
const texture = textureLoader.load('texture.jpg');

// 创建材质
const material = new THREE.MeshStandardMaterial({
    // 颜色纹理
    map: texture,
    
    // 法线贴图(凹凸感)
    normalMap: normalTexture,
    
    // 粗糙度贴图
    roughnessMap: roughnessTexture,
    
    // 金属度贴图
    metalnessMap: metalnessTexture
});

高级材质效果

javascript 复制代码
// 多重贴图
const material = new THREE.MeshStandardMaterial({
    // 基础颜色贴图
    map: colorTexture,
    
    // 法线贴图(模拟表面细节)
    normalMap: normalTexture,
    normalScale: new THREE.Vector2(1, 1),
    
    // 环境贴图
    envMap: envMap,
    envMapIntensity: 1
});

// 自发光材质
const emissiveMaterial = new THREE.MeshStandardMaterial({
    color: 0xffff00,
    emissive: 0xffff00,  // 自发光颜色
    emissiveIntensity: 1  // 自发光强度
});

高级技巧

  1. 动态改变材质
javascript 复制代码
// 实时更新材质属性
material.color.set(0x00ff00);  // 改变颜色
material.opacity = 0.8;  // 改变透明度
material.needsUpdate = true;  // 通知渲染器更新
  1. 复制材质
javascript 复制代码
const newMaterial = material.clone();
  1. 材质混合
javascript 复制代码
const material = new THREE.ShaderMaterial({
    uniforms: {
        // 自定义uniform变量
    },
    vertexShader: `...`,
    fragmentShader: `...`
});

6. 纹理(Texture)

纹理(Textures)是用于给3D对象添加外观和细节的关键元素。纹理可以模拟各种材料的表面,如木材、金属、水等。以下是一些常用的纹理类型及其属性和方法:

常用纹理类型及其属性

纹理类型 描述 主要属性/方法
Texture 基础纹理类型,用于添加颜色、图案等。 minFilter, magFilter, wrapS, wrapT, offset, repeat, rotation
CanvasTexture 用于从 HTML5 <canvas> 元素创建纹理。 image, needsUpdate, format, type, anisotropy, colorSpace
DataTexture 用于创建自定义数据纹理,如深度图或法线图。 image, data, format, type, colorSpace
CubeTexture 立方体贴图,用于环境映射和反射。 images, format, mapping, minFilter, magFilter
VideoTexture 用于从视频元素创建纹理。 video, minFilter, magFilter, format, type
CompressedTexture 用于创建压缩纹理,减少内存使用。 mipmaps, generateMipmaps, premultiplyAlpha

纹理设置属性

属性 代码 说明
重复 texture.repeat.set(2, 2) 设置纹理重复次数
偏移 texture.offset.set(0.5, 0.5) 设置纹理偏移量
旋转 texture.rotation = Math.PI/4 设置纹理旋转角度
包裹模式 texture.wrapS = THREE.RepeatWrapping 设置水平包裹模式
过滤方式 texture.minFilter = THREE.LinearFilter 设置纹理缩小过滤
翻转Y轴 texture.flipY = false 控制纹理是否垂直翻转
编码 texture.encoding = THREE.sRGBEncoding 设置纹理编码方式
更新 texture.needsUpdate = true 标记纹理需要更新

常见贴图类型

**贴图(Map)**是纹理在材质上的具体应用,定义纹理如何影响物体外观

javascript 复制代码
const material = new THREE.MeshStandardMaterial({
    map: colorTexture,          // 颜色贴图
    normalMap: normalTexture,   // 法线贴图
    roughnessMap: roughMap,     // 粗糙度贴图
    bumpMap: bumpTexture,       // 凹凸贴图
    aoMap: aoTexture,          // 环境遮挡贴图
    displacementMap: dispMap    // 置换贴图
});

7. 其他

相机控制器(OrbitControls)

方法/属性 代码 说明
创建控制器 const controls = new OrbitControls(camera, renderer.domElement) 初始化轨道控制器
启用阻尼 controls.enableDamping = true 添加惯性
自动旋转 controls.autoRotate = true 相机自动围绕目标旋转
缩放限制 controls.minDistance = 2; controls.maxDistance = 10 设置缩放范围
更新控制器 controls.update() 在动画循环中更新控制器状态

动画循环

javascript 复制代码
function animate() {
    requestAnimationFrame(animate);
    
    // 更新控制器
    controls.update();
    
    // 更新场景中的对象
    mesh.rotation.x += 0.01;
    
    // 渲染场景
    renderer.render(scene, camera);
}
animate();

交互

交互类型 代码 说明
射线检测 const raycaster = new THREE.Raycaster() 创建射线检测器
鼠标事件 renderer.domElement.addEventListener('click', onClick) 监听鼠标事件
物体选择 raycaster.intersectObjects(objects) 检测射线与物体的交叉
拖拽控制 const dragControls = new DragControls(objects, camera, renderer.domElement) 实现物体拖拽
变换控制 const transformControls = new TransformControls(camera, renderer.domElement) 实现物体的变换控制
相关推荐
0_114 分钟前
让你的网页变的高大上:国际化Vue-i18n
前端·javascript·vue.js
谷隐凡二16 分钟前
fiddler安卓雷电模拟器配置踩坑篇
前端·测试工具·fiddler
哆啦美玲18 分钟前
养成编程思维——栈与队列的运用
前端·javascript·算法
类人_猿33 分钟前
ASP.NET Web(.Net Framework)POST无法正常接收数据
前端·asp.net·.net·post·post请求
城沐小巷1 小时前
外卖点餐系统小程序
前端·后端·微信小程序
东方隐侠安全团队-千里1 小时前
网安瞭望台第6期 :XMLRPC npm 库被恶意篡改、API与SDK的区别
前端·网络·网络安全·npm·node.js
Answer_ism1 小时前
【CSS】一篇掌握CSS
前端·css·html
Layue000001 小时前
学习HTML第三十四天
前端·笔记·学习·html
浪潮行舟1 小时前
css:怎么设置div背景图的透明度为0.6不影响内部元素
前端·css
anyup_前端梦工厂1 小时前
FlyHttp 的诞生:从认识各种网络请求开始
前端·ajax·uni-app