系列介绍
在 webgl 没出现之前,如果我们要在页面展示 3D 动画的效果,我们需要借助一些浏览器的插件进行实现。因此在 2011 年, webgl 诞生了,这套应用与 3D 应用的 API 能够让开发者使用 JS 语言与 GPU 进行通信,从而实现各式各样的 3D 效果。而本系列将借由 Three.js 对 webgl 进行介绍说明。
Three.js
Three.js 是一个基于 webgl 开发的开源库,它就像 echarts 建立于 canvas 上,通过 Three.js 我们可以不用直接接触最底层的内容,包括: 着色器、缓冲区、矩阵变换的内容,从而大大减小入门的难度。但本系列在通过介绍 Three.js 的过程中,也会插入一些 webgl 的基础知识,从而帮助你更好的理解。
本文的参考资料
Three.js
Three.js中文网 Three.js -- JavaScript 3D Library www.webgl3d.cn/
webgl
WebGL 理论基础 WebGL:web 中的 2D 的 3D 图形 - Web API | MDN Three.js中文网
Three.js 的三大基础概念
Three.js 的运行机制
在 Three.js 中,要实现渲染一个3D的物体,首先我们需要一个 虚拟的场景 ,然后通过将我们需要展示3D物体添加到场景中,于是便有了一个"虚拟的世界",而想要看这个虚拟的世界,便需要通过 摄像机 去拍摄,最后通过 渲染器 解析当前摄像机看到的内容,从而展示给用户。而这也使得摄像头被移动之后,仍需要重新进行渲染才可以展示出内容。
大白话
你可以理解为你在给一辆跑车拍一张海报,此时首先需要 一辆车(物体) 与 一个展台(场景) ,然后我们拿着摄像机,选好我们的站位,瞄准我们需要拍摄的车,此时 摄像机显示屏(摄像机) 就展示我们能看到的东西。最后我们需要通 按下快门键(渲染器)**,才能看到我们的海报。
场景
场景 Scene
场景的创建在 Three.js 中也十分的简单,我们可以通过 Three.Scene() 进行创建,并且将他赋值给一个变量,于是我们便可以通过 add 方法将物体放置到场景中。
js
// 你可以通过 Scene 方法创建一个场景
const Scene = new THREE.Scene()
物体
物体,是我们在开发3D场景中极为重要的内容,毕竟场景终究只是一个空壳,具体的样子和内容还需要通过物体来展示,因此物体和场景可以放在一起进行说明。而要创建一个物体,我们首先需要对一个物体进行 外形 与 材质 的描述。
webgl 渲染管线
由于 Three.js 是基于 WebGL 构建的高级 3D 库,理解 WebGL 的渲染管线有助于我们更深入地掌握 Three.js 中物体的渲染机制。因此,在介绍 Three.js 中的物体、几何体和材质之前,我们先简要了解 WebGL 的渲染管线。
顶点着色器阶段
顶点着色器是渲染管线的第一个阶段,他会通过 GPU 进行计算,将各个顶点转换为坐标值(裁剪空间坐标值),并且处理法线、颜色和纹理坐标等顶点数据。最终绘制顶点到相应的坐标
图元装配器
在 webgl 中,图元装配器 可以通过你输入的类型(三角面,线段,连续路径,...) 。然后将所有的顶点坐标转换为不同类型的组,从而使得后面光栅化能够对其进行材质处理(光栅化与上色)。注意: 在 webgl 中,任何面都是由三角面组合而成的
光栅化阶段
这一阶段你可以理解为绘制,也就是通过像素将内容绘制出来。通过对前面已经组成好的图形进行基础(不带颜色的)像素填充,并且每一个图形中都包含它对应的颜色、纹理等信息。
片元着色器阶段
片元着色器阶段是可以理解为上色阶段,它会处理每个图形中的信息,对其进行上色等操作。 ![[Pasted image 20251218101056.png]]
几何形状 Geometry
在 Three.js 中,你可以将几何形状理解为Three.js 对于顶点着色器的顶点位置的重新封装,我们只需要通过对应几何形状的 API 直接生成相应的顶点数据对象,然后交由图元装配器进行装配。我们在视图中看到模型的形状就是其决定的。
js
// 创建一个正方形
const geometry = new THREE.BoxGeometry(100, 100, 100)
材质 Material
Material 的作用是对于一个物体的外观的描述,例如: 表面的材质,颜色,透明度等,它决定了我们在视图中看到的模型的样式。其中,在 Three.js 中的面是分为正反两面的,当材质为单面时,我们只能从正面看到该物体。
js
const material = new THREE.side: THREE.DoubleSide,({
color: 0x00ffff,
side: THREE.DoubleSide, // 决定你的材质的面是单面还是双面
})
模型(物体) Objecet
在 Three.js 中,Mesh(网格)、Line(线)和 Points(点云)是三种常见的可渲染对象。它们都由 Geometry(几何体) 定义形状,由 Material(材质) 定义外观。只有将这些对象添加到场景(Scene)中,并通过渲染器(Renderer)进行绘制,我们才能在屏幕上看到由 Geometry 和 Material 共同定义的视觉结果。
js
// 创建一个网格模型对象
const mesh = new THREE.Mesh(geometry, material)
// 将网格模型对象添加到三维场景中
scene.add(mesh)
摄像机
在 Three.js 中摄像机可以理解为相机的显示器,它的类型,位置,透视将决定了我们能看到的内容,并且我们也可以随时通过移动摄像机来更换我们想看到的场景内容。
PerspectiveCamera(透视摄像机)
这是摄像机中的一种类型,通过对这个摄像机来了解一些摄像机的基本概念。
- fov: 摄像机竖直方向的角度
- aspect: 摄像机的长宽比(画幅)
- near: 摄像机的近截面(你的摄像机最近的界限)
- far: 摄像机的远截面(你的摄像机最远的界限)
js
// 创建透视相机
const width = 800
const height = 500
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000)
// 摄像机的起始位置
camera.position.set(200, 200, 200)
// 摄像机对准的位置
camera.lookAt(0, 0, 0)
渲染
渲染就像我们按下摄像机的快门。当我们对当前的场景和摄像机放到同一个渲染器中时,我们便可以通过渲染器将当前摄像机看到的内容进行渲染,渲染过后渲染器会生成一个canvas,然后放置到页面中。然后我们便可以在页面中看到我们的模型。
js
// 创建渲染器
const render = new THREE.WebGLRenderer()
render.setSize(width, height)
// 渲染出内容
render.render(scene, camera)
// 输出内容
document.body.appendChild(render.domElement)
案例
接下来,让我们通过一个基础的立方体来回顾我们前面的知识
js
// 创建三维场景
const scene = new THREE.Scene()
// 创建一个正方形
const geometry = new THREE.BoxGeometry(100, 100, 100)
// 创建一个基础材质
const material = new THREE.MeshBasicMaterial({
color: 0x00ffff,
side: THREE.DoubleSide, // 决定你的材质是单面还是双面
})
// 创建一个坐标轴,便于观察模型位置
const axios = new THREE.AxesHelper(300)
scene.add(axios)
// 创建一个网格模型对象
const mesh = new THREE.Mesh(geometry, material)
// 将网格模型对象添加到三维场景中
scene.add(mesh)
// 创建透视相机
const width = 800
const height = 500
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000)
// 摄像机的起始位置
camera.position.set(200, 200, 200)
// 摄像机对准的位置
camera.lookAt(0, 0, 0)
// 创建渲染器
const render = new THREE.WebGLRenderer()
render.setSize(width, height)
// 渲染出内容
render.render(scene, camera)
// 输出内容
document.body.appendChild(render.domElement)
下章预告
---《Three.js 入门指南:让网页"立体"起来的秘密》