Skip to content

第一个 3D 案例

三维场景 Scene

可以将三维场景 Scene 对象理解为虚拟的 3D 场景, 用来表示生活中的真实三维场景, 或者说是三维世界.

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

物体形状: 几何体 Geometry

three.js 提供了各种各样的几何体 API,用来表示三维物体的几何形状.

js
// 创建一个长方体集合对象,长宽高都为100
const geometry = new THREE.BoxGeometry(100, 100, 100);

物体外观: 材质 Material

如果你想定义物体的外观效果, 比如颜色, 就需要通过材质 Material 相关的 API 来实现.

threejs 中不同的材质渲染效果也是不同的, 下面以最简单的网格基础材质 MeshBasicMaterial 实现一个红色材质

js
//创建一个材质对象Material
const material = new THREE.MeshBasicMaterial({
  color: 0xff0000, //0xff0000设置材质颜色为红色
});

物体: 网格模型 Mesh

实际生活中有各种各样的物体, 在 threejs 中可以通过网格模型 Mesh 来表示一个虚拟的物体, 比如一个箱子

js
// 两个参数分别为几何体与材质
const mesh = new THREE.Mesh(geometry, material);

设置模型的位置

实际生活中, 一个物体往往是有位置的, 对于 threejs 而言也是一样的, 可以通过"网格模型.position"定义网格模型 Mesh 在三维场景(Scene)中的位置

js
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
//设置网格模型在三维空间中的位置坐标,默认是坐标原点(0,0,0)
mesh.position.set(0, 10, 0);

.add()方法

现在已经在 threejs 中创建了一个表示虚拟物体对象 Mesh,需要通过 add 方法将网格模型添加到三维场景中.

js
scene.add(mesh);

相机: Camera

在 threejs 中如果想把三维场景 Scene 渲染到 web 网页上, 还需要定义一个虚拟相机 camera, 就像生活中如果想获得一张照片, 那就需要一台用来拍照的相机

透视投影相机 PerspectiveCamera

threejs 提供了正投影相机 OrthographicCamera (opens new window)和透视投影相机 PerspectiveCamera

透视相机 PerspectiveCamera 本质上就是在模拟人眼, 观察这个世界的规律.

js
// 实例化一个透视摄影相机对象
const camera = new THREE.PerspectiveCamera();

相机位置

生活中用相机拍照, 你相机的位置不同, 拍照的结果也不同, threejs 中的虚拟相机也同样如此.

比如有一间房子, 你拿着相机在房子里面,看到的是房间内部, 站在房子外面看到的就是房子外面的效果.

相机对象 Camera 具有位置 position 属性, 通过位置属性 position 可以设置相机的位置

js
// 相机在threejs三维坐标系的位置
// 根据需要设置相机位置的具体值
camera.position.set(200, 200, 200);

相机观察目标 .lookAt()

你用相机拍照你需要控制相机的拍照目标, 具体说相机镜头对准的是哪个物体或说哪个坐标, 对于 threejs 相机而言, 就是设置.lookAt()方法的参数,指定一个 3D 坐标.

js
// 设置相机的视线, 参数是观察目标点的坐标
camera.lookAt(0, 0, 0); // 坐标原点
camera.lookAt(0, 20, 0); // y轴上一点
camera.lookAt(mesh.position); // 指向网格模型

定义相机渲染输出的画布尺寸

在生活中相机拍照的照片是有大小的, 对于 threejs 而言也一样, 需要定义相机在网页上输出的 Canvas 画布尺寸, 大小可以根据需要定义

Canvas 画布: 把 threejs 虚拟相机渲染三维场景在浏览器网页上呈现的结果称为 Canvas 画布

js
// 定义相机输出画布的尺寸(单位:像素px)
const width = 800; //宽度
const height = 500; //高度

透视投影相机 PerspectiveCamera:视锥体

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

js
// width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
const width = 800; //宽度
const height = 500; //高度
// 30:视场角度, width / height:Canvas画布宽高比, 1:近裁截面, 3000:远裁截面
const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);

PerspectiveCamera 参数

js
PerspectiveCamera(fov, aspect, near, far);
参数含义默认值
fov相机视锥体竖直方向视野角度50
aspect相机视锥体水平方向和竖直方向长度比,一般设置为 Canvas 画布宽高比 width / height1
near相机视锥体近裁截面相对相机距离0.1
far相机视锥体远裁截面相对相机距离,far-near 构成了视锥体高度方向2000

渲染器: renderer

生活中有了景物和相机, 那么如果想要获取一张照片, 就需要你拿着相机按一下, 咔, 完成拍照, 对于 threejs 而言,如果完成"咔"这个拍照动作, 就需要一个新的对象, 也就是 WebGL 渲染器 WebGLRenderer

WebGL 渲染器 WebGLRenderer

通过 WebGL 渲染器 WebGLRenderer 可以实例化一个 WebGL 渲染器对象

js
// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();

设置 Canvas 画布尺寸 .setSize()

js
// 定义threejs输出画布的尺寸(单位:像素px)
const width = 800; //宽度
const height = 500; //高度
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)

渲染器渲染方法.render()

渲染器 WebGLRenderer 执行渲染方法.render()后, 就可以生成一个 Canvas 画布(照片),并将三维场景 Scene 呈现在 Canvas 画布上面, 可以将 render()方法理解为相机的拍照动作, "咔".

js
renderer.render(scene, camera); // 执行渲染操作

渲染器 Canvas 画布属性.domElement

渲染器 WebGLRenderer 通过属性.domElement 可以获得渲染方法.render()生成的 Canvas 画布, domElement 本质上就是一个 HTML 元素: Canvas 画布

js
document.body.appendClild(renderer.domElement);

将生成的 Canvas 画布插入到任意 HTML 元素中

html
<div class="box"></div>
js
document.querySelector('.box').appendChild(renderer.domElement);

完整代码

index.html

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div class="box"></div>

    <script type="importmap">
      {
        "imports": {
          "three": "../build/three.module.js",
          "three/addons/": "../examples/jsm/"
        }
      }
    </script>

    <script src="./index.js" type="module"></script>
  </body>
</html>

<style>
  .box {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
  }
</style>

index.js

js
import * as THREE from 'three';

// 创建场景
const scene = new THREE.Scene();

// 创建一个几何体
const geometry = new THREE.BoxGeometry(10, 10, 10); // 长宽高都是100

// 为物体添加材质
const material = new THREE.MeshBasicMaterial({
  color: 0xff0000,
});

// 根据几何体与材质创建一个网格模型
const mesh = new THREE.Mesh(geometry, material);
mesh.position(0, 20, 0);

// 将物体添加到场景中
scene.add(mesh);

// 创建相机
const width = 800;
const height = 500;
const camera = new THREE.PerspectiveCamera(30, width / height, 0.1, 3000);

// 设置相机的位置
camera.position.set(200, 200, 200);

// 设置相机的视线, 参数是观察目标点的坐标
// camera.lookAt(0, 0, 0); // 坐标原点
// camera.lookAt(0, 20, 0); // y轴上一点
camera.lookAt(mesh.position); // 指向网格模型

// 创建一个WebGL渲染器
const renderer = new THREE.WebGLRenderer();

// 设置canvas画布的宽度和高度
renderer.setSize(width, height);

// 执行渲染
renderer.render(scene, camera);

// 将渲染后得到的canvas添加到网页中
// document.body.appendChild(renderer.domElement);
document.querySelector('.box').appendChild(renderer.domElement);

上次更新于: