我随便逛逛,我会讲解Three.js的基础

作者: 前端  发布:2019-11-20

4.2.3.1、片元着色器处理流程

片元着色器具体是如何控制颜色生成的呢?
图片 1
如上图,顶点着色器是有多少顶点,运行了多少次,而片元着色器则是,生成多少片元(像素),运行多少次。

0.简介
之前我已经给出了一篇《开始使用Three.js》。如果你还没有读过,你可能需要去读一下,本文的基础是在那一篇教程的基础上完成的。

5.1、Three.js顶点处理流程

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

之前WebGL在图元装配之后的结果,由于我们认为模型是固定在坐标原点,并且相机在x轴和y轴坐标都是0,其实正常的结果是这样的:

图片 3

5.1.1、模型矩阵
图片 4

现在,我们将模型顺时针旋转Math.PI/6,所有顶点位置肯定都变化了。

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

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

但是,如果我们直接将顶点位置用javascript计算出来,那性能会很低(顶点通常成千上万),而且,这些数据也非常不利于维护。
所以,我们用矩阵modelMatrix将这个旋转信息记录下来。

5.1.2、视图矩阵
图片 5

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

camera.position.y = 30;

1
camera.position.y = 30;

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

5.1.3、投影矩阵
图片 6

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

5.1.4、应用矩阵

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

gl_Position = position * modelMatrix * viewMatrix * projectionMatrix;

1
gl_Position = position * modelMatrix * viewMatrix * projectionMatrix;

这样,我们就在GPU中,将最终顶点位置计算出来了。
实际上,上面所有步骤,three.js都帮我们完成了。
图片 7

/**
* 每个顶点坐标乘以模型视图矩阵在乘以投影矩阵
* 获得在二维屏幕上的坐标
*/
void main() {
gl_Position = projectionMatrix *
modelViewMatrix *
vec4(position,1.0);
}

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

图片 8

当我们选择材质后,three.js会根据我们所选的材质,选择对应的顶点着色器和片元着色器。
three.js中已经内置了我们常用着色器。

全文完。

2 赞 4 收藏 评论

图片 9

复制代码 代码如下:

4.3、WebGL的完整工作流程

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

译序
Three.js是一个伟大的开源WebGL库,WebGL允许JavaScript操作GPU,在浏览器端实现真正意义的3D。但是目前这项技术还处在发展阶段,资料极为匮乏,爱好者学习基本要通过Demo源码和Three.js本身的源码来学习。

4.2.3、光栅化

和图元装配类似,光栅化也是可控的。
图片 11
在图元生成完毕之后,我们需要给模型“上色”,而完成这部分工作的,则是运行在GPU的“片元着色器”来完成。
它同样是一段opengl es程序,模型看起来是什么质地(颜色、漫反射贴图等)、灯光等由片元着色器来计算。
如下是一段简单的片元着色器代码:

precision mediump float; void main(void) { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); }

1
2
3
4
precision mediump float;  
void main(void) {
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}

gl_FragColor即输出的颜色值。

事实上,我只介绍了这两段简短的代码段。Three.js在你自己的着色器代码前已经将它们加进来了,所以你不必担心。实话说,Three.js还加了很多东西在你的代码前面,比如光照数据、节点颜色和节点法向量等等。如果没有Three.js你要亲自创建并设置这些对象,真的。
6.使用着色器材质

一、我们讲什么?

我们讲两个东西:
1、WebGL背后的工作原理是什么?
2、以Three.js为例,讲述框架在背后扮演什么样的角色?

复制代码 代码如下:

三、先了解一个基础概念

1、什么是矩阵?
简单说来,矩阵用于坐标变换,如下图:
图片 12
2、那它具体是怎么变换的呢,如下图:
图片 13
3、举个实例,将坐标平移2,如下图:
图片 14

如果这时候,你还是没有理解,没有关系,你只需要知道,矩阵用于坐标变换。

我们还可以像着色器材质添加另外两种属性:uniforms和attributes。他们可以是向量、整数或者浮点数,但是如我之前所说,uniforms变量在计算所有点的过程中保持不变,所以它们更加可能是单一的值,而attributes变量是对每个顶点而言的,所以他们应当是数组。在一个mesh中,attribute变量和顶点应当是一一对应的。
7.小结
这篇教程就到这里了,实际上我已经讲得很多了,但是在许多方面我都只是一掠而过。在下一篇教程中我会提供一个复杂的着色器,通过它我将传入一些attributes变量和uniforms变量来做一些模拟光照效果。
我将这篇教程的源码打包了,你可以下载下来作为参考

