一、Three.js 简介
(一)前世今生
Three.js 是一款运行在浏览器中的 3D 引擎,由 Ricardo Cabello(Mr.doob)在 2010 年 4 月于 GitHub 首次发布 。其起源可追溯到本世纪初,代码最初用 ActionScript 编写,2009 年移植到 JavaScript。随着 WebGL 出现,Paul Brunt 增加渲染功能,使 Three.js 设计为将绘制代码作为模块。Ricardo Cabello 负责 API 设计、创建 CanvasRenderer、SVGRenderer 并整合各种贡献。Branislav Ulicny 主要贡献在材质、着色器和后处理方面,Joshua Koo 创建了第一个面向 3D 文本的 Three.js 样本 。经过多年发展,Three.js 不断完善,已成为 Web 端创建 3D 场景和动画的重要工具,广泛应用于网页游戏、3D 产品展示、虚拟场景构建等领域 。
(二)作用
Three.js 基于原生 WebGL 封装,极大简化了在浏览器中创建和显示 3D 内容的过程。它提供了丰富的功能和接口,开发者无需深入掌握复杂的 WebGL 底层知识,就能轻松创建出精美的 3D 场景,包括各种几何形状、材质、光照效果、动画等,从而为网页带来更加生动、沉浸式的用户体验 。
二、Three.js 三要素
(一)相机(Camera)
相机决定了我们以何种视角观察 3D 场景,就如同现实生活中我们用眼睛看世界,眼睛的位置和观察方向决定了我们看到的画面。在 Three.js 中有多种相机类型,常用的是透视投影相机(PerspectiveCamera)和正投影相机(OrthographicCamera) 。
- 透视投影相机(PerspectiveCamera)
- 原理:模拟人眼观察世界的方式,遵循近大远小的规律。例如,当我们看一条笔直的公路,远处的部分看起来会比近处的窄,这就是透视效果。
- 参数:
- fov(视场角):相机视锥体垂直方向视野角度,好比我们人眼能看到的垂直范围,值越大,看到的范围越广,近大远小效果越明显。例如设置为 75 度,就确定了相机的视野范围。
- aspect(宽高比):视锥体宽度和高度的比值,一般设置为渲染区域(如 canvas 画布)的宽高比。比如画布宽度为 800px,高度为 600px,宽高比就是 800/600 = 4/3 。
- near(近裁面):相机视锥体近截面相对相机的距离,可理解为人眼能看清的最近距离,距离相机小于这个值的物体不会被渲染。
- far(远裁面):相机视锥体远截面相对相机的距离,即人眼能看到的最远距离,距离相机大于这个值的物体也不会被渲染。
- 代码示例:
// 创建一个透视投影相机,视场角75度,宽高比为窗口宽高比,近裁面0.1,远裁面1000
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 设置相机位置,例如在z轴方向距离原点5的位置
camera.position.z = 5;
- 正投影相机(OrthographicCamera)
- 原理:所有物体被渲染出来的尺寸都一样,不受距离影响,常用于二维游戏或需要精确尺寸显示的场景,如建筑图纸展示。
- 参数:
- left、right、top、bottom:分别表示相机视景体左、右、上、下四个面的位置,这四个面和near、far面共同围成一个长方体视景体。
- near、far:与透视投影相机类似,分别表示近裁面和远裁面距离。
- 代码示例:
// 创建一个正投影相机,视景体范围:左 -4,右4,上4,下 -4,近裁面 -200,远裁面500
const camera = new THREE.OrthographicCamera(-4, 4, 4, -4, -200, 500);
(二)场景(Scene)
场景就像是一个虚拟的 3D 世界容器,我们在这个世界里放置各种物体、灯光等元素。它是所有对象的父级,所有要展示的 3D 内容都要添加到场景中,就如同在一个舞台上摆放道具,这个舞台就是场景 。
- 作用:管理和组织场景中的所有对象,包括网格模型(Mesh)、光源(Light)等。场景决定了这些对象的空间关系和渲染顺序 。
- 代码示例:
// 创建一个场景对象
const scene = new THREE.Scene();
例如,我们创建一个简单的立方体并添加到场景中:
// 创建一个立方体几何对象
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 创建一个材质对象
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 创建一个网格模型,由几何对象和材质对象组成
const cube = new THREE.Mesh(geometry, material);
// 将网格模型添加到场景中
scene.add(cube);
(三)渲染器(Renderer)
渲染器的作用是将相机和场景组合起来,把 3D 场景渲染成 2D 图像并显示在页面上,就像是将相机拍摄的 3D 世界照片冲洗出来展示给我们看 。
- WebGL 渲染器(WebGLRenderer):最常用的渲染器,利用浏览器的 WebGL 功能进行硬件加速渲染,能高效地渲染复杂的 3D 场景 。
- 代码示例:
// 创建一个WebGL渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器的尺寸为窗口尺寸
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染器的输出画布添加到页面的body元素中
document.body.appendChild(renderer.domElement);
// 执行渲染操作,将场景和相机传入
renderer.render(scene, camera);
- 其他渲染器:除了 WebGLRenderer,还有 CanvasRenderer(基于 HTML5 Canvas 绘制,性能较低,适用于不支持 WebGL 的浏览器)、CSS3DRenderer(使用 CSS3D 变换实现 3D 效果,对复杂场景支持不好)等 。
三、几何体示例
(一)BoxGeometry(立方体几何体)
- 描述:用于创建一个立方体形状的几何对象,可通过设置参数调整立方体的长、宽、高 。
- 代码示例:
// 创建一个长、宽、高分别为2、1、3的立方体几何体
const geometry = new THREE.BoxGeometry(2, 1, 3);
(二)PlaneGeometry(平面几何体)
- 描述:创建一个平面形状的几何对象,常用于地面、墙面等大面积平坦表面的场景构建。可以设置平面的宽度和高度,以及宽度和高度方向的分段数 。
- 代码示例:
// 创建一个宽度为5,高度为3,宽度和高度方向分段数都为1的平面几何体
const geometry = new THREE.PlaneGeometry(5, 3, 1, 1);
(三)ShapeGeometry(自定义形状几何体)
- 描述:允许我们通过定义一系列的路径和形状来创建复杂的自定义几何对象。先创建一个Shape对象,在上面绘制各种路径(如直线、曲线等),然后通过ShapeGeometry将Shape对象转换为几何体 。
- 代码示例:
// 创建一个Shape对象
const shape = new THREE.Shape();
// 移动到起始点
shape.moveTo(0, 0);
// 绘制一条直线到(100, 0)
shape.lineTo(100, 0);
// 绘制一条曲线到(100, 100)
shape.bezierCurveTo(100, 50, 50, 50, 50, 100);
// 绘制一条直线回到起始点(0, 0)
shape.lineTo(0, 100);
shape.closePath();
// 根据Shape对象创建ShapeGeometry几何体
const geometry = new THREE.ShapeGeometry(shape);
四、光源
(一)环境光(AmbientLight)
- 描述:环境光会均匀地照亮场景中的所有物体,它没有特定的方向,就像现实生活中的环境亮度,比如阴天时整个环境都有一定亮度,没有明显的光线方向 。环境光会影响场景中所有物体的整体亮度,使物体在没有其他直接光源照射时也能被看到 。
- 代码示例:
// 创建一个环境光,颜色为浅灰色(0xcccccc)
const ambientLight = new THREE.AmbientLight(0xcccccc);
// 将环境光添加到场景中
scene.add(ambientLight);
(二)照射光源(如点光源 PointLight)
- 描述:点光源从一个特定的点向各个方向发射光线,就像一个灯泡,光线向四周发散 。点光源可以设置颜色、强度和衰减等属性,强度决定光线的明亮程度,衰减表示光线随着距离增加而减弱的程度 。
- 代码示例:
// 创建一个点光源,颜色为白色(0xffffff),强度为1
const pointLight = new THREE.PointLight(0xffffff, 1);
// 设置点光源的位置,例如在(1, 2, 3)处
pointLight.position.set(1, 2, 3);
// 将点光源添加到场景中
scene.add(pointLight);
五、源码粘贴处
以下是一个完整的 Three.js 示例代码,包含相机、场景、渲染器、立方体几何体、环境光和点光源的创建与设置:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js Example</title>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
</head>
<body>
<script>
// 创建场景
const scene = new THREE.Scene();
// 创建相机
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(1, 1, 1);
// 创建材质
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
// 创建网格模型
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 创建环境光
const ambientLight = new THREE.AmbientLight(0xcccccc);
scene.add(ambientLight);
// 创建点光源
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(1, 2, 3);
scene.add(pointLight);
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>