前言
之前更完一篇,忙完其他事就给忘了这茬了。看到小伙伴在催更,二话没说赶紧更新一篇。
在开始之前我们先简短介绍下Three.js
、WebGL
、Canvas
三者是什么及它们之间的关系:
什么是 Canvas?
Canvas 是 HTML5 中新增的元素,用于绘制图形和图像。它提供了一个 2D 绘图上下文,可以用来绘制各种形状、线条、文字和图像。已经被广泛应用于游戏开发、图像编辑、数据可视化、动画制作等领域。
什么是 WebGL?
WebGL(Web 图形库)是一种 JavaScript API,用于在任何兼容的 Web 浏览器中呈现交互式 3D 和 2D 图形,而无需使用插件。WebGL 通过引入一个与 OpenGL ES 2.0 紧密相符合的 API,可以在 HTML5 <canvas>
元素中使用(简介引自 MDN)。
以我的理解,WebGL 给我们提供了一系列的图形接口,能够让我们通过 JavaScript 去使用 GPU 来进行浏览器图形渲染的工具。
什么是 Three.js?
Three.js 在 WebGL 的 API 接口基础上,又进行的一层封装。Three.js 以简单、直观的方式封装了 3D 图形编程中常用的对象。Three.js 在开发中使用了很多图形引擎的高级技巧,极大地提高了性能。
创建
创建一个几何体需要6个步骤:
1. 初始设置
2. 创建场景
3. 创建相机
4. 创建立方体及外观
5. 创建渲染器
6. 渲染场景
以下内容基于vue项目开发, vue项目搭建不做阐述:
1. 初始设置
index.html
中加入canvas
标签,canvas
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
/>
<title>My first three.js app</title>
</head>
<body>
<canvas class="webgl"></canvas>
<script type="module" src="./main.js"></script>
</body>
</html>
main.js
引入three.js
,可以打印THREE
查看默认的属性和方法
import * as THREE from "three";
console.log(THREE);
2.创建3D场景 Scene
你可以把三维场景Scene (opens new window)对象理解为虚拟的3D场景,用来表示模拟生活中的真实三维场景,或者说三维世界。
// 创建3D场景对象Scene
const scene = new THREE.Scene();
创建完场景后,需要把一切逐个加入到场景里,就像舞台上需要载入镜头、演员、布景等。需要载入的内容有:
- 相机:Camera
- 物体形状:几何体Geometry
- 物体外观:材质Material
- 物体:网格模型Mesh
- 模型位置.position
3. 创建相机 Camera
相机这块对于新手来说比较复杂、难以理解,需要较好的3D空间想象力。
Three.js 中的相机主要有以下几种:
- 透视相机(PerspectiveCamera) :这是最常用的相机类型,它模拟了人眼的视角,具有透视效果。
- 正交相机(OrthographicCamera) :这种相机不会产生透视效果,而是以平行投影的方式来渲染场景。
- 立体相机(StereoCamera) :这种相机用于创建立体效果,它包含两个相机,分别模拟左右眼的视角。
- 立方体相机(CubeCamera) :这种相机用于创建六个面的立方体贴图,可以用于环境映射。
这里以透视相机(PerspectiveCamera)为例,设置相机参数及拍摄视角,并添加到场景
Scene
中:
透视投影相机
PerspectiveCamera
:视锥体
透视相机是 Three.js 中最常用的相机类型,它模拟了人眼的视角,具有透视效果。透视相机的参数包括:
- 焦距(fov) :焦距决定了相机的视野范围,焦距越大,视野范围越小。
- 纵横比(aspect) :纵横比决定了相机的画面比例,通常设置为与渲染目标的比例一致。
- 近平面(near) :近平面决定了相机能够渲染的最近距离,近平面之外的物体将不会被渲染。
- 远平面(far) :远平面决定了相机能够渲染的最远距离,远平面之内的物体将不会被渲染。
透视投影相机的四个参数fov, aspect, near, far
构成一个四棱台3D空间,被称为视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示在Canvas画布上。
// Camera
// 设置画布大小
const sizes = {
width: 800,
height: 600,
};
// 75:视场角度, sizes.width / sizes.height :Canvas画布宽高比, 1:近裁截面, 3000:远裁截面
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 1, 3000);
camera.position.z = 5; // z视角
scene.add(camera); // 添加到场景
4. 创建立方体及外观
4.1 物体形状:几何体Geometry
Three.js提供了各种各样的几何体API,用来表示三维物体的几何形状。
文档搜索关键词geometry
你可以看到threejs提供各种几何体相关API,具体使用方法,也可以参考文档。
//创建一个长方体几何对象Geometry
const geometry = new THREE.BoxGeometry(1, 1, 1);
4.2 物体外观:材质Material
如果你想定义物体的外观效果,比如颜色,就需要通过材质Material
相关的API实现。
threejs不同材质渲染效果不同,下面就以threejs最简单的网格基础材质MeshBasicMaterial (opens new window)为例给大家实现一个红色材质效果。
//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial({
color: 0xff0000,//0xff0000设置材质颜色为红色
});
颜色设置可以有3种格式:
- ‘red’
- 0xff0000
- #ff0000
4.3 物体:网格模型Mesh
实际生活中有各种各样的物体,在threejs中可以通过网格模型Mesh (opens new window)表示一个虚拟的物体,比如一个箱子、一个鼠标。
// 两个参数分别为几何体geometry、材质material
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
4.3 模型位置.position
实际生活中,一个物体往往是有位置的,对于threejs而言也是一样的,你可以通过位置属性.position
定义网格模型Mesh
在三维场景Scene
中的位置。
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
//设置网格模型在三维空间中的位置坐标,默认是坐标原点
mesh.position.set(1, 1, 1);
4.3 添加到场景 .add()
scene.add(mesh);
5. 创建渲染器
WebGL渲染器WebGLRenderer (opens new window)执行渲染方法.render()
就可以生成一个Canvas画布(照片),并把三维场景呈现在canvas画布上面,你可以把.render()
理解为相机的拍照动作“咔”。
5.1 WebGL渲染器WebGLRenderer
通过WebGL渲染器WebGLRenderer (opens new window)可以实例化一个WebGL渲染器对象。
// 获取画布DOM,创建渲染器对象
// canvas.webgl是指 <canvas class="webgl"></canvas>
const canvas = document.querySelector("canvas.webgl");
const renderer = new THREE.WebGLRenderer({ canvas: canvas });
5.2 设置Canvas画布尺寸.setSize()
renderer.setSize(sizes.width, sizes.height); //设置three.js渲染区域的尺寸(像素px)
6. 渲染场景和相机
renderer.render(scene, camera);
此时可以打开浏览器 http://localhost:5173/
预览效果,会发现一个红色的立方体
7. 如果想加上一点小动画
通过HTML5的请求动画帧函数: window.requestAnimationFrame()
, 辅助实现WebGPU的动画效果。实现函数的周期性执行,默认每秒钟执行60次,也可能低于60次。
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
完成,打开浏览器http://localhost:5173/
可看到一个旋转的红色立方体
http://localhost:5173/
完整代码
import * as THREE from "three";
console.log(THREE);
// 场景 scene
const scene = new THREE.Scene();
// object
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(1, 1, 1);
scene.add(mesh);
const sizes = {
width: 800,
height: 600,
};
// Camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height,1,3000);
camera.position.z = 5;
scene.add(camera);
const canvas = document.querySelector("canvas.webgl");
const renderer = new THREE.WebGLRenderer({ canvas: canvas });
renderer.setSize(sizes.width, sizes.height);
renderer.render(scene, camera);
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
原文链接:https://juejin.cn/post/7341239784734048297 作者:smile唯心