4.2.1、获取顶点坐标

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

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

复制代码 代码如下:

4.2.2.1、顶点着色器处理流程

回到刚才的话题,顶点着色器是如何处理顶点坐标的呢?
图片 16
如上图,顶点着色器会先将坐标转换完毕,然后由GPU进行图元装配,有多少顶点,这段顶点着色器程序就运行了多少次。
你可能留意到,这时候顶点着色器变为:

attribute vec4 position; uniform mat4 matrix; void main() { gl_Position = position * matrix; }

1
2
3
4
5
attribute vec4 position;
uniform mat4 matrix;
void main() {
  gl_Position = position * matrix;  
}

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

/**
* 将任意一个像元色设置为粉红
*/
void main() {
gl_FragColor = vec4(1.0, // R
0.0, // G
1.0, // B
1.0); // A
}

4.2、WebGL绘制流程

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

接下来,我们分步讲解每个步骤。

/**
* 假设我们可以使用JQuery
* 将着色器的代码文本从DOM中抽取出来
*/
var vShader = $('vertexshader');
var fShader = $('fragmentshader');
var shaderMaterial =
new THREE.ShaderMaterial({
vertexShader: vShader.text(),
fragmentShader: fShader.text()
});

二、我们为什么要了解原理?

我们假定你对WebGL已经有一定了解,或者用Three.js做过了一些东西,这个时候,你可能碰到了这样一些问题:
1、很多东西还是做不出来,甚至没有任何思路;
2、碰到bug无法解决,甚至没有方向;
3、性能出现问题,完全不知道如何去优化。
这个时候,我们需要了解更多。

我想讨论一下着色器。在Three.js帮助你免去了很多麻烦之前,原生WebGL就很优秀了。有的时候,你也许会想要完成一些特定的效果,或者想对呈现在你的屏幕上的东西钻研得更深入一些,那么着色器一定会进入你的视野。如果你像我一样,你也同样希望实现一些比上一篇教程中的基础更加有意思的东西。这篇教程中,我会讲解Three.js的基础,这些基础实际上为我们做了很多枯燥的工作。
在开始之前我还要说,这篇教程会有相当多的篇幅在解释着色器的代码,之后会有一篇教程会在着色器代码的基础上前进一点,利用着色器去做点什么。这是因为着色器shaders第一眼看上去并不易懂,需要一些解释。
1.两种着色器
WebGL没有固定的渲染管线,你无法直接使用一个黑盒子式的着色器(译者注:上个世纪的显卡基本都只支持固定渲染管线);WebGL提供的是可编程的管线,这种方式更强大但也更难理解和使用。长话短说,可编程渲染管线意味着编写程序的人要自己负责获取顶点并将它绘制在屏幕上了。着色器是渲染管线的一部分,有两种着色器:
1.顶点着色器
2.片元着色器
你应当知道的是,这两种着色器都完全运行在显卡的GPU上,我们将需要它们处理的数据从CPU上卸下,装到GPU上,减轻了CPU的复旦。现代的GPU对着色器需要的调用的运算类型都做了大幅优化,这样做很值得。
2.顶点着色器
基元形状,比如一个球体,是由顶点构成的,是吧?顶点着色器被依次传入这些顶点中的一个顶点,然后处理它。如何处理每个顶点是可以自由定制的,但顶点着色器有一个必做的事,就是为一个名为 gl_Position 的变量赋值,该变量是一个4维数组,表示该顶点最终在屏幕上的位置。这本身是个有意思的过程,因为我们实际上在谈论如何将一个三维坐标(一个具有x、y、z值得顶点)转化为,或者说投影到二维的屏幕上。谢天谢地,要是我们使用Three.js之类的工具,我们能够如此方便地访问到 gl_Position 。
3.片元着色器
现在我们有包含顶点的三维物体了,现在要将物体投影到二维屏幕上了,但颜色哪里去了?纹理和光照呢?这正是片元着色器要处理的。
和顶点着色器类似,片元着色器有一项必须完成的任务:设置或消除变量 gl_FragColor ,另一个四维浮点变量,也就是片元点最终的颜色。什么是片元?想象一个具有三个顶点的三角形,片元就是经过这三个顶点计算后的,所有在三角形内部的点。因此,片元值由顶点的值内插生成。如果一个顶点的颜色是红色,相邻顶点的颜色是蓝色,那么我们可以观测到颜色从红色顶点附近渐变,由红色变成紫色,最终在蓝色顶点附近变成蓝色。
4.着色器变量
说到着色器变量,有三种:Uniforma,Attributes和Varyings。当我第一次听到这三个词语时,我很困惑,因为它们和我之前用到的东西完全不匹配。但现在,你可以这样理解它们:
1.Uniforms变量既可以传入顶点着色器,也可以传入片元着色器,它们包含了哪些在整个渲染过程中保持不变的变量,比如,一个点光源的位置。
2.Attributes变量对应于每个顶点,它们只可以传入顶点着色器中,比如每个顶点都具有一个颜色。Attributes变量和顶点的关系是一一对应的。
3.Varyings变量是在顶点着色器中定义,并且准备传入给片元着色器的变量。为了确保这点,我们需要确保在两个着色器中变量的类型和命名完全一致。一个经典的应用是法线向量,因为在计算光照的时候需要用到法线。
在后面一篇教程中,我会使用这三种变量,你也会学习到这三种变量如何真正应用起来得。
现在,我们已经谈过了顶点着色器、片元着色器和三种着色器变量。是时候来看一个我们可以创建的最简单的着色器了。
5.Hello World(译者吐槽:能不能不要秀法语啊)
这儿有一个最简单的顶点着色器:

图解WebGL&Three.js工作原理

2017/05/22 · HTML5 · WebGL

原文出处: 万波   

“哥,你又来啦?”
“是啊,我随便逛逛。”
“别介啊……给我20分钟,成不?”
“5分钟吧,我很忙的。”
“不行,20分钟,不然我真很难跟你讲清楚。”
“好吧……”
“行,那进来吧,咱好好聊聊”

Three.js是一个伟大的开源WebGL库,WebGL允许JavaScript操作GPU,在浏览器端实现真正意义的3D。但是目前这项技术还处在发展阶段,资料极为...

五、Three.js究竟做了什么?

我们知道,three.js帮我们完成了很多事情,但是它具体做了什么呢,他在整个流程中,扮演了什么角色呢?
我们先简单看一下,three.js参与的流程:
图片 18
黄色和绿色部分,都是three.js参与的部分,其中黄色是javascript部分,绿色是opengl es部分。
我们发现,能做的,three.js基本上都帮我们做了。

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

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

在顶点着色器中,我们通过Three.js传入了一些uniforms变量。有两个4×4的矩阵uniforms变量:模型视图矩阵和投影矩阵。你并不需要太了解这两个矩阵是怎么工作的。简单地说,这两个矩阵描述了三维点坐标如何投影成为二维屏幕上的坐标。

四、WebGL的工作原理

这就是全部了。如果现在直接运行的话,你就可以在屏幕上看到一个“无光”的粉红色形体。不是很复杂,是吗?

4.2.2、图元装配

我们已经知道,图元装配就是由顶点生成一个个图元(即三角形)。那这个过程是自动完成的吗?答案是并非完全如此。
为了使我们有更高的可控性,即自由控制顶点位置,WebGL把这个权力交给了我们,这就是可编程渲染管线(不用理解)。
WebGL需要我们先处理顶点,那怎么处理呢?我们先看下图:
图片 19

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

attribute vec4 position; void main() { gl_Position = position; }

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

从这儿开始,Three.js将会编译并运行你的着色器,将其连接在你创建的材质上,材质又依附于你创建的mesh上。它并没有变得比真的更容易。也许是这样吧,但我们在考虑浏览器3D编程,我想你应该预期,这个话题是有一定复杂性的。

一个最简单的片元着色器:

4.1、WebGL API

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

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

就算是这样一个复杂的模型,也是一个个三角形画出来的。

5.2、片元着色器处理流程

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

本文由9159.com发布于前端,转载请注明出处:我随便逛逛,我会讲解Three.js的基础

关键词:

上一篇:没有了
下一篇:没有了