浅谈图形学、WebGL 以及 Three.js
主題
- 图形学: 基本概念/顶点着色器/片元着色器/图形是如何绘制到电脑萤幕上的
- WebGL: 基本概念/Canvas
- Three.js: 相关API/通过 Three.js 来实作
—————————————————————————————————————————————
展示:https://threejs.org/examples/
- 图形学
基本概念:图形学(Computer Graphics, CG)是研究计算机在硬件和软件的帮助下创建计算机图形的计算机科学学科,主要关注数字合成与操作视觉的图形内容。
它包含三维图形/二维图形以及影响处理。当然,今天主要关注的是3D/2D图形处理的部分。
计算机图形学的主要研究内容就是研究如何在计算机中表示图形;以及利用计算机进行图形的计算、处理和显示的相关原理与算法。
什么是图形:图形通常由由点、线、面、体等几何元素,以及灰度、色彩、线型、线宽等非几何属性组成。
主要目的:利用电脑产生令人赏心悦目的真实感图形。因此,为了创建更符合真实世界的场景,必须先创建该场景的几何表示、再利用某种光照模型,以计算在假想的光源、纹理、材质属性下的光照明效果。
3D电脑图形:电脑里储存几何数据的三维表示。有三个维度。因此储存的顶点信息必须有三个维度的信息。
图形是如何绘制到电脑萤幕的:三个阶段:建模、场景布局和动画、绘制
1⃣️ 建模:确定后面场景所要使用的对象的形状。大多数情况下,还包括编辑物体表面或材料性质(例如,颜色、荧光度、漫射、镜面反射等等)
2⃣️场景布局:模型在渲染之前,必须防止在一个场景中。于是我们才可以定义模型的位置和大小。
场景设置涉及安排一个场景内的虚拟物体、灯光、摄影机和其他实体。这样便可以制作静态画面、或一段动画。
照明非常重要。光照的强度、方向对一个场景的氛围和情绪有重要影响。
3⃣️渲染:渲染这一步骤令刚刚建立好的场景和模型得以显示在荧幕面前。渲染过程需要非常昂贵的计算,特别是模拟的物理过程复杂且多样时。(例如尘埃粒子的显示)
着色器
着色器是一种电脑程序。其在电脑图形的渲染上有很大的作用。
顶点着色器:处理每个顶点,把顶点的位置投射在荧幕上,即计算顶点的二维坐标。同时,其也负责顶点的深度缓冲(Z-Buffer,用来确定哪个顶点在前,哪个在后,以确定哪个表面在前,哪个在后,来使渲染图形时能够正确确定)的计算。
片元着色器:计算每个片元(片段,最小颜色单位,一般是像素)的颜色和其他属性(光照、材质、凹凸效果)。
2. WebGL (Web Graphics Library)
是3D图形库,一种 JavaScript API。通过支援WebGL,浏览器可以在不使用其他插件的情况下显示2D、3D图形。WebGL已经是浏览器的标准。
Canvas: 画布 是HTML5的一种标签。JavaScript可以利用该标签进行绘图后的显示。
WebGL API
WebGL基本绘图元素只有点、线、三角形,如下图中的这种复杂图形,它也是由三角形构成的
WebGL 绘制流程
1⃣️ 获取顶点坐标
简单图形的顶点坐标可以通过自己写或者库(如three.js)提供的api来获得,
但是复杂图形的顶点坐标数目庞大,一般是通过三维软件导出的(如3dmax等软件导出的obj文件)
由于顶点数据往往成千上万,在获取到顶点坐标后,我们通常会将它存储在显存,即缓存区内,方便GPU更快读取。
2⃣️ 图元装配
图元装配就是由顶点生成一个个图元(即三角形)。
顶点着色器--它由opengl es编写,由javascript以字符串的形式定义并传递给GPU生成。
如下是一段顶点着色器代码:
attribute vec4 position;
void main() {
gl_Position = position;
}
attribute修饰符用于声明由浏览器(javascript)传输给顶点着色器的变量值;
position即我们定义的顶点坐标;
gl_Position是一个内建的传出变量。
这段代码什么也没做,如果是绘制2d图形,没有什么问题,但如果是绘制3d图形,即传入的顶点坐标是一个三维坐标,我们则需要将三维坐标转换成屏幕坐标。
比如:v(-0.5, 0.0, 1.0)转换为p(0.2, -0.4),这个过程类似我们用相机拍照。
顶点着色器处理流程
如上图,顶点着色器会先将坐标转换完毕,然后由GPU进行图元装配,有多少顶点,这段顶点着色器程序就运行了多少次。
这时候顶点着色器变为:
attribute vec4 position;
uniform mat4 matrix;
void main() {
gl_Position = position * matrix;
}
这就是应用了矩阵matrix,将三维世界坐标转换成屏幕坐标,这个矩阵叫投影矩阵,由javascript传入。
3⃣️ 光栅化
在图元生成完毕之后,我们需要给模型“上色”,而完成这部分工作的,则是运行在GPU中的“片元着色器”来完成。
它同样是一段opengl es程序,模型看起来是什么质地(颜色、漫反射贴图等)、灯光等由片元着色器来计算。
如下是一段简单的片元着色器代码:
precision mediump float;
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
gl_FragColor即输出的颜色值。
片元着色器处理流程
片元着色器生成多少片元(像素),运行多少次。
3. Three.js
Three.js是以WebGL为基础的库,封装了一些3D渲染需求中重要的工具方法与渲染循环。WebGL门槛相对较高,Three.js对WebGL提供的接口进行了非常好的封装,简化了很多细节,大大降低了学习成本。
Three.js在WebGL基础上都为我们做了什么?
辅助我们导出了模型数据;
自动生成了各种矩阵;
生成了顶点着色器;
辅助我们生成材质,配置灯光;
根据我们设置的材质生成了片元着色器。
而且将WebGL基于光栅化的2D API,封装成了我们人类能看懂的 3D API。