three.js基于Webgl做了什么?

一、我们讲什么?

我们讲两个东西:

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生成。

比如如下就是一段顶点着色器代码:

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),这个过程类似我们用相机拍照。


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程序,模型看起来是什么质地(颜色、漫反射贴图等)、灯光等由片元着色器来计算。

如下是一段简单的片元着色器代码:

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,所有顶点位置肯定都变化了。

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

但是,如果我们直接将顶点位置用javascript计算出来,那性能会很低(顶点通常成千上万),而且,这些数据也非常不利于维护。

所以,我们用矩阵modelMatrix将这个旋转信息记录下来。


5.1.2、视图矩阵

然后,我们将相机往上偏移30。

camera.position.y = 30;

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


5.1.3、投影矩阵

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


5.1.4、应用矩阵

然后,我们编写顶点着色器:

gl_Position = position * modelMatrix * viewMatrix * projectionMatrix;

这样,我们就在GPU中,将最终顶点位置计算出来了。

实际上,上面所有步骤,three.js都帮我们完成了。


5.2、片元着色器处理流程

我们已经知道片元着色器负责处理材质、灯光等信息,但具体是怎么处理呢?

如下图:


5.3、three.js完整运行流程:


当我们选择材质后,three.js会根据我们所选的材质,选择对应的顶点着色器和片元着色器。

three.js中已经内置了我们常用着色器。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容