Three.js零基础入门学习笔记一:初识Three.js,先从一个立方体开始

  • 原创
  • 作者:程序员三丰
  • 发布时间:2025-09-24 16:06
  • 浏览量:64
本文从零开始认识 three.js ,并从基本三要素开始构建代码进行简单的实践,让我们轻松的进入 three.js 学习之旅!

Three.js 文档:https://threejs.org/

哔哩哔哩配套视频学习教程地址:https://www.bilibili.com/video/BV1HPYQz7Ed2?spm_id_from=333.788.videopod.episodes&vd_source=628c735d0423e2bd1153ac15c47d3d87

为什么要学 three.js

  • 市场需求
    就业机会、薪资更具有优势。

  • 前端发展趋势
    用户交互由 2D 发展为 3D,体验更好。
    常见应用场景如:全景展览,在线选车,智慧城市等。

Three.js 可以在浏览器上渲染 3D场景。

学前基础

需要储备什么知识,才能学习这套课程呢?

  • 基础:一定要有前端编程的基础(HTML + CSS + JavaScript)。
  • 工具:对工程化,模块化,包管理器等工具链有一定的了解。
  • 锦上添花:图形学(没有也没关系,three.js 都进行了一定的封装)。

课程安排

  • 第一阶段:学习 three.js 的核心知识
    学习内容包括:场景、摄像机、渲染器、几何图形、材质、网格、GUI、全景图、光线投射、性能。

  • 第二阶段:学习 three.js 的进阶知识
    学习内容包括:贴图、粗糙度、金属度、物理材质、模型、坐标、光源、阴影、gsap、精灵物体。

  • 第三阶段:学习着色器原理

什么是 three.js

three.js 是一个基于 JavaScript 的 WebGL 引擎,可直接运行 GPU 驱动游戏与图形驱动应用于浏览器。其提供大量特性与 API 以绘制 3D 场景于浏览器。

拓展知识:

  • WebGL:Web 图形库,一组浏览器的 API,可以无需其他插件,可独立渲染 3D 场景。
  • GPU:是计算机的图形处理单元部件,负责在显示器上绘制显示图形。

一句话总结 Three.js、WebGL、GPU 三者的关系就是:Three.js 对 WebGL 代码进行封装,底层依赖 GPU 进行图形绘制

代码环境

基于 vite 前端构建工具和 JavaScript 语法。

在命令行工具中定位到要搭建项目的路径,然后执行下面的命令:

pnpm create vite

执行命令后,根据提示设置项目名称【Project name】,并选择框架模版【vanilla】,开发语言类型选择【JavaScript】,最终会生成一个名称为项目名称的目录,进入该目录,然后执行 pnpm install 安装依赖,再执行 pnpm dev 运行项目,在浏览器通过 http://localhost:5173/ 访问项目。

如果上面搭建项目成功,可以删除掉构搭建项目中默认生成的代码和文件,以一个轻量且干净的最小框架开始后面的 three.js 学习之旅。

建议:

删除 src 目录下的除了 main.js 和 style.css 以外文件,然后删除 main.js 文件内容只保留导入 style.css 即可。

当然你可以根据自己的需求进行处理。

接下来我们就开始进入 three.js 实战学习阶段了。

three.js 三要素

简单了解基础三要素,方便我们后续的代码实践:

  • 场景:放置物体的容器。
  • 摄像机:类似人眼,可调整位置、角度等信息,展示不同的画面。
  • 渲染器:接收场景和摄像机,计算在浏览器上渲染的最终 2D 画面。

实践:制作一个简单的立方体

安装three.js

pnpm add three

引入 three.js,初始化三要素

// file: src/main.js

// 引入 three.js
import * as THREE from 'three';

// 场景,摄像机,渲染器
let scene, camera, renderer;

// 初始化三要素
function init() {
  // 1. 创建场景对象
  scene = new THREE.Scene();

  // 2. 创建摄像机对象
  // 参数1:垂直角度(建议75),视野范围
  // 参数2:宽高比(建议与画布相同宽高),物体绘制比例
  // 参数3:近截面距离摄像机距离
  // 参数4:远截面距离摄像机距离
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  // 移动摄像机 z 轴 5 个单位(默认摄像机和物体的坐标轴的都在原点)
  camera.position.z = 5;

  // 3. 创建渲染器
  renderer = new THREE.WebGLRenderer({
    antialias: true, // 开启抗锯齿 - 优化
  });
  renderer.setSize(window.innerWidth, window.innerHeight); // 设置画布大小
  document.body.append(renderer.domElement); // 添加到DOM显示
  renderer.render(scene, camera); // 传入场景和摄像机,渲染画面
}

