第 60 期 - Three.js 入门开发全解析
摘要
文章从 Three.js 的介绍开始,讲述开发环境搭建,涵盖重要概念如场景、物体、相机、渲染器等,接着展示第一个场景的创建过程、坐标系统相关知识、物体移动方法,还包括几何体与材质创建物体、动画制作、交互添加、光源种类及环境光阴影效果实现,最后介绍了纹理添加到平面和立方体上
Three.js 介绍
Three.js 是一个开源的应用级 3D JavaScript 库,可让开发者在网页创建 3D 体验,它屏蔽了 WebGL 底层调用细节。
开发环境搭建
- 初始化项目:创建目录后使用
npm init -y
初始化package.json
。 - 安装打包工具:例如使用
npm install --save-dev parcel
安装 Web 应用打包工具 parcel(也可使用其他如 webpack 等)。 - 创建文件:新建
src/index.html
和src/script.js
两个文件。index.html
中设置了基本的网页结构,并且<script>
标签引入script.js
时需加上type="module"
,因为script.js
会使用import
模块化语法。- 在
package.json
中加入"start": "parcel src/index.html"
脚本。
- 引入 Three.js:使用
npm install three
引入 Three.js,在src/script.js
中可通过import * as THREE from "three";console.log(THREE);
验证是否引入成功。
Three.js 重要概念
- scene(场景):像容器,可加入物体(模型、粒子、光源、相机等)。
- objects(物体):种类多样,如原始几何体、导入模型、粒子、光源等。
- camera(相机):理论视角,虽然加入场景但不可见,有透视相机等类型。
- 透视相机构造参数有视野(
fov
)、宽高比(aspect
)、近平面距离(near
)、远平面距离(far
)。
- 透视相机构造参数有视野(
- renderer(渲染器):从相机角度渲染场景,结果绘制到
canvas
中。
第一个 Three.js 场景
- 创建渲染器并设置尺寸添加到
body
中:
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.pixelRatio = window.devicePixelRatio;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.append(renderer.domElement);
- 创建场景:
const scene = new THREE.Scene();
- 创建相机并设置参数:
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
- 创建物体(坐标辅助线)并添加到场景:
const axis = new THREE.AxesHelper(5);
scene.add(axis);
- 渲染场景:
renderer.render(scene, camera);
但初始时屏幕黑暗,原因与坐标系统有关。
坐标系统
Three.js 使用右手坐标系,默认物体和透视相机在原点(0,0,0)
,距离为0
且相机看向原点,所以不渲染内容。解决办法是移动相机或物体,如设置camera.position.set(5, 5, 10);
或单独设置坐标,且设置camera.lookAt(0, 0, 0);
就能看到坐标辅助线。
Geometry 和 Material
创建立方体需要创建Mesh
对象(几何形状和材质的组合)。
- 创建立方几何体:
const geometry = new THREE.BoxGeometry(4, 4, 4);
- 创建红色材质:
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
- 组合为
Mesh
对象并添加到场景:
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
立方体动画
- 设置初始旋转角度:
cube.rotation.y = Math.PI / 4;
- 通过
requestAnimationFrame
实现动画:
function animate() {
requestAnimationFrame(animate);
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
- 动画优化:使用
three.js
中内置的Clock
保证两秒自转一圈。
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const elapsedTime = clock.getElapsedTime();
cube.rotation.y = elapsedTime * Math.PI;
renderer.render(scene, camera);
}
添加交互
添加OrbitControls
控制器实现用户与场景交互。
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
const controls = new OrbitControls(camera, renderer.domElement);
controls.update();
交互添加光源
Three.js 中有环境光源、方向光源和点光源三种重要光源。
- 环境光(Ambient Light):均匀照亮场景所有物体,不考虑位置和方向。
- 方向光(Directional Light):平行光源,有确定方向和强度,类似太阳光。
- 点光源(Point Light):位于特定位置,向所有方向发射光线,类似灯泡。 添加环境光和方向光示例:
const material = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(10, 0, 10);
scene.add(directionalLight);
环境光阴影
- 使渲染器能渲染阴影:
renderer.shadowMap.enabled = true;
- 方向光投射阴影:
directionalLight.castShadow = true;
- 立方体会产生阴影:
cube.castShadow = true;
- 创建能接受阴影的平面并设置:
const planeGeometry = new THREE.PlaneGeometry(20, 20);
const planeMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff });
const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.rotation.x = -0.5 * Math.PI;
planeMesh.position.set(0, -3, 0);
planeMesh.receiveShadow = true;
scene.add(planeMesh);
- 添加方向光辅助线:
const directionalLightHelper = new THREE.DirectionalLightHelper(
directionalLight
);
scene.add(directionalLightHelper);
纹理
- 地板纹理:
- 引入图片。
- 初始化纹理加载器。
- 给地板加载纹理。
import floor from "./images/floor_wood.jpeg";
const textloader = new THREE.TextureLoader();
const planeMaterial = new THREE.MeshStandardMaterial({
map: textloader.load(floor),
});
- 立方体纹理:为不同面设置不同纹理,通过在构造
Mesh
对象时传入6
个MeshBasicMaterial
对象的数组,按特定顺序设置各面纹理。
扩展阅读
Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有