ThreeJS入门

1,731 阅读4分钟

这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战

Threejs 该项目的是使用默认的WebGL渲染器创建一个易于使用,轻量级的3D库。该库还在示例中提供了Canvas 2D,SVG和CSS3D渲染器

为何要使用ThreeJS?

WebGL原生的api是一种非常低级的接口,而且还需要一些数学和图形学的相关技术。对于没有相关基础的人来说,入门真的很难,Three.js将入门的门槛降低了整整的一大截,对WebGL进行封装,简化我们创建三维动画场景的过程。

优点

Three.js作为WebGL框架中的佼佼者,由于它的易用性和扩展性,使得它能够满足大部分的开发需求。

  1. Three.js掩盖了3D渲染的细节:Three.js将WebGL原生API的细节抽象化,将3D场景拆解为网格、材质和光源(即它内置了图形编程常用的一些对象种类)。
  2. 面向对象:开发者可以使用上层的JavaScript对象,而不是仅仅调用JavaScript函数。
  3. 功能非常丰富:Three.js除了封装了WebGL原始API之外,Three.js还包含了许多实用的内置对象,可以方便地应用于游戏开发、动画制作、幻灯片制作、髙分辨率模型和一些特殊的视觉效果制作。
  4. 速度很快:Three.js采用了3D图形最佳实践来保证在不失可用性的前提下,保持极高的性能。 支持交互:WebGL本身并不提供拾取(picking)功能(即是否知道鼠标正处于某个物体上)。而Three.js则固化了拾取支持,这就使得你可以轻松为你的应用添加交互功能。
  5. 包含数学库:Three.js拥有一个强大易用的数学库,你可以在其中进行矩阵、投影和矢量运算。
  6. 内置文件格式支持:你可以使用流行的3D建模软件导出文本格式的文件,然后使用Three.js加载;也可以使用Three.js自己的JSON格式或二进制格式。
  7. 扩展性很强:为Three.js添加新的特性或进行自定义优化是很容易的事情。如果你需要某个特殊的数据结构,那么只需要封装到Three.js即可。

缺点

  1. 官网文档非常粗糙,对于新手极度不友好。
  2. 国内的相关资源匮乏。
  3. Three.js所有的资料都是以英文格式存在,对国内的朋友来说又提高了门槛。
  4. Three.js不是游戏引擎,一些游戏相关的功能没有封装在里面,如果需要相关的功能需要进行二次开发。

案例

接下来看一个入门案例

效果图:

2021-08-08 23.34.25.gif

使用ThreeJS想要创建内容,必要要有基础三要素:渲染器、相机、场景

相机获取到场景内显示的内容,然后再通过渲染器渲染到画布上面

创建渲染器:

//初始化渲染器
const initRenderer = () => {
  renderer = new THREE.WebGLRenderer(); //实例化渲染器
  renderer.setSize(window.innerWidth, window.innerHeight); //设置宽和高
  document.body.appendChild(renderer.domElement); //添加到dom
};

创建相机:


//初始化相机
const initCamera = () => {
  camera = new THREE.PerspectiveCamera(
    45,
    window.innerWidth / window.innerHeight,
    0.1,
    200
  ); //实例化相机
  camera.position.set(0, 0, 15);
};

创建场景:

//初始化场景
const initScene = () => {
  scene = new THREE.Scene(); //实例化场景
};

基础三要素准备完成,这个时候还不能展示内容,因为场景内还没有内容,渲染出来也是什么都没有,接下来需要往场景里面添加内容

//创建模型
const initMesh = () => {
  geometry = new THREE.BoxGeometry(2, 2, 2); //创建几何体
  material = new THREE.MeshNormalMaterial(); //创建材质

  mesh = new THREE.Mesh(geometry, material); //创建网格
  scene.add(mesh); //将网格添加到场景
};

此时通过渲染器渲染

renderer.render(scene, camera); //渲染界面

此时页面已经展示

image-20210808235215726.png

并不是我们想要的效果,因为还没动起来

接下来让其动起来


//运行动画
const animate = () => {
  requestAnimationFrame(animate); //循环调用函数

  mesh.rotation.x += 0.01; //每帧网格模型的沿x轴旋转0.01弧度
  mesh.rotation.y += 0.02; //每帧网格模型的沿y轴旋转0.02弧度

  renderer.render(scene, camera); //渲染界面
};

此时我们只需要将这些在页面加载完成之后调用,便可以如开始那般动起来

// 页面加载完成是调用
window.addEventListener("load", () => {
  initRenderer();
  initScene();
  initCamera();
  initMesh();
  animate();
});