【three.js系列二】入门教程——几何体

前言

之前更完一篇,忙完其他事就给忘了这茬了。看到小伙伴在催更,二话没说赶紧更新一篇。

在开始之前我们先简短介绍下Three.jsWebGLCanvas三者是什么及它们之间的关系:

什么是 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);

【three.js系列二】入门教程——几何体

2.创建3D场景 Scene

你可以把三维场景Scene (opens new window)对象理解为虚拟的3D场景,用来表示模拟生活中的真实三维场景,或者说三维世界。

// 创建3D场景对象Scene
const scene = new THREE.Scene();

创建完场景后,需要把一切逐个加入到场景里,就像舞台上需要载入镜头、演员、布景等。需要载入的内容有:

  1. 相机:Camera
  2. 物体形状:几何体Geometry
  3. 物体外观:材质Material
  4. 物体:网格模型Mesh
  5. 模型位置.position

3. 创建相机 Camera

相机这块对于新手来说比较复杂、难以理解,需要较好的3D空间想象力。

Three.js 中的相机主要有以下几种:

  • 透视相机(PerspectiveCamera) :这是最常用的相机类型,它模拟了人眼的视角,具有透视效果。
  • 正交相机(OrthographicCamera) :这种相机不会产生透视效果,而是以平行投影的方式来渲染场景。
  • 立体相机(StereoCamera) :这种相机用于创建立体效果,它包含两个相机,分别模拟左右眼的视角。
  • 立方体相机(CubeCamera) :这种相机用于创建六个面的立方体贴图,可以用于环境映射。

这里以透视相机(PerspectiveCamera)为例,设置相机参数及拍摄视角,并添加到场景Scene中:

【three.js系列二】入门教程——几何体

透视投影相机PerspectiveCamera:视锥体

透视相机是 Three.js 中最常用的相机类型,它模拟了人眼的视角,具有透视效果。透视相机的参数包括:

  • 焦距(fov) :焦距决定了相机的视野范围,焦距越大,视野范围越小。
  • 纵横比(aspect) :纵横比决定了相机的画面比例,通常设置为与渲染目标的比例一致。
  • 近平面(near) :近平面决定了相机能够渲染的最近距离,近平面之外的物体将不会被渲染。
  • 远平面(far) :远平面决定了相机能够渲染的最远距离,远平面之内的物体将不会被渲染。

透视投影相机的四个参数fov, aspect, near, far构成一个四棱台3D空间,被称为视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示在Canvas画布上。

【three.js系列二】入门教程——几何体

// 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种格式:

  1. ‘red’
  2. 0xff0000
  3. #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/

【three.js系列二】入门教程——几何体

完整代码

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唯心

(0)
上一篇 2024年3月2日 下午4:42
下一篇 2024年3月2日 下午4:52

相关推荐

发表回复

登录后才能评论