关于前端:图解WebGLThreejs工作原理转载

29次阅读

共计 3763 个字符,预计需要花费 10 分钟才能阅读完成。

去年的时候,有钻研 3D 可视化我的项目,用 three.js 做了个 3D 可视化监控 V1 版本,次要参照的是
郭隆邦技术博客 http://www.yanhuangxueyuan.co…
three editor https://threejs.org/editor/
form-generator https://mrhj.gitee.io/form-ge…
学习 three 的时候,看用户文档还是比拟头疼,很多货色不晓得如何查看,只能挨着找 demo,找到类似成果,而后查 demo 代码找要害 API,在去看官网 docs, 之前没有 webgl 根底,学习 three 能够做出相干性能,然而具体是怎么实现的,并不理解。往年打算学习下 webgl,在 w3cschool 下面看 webgl 的常识,比拟干燥,没有残缺代码。很多术语都看不懂,还须要一个个去搜寻。明天无心翻到图解 webgl&three.js 工作原理,感觉写的比拟好,故转载过去多学习几遍,也能够帮忙更多人来理解它们的原理。好吧,咱们一起来学习吧!

一、咱们讲什么?

咱们讲两个货色:
1、WebGL 背地的工作原理是什么?
2、以 Three.js 为例,讲述框架在背地表演什么样的角色?

二、咱们为什么要理解原理?

咱们假设你对 WebGL 曾经有肯定理解,或者用 Three.js 做过了一些货色,这个时候,你可能碰到了这样一些问题:
1、很多货色还是做不进去,甚至没有任何思路;
2、碰到 bug 无奈解决,甚至没有方向;
3、性能呈现问题,齐全不晓得如何去优化。
这个时候,咱们须要理解更多。

三、先理解一个根底概念 

1、什么是矩阵?
简略说来,矩阵用于坐标变换,如下图:

2、那它具体是怎么变换的呢,如下图:

3、举个实例,将坐标平移 2,如下图:

如果这时候,你还是没有了解,没有关系,你只须要晓得,矩阵用于坐标变换。

四、WebGL 的工作原理

4.1、WebGL API

在理解一门新技术前,咱们都会先看看它的开发文档或者 API。
查看 Canvas 的绘图 API,咱们会发现它能画直线、矩形、圆、弧线、贝塞尔曲线。
于是,咱们看了看 WebGL 绘图 API,发现:

它只能会点、线、三角形?肯定是我看错了。
没有,你没看错。

就算是这样一个简单的模型,也是一个个三角形画进去的。

4.2、WebGL 绘制流程

简略说来,WebGL 绘制过程包含以下三步:
1、获取顶点坐标
2、图元拆卸(即画出一个个三角形)
3、光栅化(生成片元,即一个个像素点)

接下来,咱们分步解说每个步骤。

4.2.1、获取顶点坐标

顶点坐标从何而来呢?一个立方体还好说,如果是一个机器人呢?
没错,咱们不会一个一个写这些坐标。
往往它来自三维软件导出,或者是框架生成,如下图:

写入缓存区是啥?
没错,为了简化流程,之前我没有介绍。
因为顶点数据往往成千上万,在获取到顶点坐标后,咱们通常会将它存储在显存,即缓存区内,不便 GPU 更快读取。

4.2.2、图元拆卸

咱们曾经晓得,图元拆卸就是由顶点生成一个个图元(即三角形)。那这个过程是主动实现的吗?答案是并非齐全如此。
为了使咱们有更高的可控性,即自在控制顶点地位,WebGL 把这个势力交给了咱们,这就是可编程渲染管线(不必了解)。
WebGL 须要咱们先解决顶点,那怎么解决呢?咱们先看下图:

咱们引入了一个新的名词,叫“顶点着色器”,它由 opengl es 编写,由 javascript 以字符串的模式定义并传递给 GPU 生成。
比方如下就是一段顶点着色器代码:

1

2

3

4

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),这个过程相似咱们用相机拍照。(该转换没太看懂 屏幕坐标跟 V 坐标是如何转换过去的,有晓得的能够解释下吗?)

4.2.2.1、顶点着色器解决流程

回到方才的话题,顶点着色器是如何解决顶点坐标的呢?

如上图,顶点着色器会先将坐标转换结束,而后由 GPU 进行图元拆卸,有多少顶点,这段顶点着色器程序就运行了多少次。
你可能留意到,这时候顶点着色器变为:

attribute vec4 position;

uniform mat4 matrix;

void main() {

gl_Position = position * matrix;

}

这就是利用了矩阵 matrix,将三维世界坐标转换成屏幕坐标,这个矩阵叫投影矩阵,由 javascript 传入,至于这个 matrix 怎么生成,咱们暂且不探讨。

