原标题:图解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编写,由java以字符串的形式定义并传递给GPU生成。
比如如下就是一段顶点着色器代码:
attribute vec4 position;void main() { gl_Position = position; }
attribute修饰符用于声明由浏览器(java)传输给顶点着色器的变量值;
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,将三维世界坐标转换成屏幕坐标,这个矩阵叫投影矩阵,由java传入,至于这个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传递给顶点着色器;
责任编辑: