gitee 地址

gitee地址: gittee地址

本篇目标

  • 搭建开发环境
  • 安装three.js
  • 了解three.js的基本内容
  • 搭建一个3d立方体并渲染到页面上

    搭建

    全程采用vite用作本地服务启动工具。
    创建一个文件夹,在终端中打开文件夹并输入以下内容
    1
    2
    3
    4
    5
    6
    7
    8

    // pnpm
    pnpm create vite
    // npm
    npm create vite@latest
    // yarn
    yarn create vite

    删除多余文件,并删除main.js中的内容。文件夹结构如下图:
    无标题.png

安装 three.js

1
2
3
4
5
6
7
8
9
// pnpm 
pnpm i three -s
// npm
npm i three -s
// yarn
yarn three

//
<script src="https://threejs.org/build/three.js"></script>

了解three.js

three.js官网地址:官网
在使用的过程中,我们需要用到three.js的三大组件,分别是场景(Scene)、相机(Camera)、渲染器(Renderer)

场景 ( Sene )

场景是所有物体的容器。我们需要将所渲染的内容放入场景中。

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

相机( Camera )

相机决定了场景中那个角度的景色会显示出来。相机就像人的眼睛一样,人站在不同位置,抬头或者低都能够看到不同的景色。场景只有一种,但是相机却有很多种只要设置不同的相机参数,就能够让相机产生不一样的效果。

StereoCamera 立体相机
PerspectiveCamera 透视相机
OrthographicCamera 正交相机
CubeCamera 立方相机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 创建相机
/*
PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )
fov — 摄像机视锥体垂直视野角度
aspect — 摄像机视锥体长宽比
near — 摄像机视锥体近端面
far — 摄像机视锥体远端面
*/

// 透视相机
const camera = new THREE.PerspectiveCamera(
75, // 摄像机视锥体垂直视野角度,从视图的底部到顶部,以角度来表示。默认值是50。
window.innerWidth / window.innerHeight, // 摄像机视锥体的长宽比,通常是使用画布的宽/画布的高。默认值是1(正方形画布)。
0.1, // 摄像机的近端面,默认值是0.1。
1000 // 摄像机的远端面,默认值 2000
)

渲染器 renderer

渲染器决定了渲染的结果应该画在页面的什么元素上面,并且以怎样的方式来绘制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

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

// 设置大小
renderer.setSize(
window.innerWidth, // 宽度
window.innerHeight // 高度
);
//挂载到页面
document.body.appendChild(renderer.domElement)


// 渲染
function animate() {

//scene:前面定义的场景,camera:前面定义的相机
//renderTarget:渲染的目标默认是是渲染到前面定义的render变量中
//forceClear:每次绘制之前都将画布的内容给清除,即使自动清除标志autoClear为false,也会清除
renderer.render(scene, camera)

// 使用 requestAnimationFrame 执行动画
requestAnimationFrame(animate)
}

// 渲染
animate()

材质

1
2
// 添加材质
const material = new THREE.MeshBasicMaterial({ color: 0xffff0000 });

材质Api列表

MeshNormalMaterial 法线网格材质
MeshBasicMaterial 基础网格材质
MeshLambertMaterial Lambert网格材质
MeshPhongMaterial Phong网格材质
MeshToonMaterial 卡通网格材质