// 初始化元素
init();

此时浏览器看到是黑屏效果,可以通过控制台查看 DOM 结构。

绘制立方体

绘制立方体步骤:

  1. 创建图形,宽高深为 1 单位;
  2. 创建材质,颜色为绿色 0x00ff00;
  3. 创建网格物体对象,传入图形和材质;
  4. 把物体对象添加到场景。

注意:

  • 默认物体中心与坐标轴中心点重合,所以摄像机需要位移才能看到物体,也就是摄像机需要拉远一些才能看到物体。
  • 渲染器需要调用 render 才能渲染画面(等待物体添加到场景后,再调用)

继续完善上面的代码绘制立方体:

// file: src/main.js

// 引入 three.js
import * as THREE from 'three';

// 场景,摄像机,渲染器
let scene, camera, renderer;
// 立方体
let cube;

// 初始化三要素
function init() {
  // 1. 创建场景对象
  scene = new THREE.Scene();

  // 2. 创建摄像机对象
  // 参数1:垂直角度(建议75),视野范围
  // 参数2:宽高比(建议与画布相同宽高),物体绘制比例
  // 参数3:近截面距离摄像机距离
  // 参数4:远截面距离摄像机距离
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  // 移动摄像机 z 轴 5 个单位(默认摄像机和物体的坐标轴的都在原点)
  camera.position.z = 5;

  // 3. 创建渲染器
  renderer = new THREE.WebGLRenderer({
    antialias: true, // 开启抗锯齿 - 优化
  });
  renderer.setSize(window.innerWidth, window.innerHeight); // 设置画布大小
  document.body.append(renderer.domElement); // 添加到DOM显示
}

// 创建立方体
function createCube() {
  // 1. 创建图形,宽深高为 1 单位(立体缓冲几何体)
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  // 2. 创建材质,颜色为绿色 0x00ff00 (网格基础材质 - 线面纯颜色描绘表面)
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  // 3. 创建网格物体对象,传入图形和材质(网格物体对象)
  cube = new THREE.Mesh(geometry, material);
  // 4. 把物体加入到场景中
  scene.add(cube);
}

// 初始化元素
init();

// 创建立方体
createCube();

renderer.render(scene, camera); // 传入场景和摄像机,渲染画面

此时浏览器效果如下:

由于我们目前看到的只是正方体的一个面,也就是正视图,所以看起来像是平面效果。如果看到其他面,请继续学习下一章节《轨道控制器》。

添加轨道控制器

轨道控制器:可以使摄像机围绕目标进行轨道运动。

作用:右键拖动,左键旋转,滚轮拉近,拉远摄像机。

使用:

  1. 单独引入 OrbitControls 轨道控制器构造函数;
  2. 创建轨道控制器;
  3. 在渲染循环中更新场景渲染。

继续基于上面的代码使用轨道控制器:

// file: src/main.js

// 引入 three.js
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

// 场景,摄像机,渲染器
let scene, camera, renderer;
// 轨道控制器
let controls;
// 立方体
let cube;

// 初始化三要素
function init() {
  // 1. 创建场景对象
  scene = new THREE.Scene();

  // 2. 创建摄像机对象
  // 参数1:垂直角度(建议75),视野范围
  // 参数2:宽高比(建议与画布相同宽高),物体绘制比例
  // 参数3:近截面距离摄像机距离
  // 参数4:远截面距离摄像机距离
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  // 移动摄像机 z 轴 5 个单位(默认摄像机和物体的坐标轴的都在原点)
  camera.position.z = 5;

  // 3. 创建渲染器
  renderer = new THREE.WebGLRenderer({
    antialias: true, // 开启抗锯齿 - 优化
  });
  renderer.setSize(window.innerWidth, window.innerHeight); // 设置画布大小
  document.body.append(renderer.domElement); // 添加到DOM显示
}

// 创建立方体
function createCube() {
  // 1. 创建图形,宽深高为 1 单位(立体缓冲几何体)
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  // 2. 创建材质,颜色为绿色 0x00ff00 (网格基础材质 - 线面纯颜色描绘表面)
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  // 3. 创建网格物体对象,传入图形和材质(网格物体对象)
  cube = new THREE.Mesh(geometry, material);
  // 4. 把物体加入到场景中
  scene.add(cube);
}

// 创建轨道控制器
function createControls() {
  controls = new OrbitControls(camera, renderer.domElement);
}

/**
 * 渲染循环
 */
