Three.js 场景完全入门指南:让你的 3D 场景不再乱成一团

前言

随着网页技术的不断发展,3D 图形逐渐成为网页设计中不可或缺的一部分。Three.js 是一个强大的 JavaScript 库,使得在网页上创建和展示 3D 图形变得更加简单。无论是游戏开发、数据可视化还是艺术创作,Three.js 都能为你提供丰富的功能和灵活的 API。

本文将深入探讨如何使用 Three.js 创建 3D 场景,帮助你从零开始构建一个完整而有趣的 3D 应用程序。我们将涵盖基本概念、常用功能和最佳实践,并通过具体的案例来说明每个部分。

第一部分:Three.js 简介

1.1 什么是 Three.js?

Three.js 是一个基于 WebGL 的跨平台 JavaScript 库,用于在浏览器中创建和展示 3D 图形。它封装了复杂的 WebGL API,使开发者可以更容易地创建 3D 场景,而无需深入了解底层的图形编程。

1.2 三维空间中的基本概念

在学习 Three.js 之前,我们需要理解一些三维空间中的基本概念:

  • 坐标系:三维空间通常使用右手坐标系表示,其中 X 轴表示水平,Y 轴表示垂直,Z 轴表示深度。

  • 几何体:三维形状的基本构成部分,例如立方体、球体和圆柱体等。

  • 材质:定义几何体表面外观的属性,包括颜色、纹理和光泽度等。

  • 光源:用于照亮场景的元素,可以影响物体的外观和阴影效果。

  • 摄像机:观察场景的“眼睛”,决定了我们看到的内容和视角。

  • 渲染器:将场景渲染为图像并显示在屏幕上的组件。

1.3 安装与设置

要开始使用 Three.js,你首先需要引入库文件。可以通过 CDN 或者将其下载到本地进行使用。以下是通过 CDN 引入的方式:

htmlCopy Code
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Three.js 示例</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> </head> <body> <script> // 这里是 Three.js 代码 </script> </body> </html>

第二部分:创建你的第一个 Three.js 场景

2.1 初始化场景

首先,我们需要创建一个基本的 Three.js 场景,包括场景、摄像机和渲染器。

javascriptCopy Code
// 创建场景 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);

2.2 添加几何体

接下来,我们来添加一个简单的立方体到场景中。

javascriptCopy Code
// 创建立方体几何体 const geometry = new THREE.BoxGeometry(); // 创建材质 const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 创建网格对象 const cube = new THREE.Mesh(geometry, material); // 将立方体添加到场景 scene.add(cube);

2.3 渲染场景

最后,我们需要创建一个动画循环来渲染场景并更新物体的位置。