three.js 渲染步骤流程

  • 生成几何体 -> 生成材质 -> 混合生成模型 -> 添加到场景中
  • 场景操作 -> 生成场景(配置参数…) -> 模型导入场景
  • 相机操作 -> 生成相机 -> 添加控制器(控制相机)
  • 渲染器操作 -> 生成渲染器 -> 场景和相机添加到渲染器中 -> 建立和canvas 关联
  • 更新模块(动画模块) -> 动画的连续 ,相机 ,场景的更新控制

    实现一个简单的立方体

    main.js中引入three.js
    1
    import * as THREE from "three"

    创建一个场景

    1
    2
    3
    4
    //创建场景

    const scene = new THREE.Scene()

    创建相机

    这里采用 透视相机
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    // 创建相机

    /*
    PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )
    fov — 摄像机视锥体垂直视野角度
    aspect — 摄像机视锥体长宽比
    near — 摄像机视锥体近端面
    far — 摄像机视锥体远端面
    */

    // 透视相机
    const camera = new THREE.PerspectiveCamera(
    75, // 摄像机视锥体垂直视野角度,从视图的底部到顶部,以角度来表示。默认值是50。
    window.innerWidth / window.innerHeight, // 摄像机视锥体的长宽比,通常是使用画布的宽/画布的高。默认值是1(正方形画布)。
    0.1, // 摄像机的近端面,默认值是0.1。
    1000 // 摄像机的远端面,默认值 2000
    )

    创建渲染器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 创建渲染器
    const renderer = new THREE.WebGLRenderer();

    // 设置大小
    renderer.setSize(
        1000, // 宽度
        500 // 高度
    );

    //挂载到页面
    document.body.appendChild(renderer.domElement)

    添加立方体

    1
    2
    3
    4
    5
    6
    7
    8
    // 添加物体

    /*
        width:立方体x轴的长度,
        height:立方体y轴的长度,
        depth:立方体z轴的长度也是深度
    */
    let geometry = new THREE.BoxGeometry(10, 10, 10);

常见几何体

BoxGeometry 立体矩形
CircleGeometry
CylinderGeometry 圆柱
ConeGeometry 圆锥
DodecahedronGeometry 十二面几何体(球)
PlaneGeometry 平面几何体 (重要)生成底面
RingGeometry 平面圆环几何体
TorusGeometry 圆环几何体

添加材质

1
2
// 添加材质
const material = new THREE.MeshBasicMaterial({ color: 0xffff0000 });

添加网格

1
2
3
4
// 添加网格
const cube = new THREE.Mesh( geometry, material );
// 将网格添加到场景中
scene.add( cube );

设置相机位置

因为相机的默认位置是(0, 0, 0),所以需要修改相机的位置,不然看不到我们创建的立方体

1
2
// 设置相机位置
camera.position.z = 50;

渲染到页面上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 渲染
function animate() {

    // 使用 requestAnimationFrame 执行动画
    requestAnimationFrame(animate)


    //scene:前面定义的场景,camera:前面定义的相机
    //renderTarget:渲染的目标默认是是渲染到前面定义的render变量中
    //forceClear:每次绘制之前都将画布的内容给清除,即使自动清除标志autoClear为false,也会清除
    renderer.render(scene, camera)
}    


// 渲染
animate()

此时此刻,我们的页面上就会出现一个红色的盒子
image.png
我们看到的是一个平面的,我们修改渲染函数,让他动起来并且看到他的完整样子。将渲染函数修改成如下样子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 渲染
function animate() {


    // 使用 requestAnimationFrame 执行动画
    requestAnimationFrame(animate)


    // 修改其旋转的度数,让其每次渲染增加0.01的弧段进行渲染
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;


    //scene:前面定义的场景,camera:前面定义的相机
    //renderTarget:渲染的目标默认是是渲染到前面定义的render变量中
    //forceClear:每次绘制之前都将画布的内容给清除,即使自动清除标志autoClear为false,也会清除
    renderer.render(scene, camera)
}

requestAnimationFrame是原生自带的实现动画用的,具体的可以看MDN

现在我们看到的就是一个会转的立方体
image.png

让我们来完善一下

  • 把黑色背景给他改个颜色
  • 并添加一个x,y,z坐标线
  • 将6个面的颜色改成不一样的

修改场景背景颜色

1
2
// 修改场景背景颜色
scene.background = new THREE.Color(0xffffcc99)

image.png
添加x,y,z坐标线

1
2
3
// 添加 三色坐标轴
const axesHelper = new THREE.AxesHelper(20)
scene.add( axesHelper )

image.png

修改每个面的颜色。
我们将添加材质那一句修改为如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 添加材质
// const material = new THREE.MeshBasicMaterial({ color: 0xffff0000 });

// 添加材质
const materials = []


for(let i = 0; i < 6; i++){
    materials.push(new THREE.MeshBasicMaterial({ color: Math.random() * 0x00ff0000 }))
}

// 添加网格
const cube = new THREE.Mesh( geometry, materials );
scene.add( cube );

image.png

一个能够自己旋转的立方体我们就做好了。

下篇文章将使用controls让我们可以通过鼠标、键盘控制我们的盒子模型。