function renderLoop() {
  renderer.render(scene, camera);

  // 手动 JS 代码更新过摄像机信息,必须调用轨道控制器 update 方法
  controls.update();

  // 根据当前计算机浏览器刷新帧率(默认 60 次/秒),不断递归调用此函数渲染最新的画面状态
  // 好处:当前页面切换到后台,暂停递归
  requestAnimationFrame(renderLoop);
}

// 初始化元素
init();

// 创建轨道控制器
createControls();

// 创建立方体
createCube();

// 渲染循环
renderLoop();

此时在浏览器中,就可以右键拖动立方体,左键旋转立方体看不同的面,滚轮拉进,拉远摄像机。

添加坐标轴(辅助对象)

给画布添加坐标轴辅助对象,就是在画布中模拟 3 个坐标轴(x,y,z),随时显示和调整,辅助我们开发和调试。

注意:因为浏览器兼容性,线段最大最小宽度只能为1。

加入坐标轴辅助对象后完整的 main.js 的代码如下:

// file: src/main.js

// 引入 three.js
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

// 场景,摄像机,渲染器
let scene, camera, renderer;
// 轨道控制器
let controls;
// 立方体
let cube;

// 初始化三要素
function init() {
  // 1. 创建场景对象
  scene = new THREE.Scene();

  // 2. 创建摄像机对象
  // 参数1:垂直角度(建议75),视野范围
  // 参数2:宽高比(建议与画布相同宽高),物体绘制比例
  // 参数3:近截面距离摄像机距离
  // 参数4:远截面距离摄像机距离
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  // 移动摄像机 z 轴 5 个单位(默认摄像机和物体的坐标轴的都在原点)
  camera.position.z = 5;

  // 3. 创建渲染器
  renderer = new THREE.WebGLRenderer({
    antialias: true, // 开启抗锯齿 - 优化
  });
  renderer.setSize(window.innerWidth, window.innerHeight); // 设置画布大小
  document.body.append(renderer.domElement); // 添加到DOM显示
}

// 创建立方体
function createCube() {
  // 1. 创建图形,宽深高为 1 单位(立体缓冲几何体)
  const geometry = new THREE.BoxGeometry(1, 1, 1);
  // 2. 创建材质,颜色为绿色 0x00ff00 (网格基础材质 - 线面纯颜色描绘表面)
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  // 3. 创建网格物体对象,传入图形和材质(网格物体对象)
  cube = new THREE.Mesh(geometry, material);
  // 4. 把物体加入到场景中
  scene.add(cube);
}

// 创建轨道控制器
function createControls() {
  controls = new OrbitControls(camera, renderer.domElement);
}

/**
 * 渲染循环
 */
function renderLoop() {
  renderer.render(scene, camera);

  // 手动 JS 代码更新过摄像机信息,必须调用轨道控制器 update 方法
  controls.update();

  // 根据当前计算机浏览器刷新帧率(默认 60 次/秒),不断递归调用此函数渲染最新的画面状态
  // 好处:当前页面切换到后台,暂停递归
  requestAnimationFrame(renderLoop);
}

// 添加坐标轴辅助对象
function createHelper() {
  /**
   * 用于简单模拟3个坐标轴的对象.
   * 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
   */
  const axesHelper = new THREE.AxesHelper(5)
  scene.add(axesHelper)
}

// 初始化元素
init();

// 创建轨道控制器
createControls();

// 添加坐标轴
createHelper()

// 创建立方体
createCube();

// 渲染循环
renderLoop();

效果如下:

尾语

至此,我们完成一个简单 three.js 应用,是不是没有想象中那么难,而且平时做多了平面效果,3D 效果还是挺有趣的!

声明:本文为原创文章,51blog.xyz和作者拥有版权,如需转载,请注明来源于51blog.xyz并保留原文链接:https://www.51blog.xyz/article/93.html

文章归档

推荐文章

buildadmin logo
Thinkphp8 Vue3 Element PLus TypeScript Vite Pinia

🔥BuildAdmin是一个永久免费开源,无需授权即可商业使用,且使用了流行技术栈快速创建商业级后台管理系统。

热门标签

PHP ThinkPHP ThinkPHP5.1 Go Mysql Mysql5.7 Redis Linux CentOS7 Git HTML CSS CSS3 Javascript JQuery Vue LayUI VMware Uniapp 微信小程序 docker wiki Confluence7 学习笔记 uView ES6 Ant Design Pro of Vue React ThinkPHP6.0 chrome 扩展 翻译工具 Nuxt SSR 服务端渲染 scrollreveal.js ThinkPHP8.0 Mac webman 跨域CORS vscode GitHub ECharts Canvas vue3 three.js