javascriptCopy Code
function animate() { requestAnimationFrame(animate); // 旋转立方体 cube.rotation.x += 0.01; cube.rotation.y += 0.01; // 渲染场景 renderer.render(scene, camera); } animate();

2.4 完整示例

完整示例如下:

htmlCopy Code
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Three.js 示例</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/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(); 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(); </script> </body> </html>

第三部分:进阶特性

3.1 使用不同的材质

Three.js 提供多种材质类型,如 MeshBasicMaterialMeshPhongMaterialMeshStandardMaterial 等。下面是一个使用 MeshPhongMaterial 的示例:

javascriptCopy Code
const material = new THREE.MeshPhongMaterial({ color: 0x0077ff, shininess: 100 });

3.2 添加光源

光源对场景的渲染效果至关重要。下面是如何添加一个环境光和一个点光源的示例:

javascriptCopy Code
// 添加环境光 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);

3.3 加载纹理

你可以使用 THREE.TextureLoader 加载纹理来为材质添加更多细节。以下是一个加载纹理的示例:

javascriptCopy Code
const textureLoader = new THREE.TextureLoader(); const texture = textureLoader.load('path/to/your/texture.jpg'); const material = new THREE.MeshBasicMaterial({ map: texture });

3.4 使用模型

Three.js 支持多种 3D 模型格式,如 OBJ、FBX 和 GLTF。加载这些模型可以使用 THREE.GLTFLoader。以下是加载 GLTF 模型的示例:

javascriptCopy Code
const loader = new THREE.GLTFLoader(); loader.load('path/to/model.gltf', (gltf) => { scene.add(gltf.scene); });

3.5 动画

Three.js 支持动画。你可以使用 THREE.AnimationMixer 来为模型添加动画。以下是简化示例:

javascriptCopy Code
const mixer = new THREE.AnimationMixer(gltf.scene); gltf.animations.forEach((clip) => { mixer.clipAction(clip).play(); }); function animate() { requestAnimationFrame(animate); mixer.update(0.01); // 更新动画 renderer.render(scene, camera); }

第四部分:交互性

4.1 鼠标事件

可以通过监听鼠标事件来实现基本的交互。例如,检测鼠标点击并选中模型:

javascriptCopy Code
const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); window.addEventListener('click', (event) => { mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; raycaster.setFromCamera(mouse, camera); const intersects = raycaster.intersectObjects(scene.children); if (intersects.length > 0) { intersects[0].object.material.color.set(0xff0000); // 点击后改变颜色 } });

4.2 键盘事件

可以通过监听键盘事件来实现其他交互,例如控制摄像机的移动:

javascriptCopy Code
window.addEventListener('keydown', (event) => { switch(event.key) { case 'w': camera.position.z -= 0.1; // 向前移动 break; case 's': camera.position.z += 0.1; // 向后移动 break; } });

第五部分:实例分析

5.1 3D 游戏场景

我们可以创建一个简单的 3D 游戏场景,里面有一个移动的角色和一些障碍物。

javascriptCopy Code
// 角色几何体 const playerGeometry = new THREE.BoxGeometry(1, 1, 1); const playerMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); const player = new THREE.Mesh(playerGeometry, playerMaterial); scene.add(player); // 障碍物 const obstacleGeometry = new THREE.BoxGeometry(1, 1, 1); const obstacleMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const obstacle = new THREE.Mesh(obstacleGeometry, obstacleMaterial); obstacle.position.x = 3; scene.add(obstacle); // 游戏循环 function gameLoop() { requestAnimationFrame(gameLoop); player.position.x += 0.01; // 角色移动 if (player.position.x > 5) player.position.x = -5; // 循环 renderer.render(scene, camera); } gameLoop();

5.2 数据可视化

我们可以使用 Three.js 创建简单的数据可视化图表,如柱状图或折线图。

javascriptCopy Code
const data = [5, 10, 15, 20, 25]; data.forEach((value, index) => { const barGeometry = new THREE.BoxGeometry(0.5, value, 0.5); const barMaterial = new THREE.MeshBasicMaterial({ color: 0x0077ff }); const bar = new THREE.Mesh(barGeometry, barMaterial); bar.position.x = index * 0.6 - (data.length * 0.3); // 调整位置 bar.position.y = value / 2; // 高度一半 scene.add(bar); });

5.3 交互式艺术作品

利用 Three.js 的强大功能,可以创建各种交互式艺术作品。比如,通过鼠标移动改变场景中的元素:

javascriptCopy Code
const spheres = []; for (let i = 0; i < 10; i++) { const sphereGeometry = new THREE.SphereGeometry(0.2, 32, 32); const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 }); const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); sphere.position.set(Math.random() * 10 - 5, Math.random() * 10 - 5, Math.random() * 10 - 5); scene.add(sphere); spheres.push(sphere); } window.addEventListener('mousemove', (event) => { const x = (event.clientX / window.innerWidth) * 2 - 1; // 归一化 const y = -(event.clientY / window.innerHeight) * 2 + 1; spheres.forEach(sphere => { sphere.position.x += (Math.random() - 0.5) * 0.1; // 随机移动 sphere.position.y += (Math.random() - 0.5) * 0.1; }); });

结论

通过本指南,希望你对 Three.js 有了更深入的了解。我们从基础知识开始,逐步深入到更复杂的特性和应用场景。Three.js 是一个功能强大的工具,适合各种 3D 项目开发。无论是游戏、数据可视化还是艺术创作,Three.js 都能为你带来无限的可能性。

参考资料

希望你能充分发挥 Three.js 的潜力,创造出令人惊叹的 3D 场景!