4.2.3、光栅化

和图元拆卸相似,光栅化也是可控的。

在图元生成结束之后,咱们须要给模型“上色”,而实现这部分工作的,则是运行在 GPU 的“片元着色器”来实现。
它同样是一段 opengl es 程序,模型看起来是什么质地(色彩、漫反射贴图等)、灯光等由片元着色器来计算。
如下是一段简略的片元着色器代码:

1

2

3

4

precision mediump float`;`

void main(`void`) {

gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);

}

gl_FragColor 即输入的色彩值。

4.2.3.1、片元着色器解决流程

片元着色器具体是如何管制色彩生成的呢?

如上图,顶点着色器是有多少顶点,运行了多少次,而片元着色器则是,生成多少片元(像素),运行多少次。

4.3、WebGL 的残缺工作流程

至此,本质上,WebGL 经验了如下解决流程:
1、筹备数据阶段
在这个阶段,咱们须要提供顶点坐标、索引(三角形绘制程序)、uv(决定贴图坐标)、法线(决定光照成果),以及各种矩阵(比方投影矩阵)。
其中顶点数据存储在缓存区(因为数量微小),以修饰符 attribute 传递给顶点着色器;
矩阵则以修饰符 uniform 传递给顶点着色器。
2、生成顶点着色器
依据咱们须要,由 Javascript 定义一段顶点着色器(opengl es)程序的字符串,生成并且编译成一段着色器程序传递给 GPU。
3、图元拆卸
GPU 依据顶点数量,挨个执行顶点着色器程序,生成顶点最终的坐标,实现坐标转换。
4、生成片元着色器
模型是什么色彩,看起来是什么质地,光照成果,暗影(流程较简单,须要先渲染到纹理,能够先不关注),都在这个阶段解决。
5、光栅化
能过片元着色器,咱们确定好了每个片元的色彩,以及依据深度缓存区判断哪些片元被挡住了,不须要渲染,最终将片元信息存储到色彩缓存区,最终实现整个渲染。

五、Three.js 到底做了什么?

咱们晓得,three.js 帮咱们实现了很多事件,然而它具体做了什么呢,他在整个流程中,表演了什么角色呢?
咱们先简略看一下,three.js 参加的流程:

黄色和绿色局部,都是 three.js 参加的局部,其中黄色是 javascript 局部,绿色是 opengl es 局部。
咱们发现,能做的,three.js 基本上都帮咱们做了。

  • 辅助咱们导出了模型数据;
  • 主动生成了各种矩阵;
  • 生成了顶点着色器;
  • 辅助咱们生成材质,配置灯光;
  • 依据咱们设置的材质生成了片元着色器。

而且将 webGL 基于光栅化的 2D API,封装成了咱们人类能看懂的 3D API。

5.1、Three.js 顶点解决流程

从 WebGL 工作原理的章节中,咱们曾经晓得了顶点着色器会将三维世界坐标转换成屏幕坐标,但实际上,坐标转换不限于投影矩阵。
如下图:

之前 WebGL 在图元拆卸之后的后果,因为咱们认为模型是固定在坐标原点,并且相机在 x 轴和 y 轴坐标都是 0,其实失常的后果是这样的:

5.1.1、模型矩阵

当初,咱们将模型顺时针旋转 Math.PI/6,所有顶点地位必定都变动了。

1

box.rotation.y = Math.PI/6;

然而,如果咱们间接将顶点地位用 javascript 计算出来,那性能会很低(顶点通常成千上万),而且,这些数据也十分不利于保护。
所以,咱们用矩阵 modelMatrix 将这个旋转信息记录下来。

5.1.2、视图矩阵

而后,咱们将相机往上偏移 30。

1

camera.position.y = 30;

同理,咱们用矩阵 viewMatrix 将移动信息记录下来。

5.1.3、投影矩阵

这是咱们之前介绍过的了,咱们用 projectMatrix 记录。

5.1.4、利用矩阵

而后,咱们编写顶点着色器:

1

gl_Position = position * modelMatrix * viewMatrix * projectionMatrix;

这样,咱们就在 GPU 中,将最终顶点地位计算出来了。
实际上,下面所有步骤,three.js 都帮咱们实现了。

5.2、片元着色器解决流程

咱们曾经晓得片元着色器负责解决材质、灯光等信息,但具体是怎么解决呢?
如下图:

5.3、three.js 残缺运行流程:

当咱们抉择材质后,three.js 会依据咱们所选的材质,抉择对应的顶点着色器和片元着色器。
three.js 中曾经内置了咱们罕用着色器。

全文完。
原文链接
作者:万技师
出处:http://www.cnblogs.com/wanbo/

正文完
 0