WebGL 是以 OpenGL ES 2.0 为基础的 3D 编程应用接口。
渲染管线(图形流水线)
渲染管线是指将数据从3D场景转换成2D图像,最终在屏幕上显示出来的总过程。它分为几个阶段:应用阶段、几何阶段和光栅阶段,关于这3个阶段的详细介绍可以点这里查看。
下面我们来仔细看看 WebGL 中的每个步骤:
1.顶点着色器
顶点着色器一般用来对模型的顶点进行矩阵变换,一般就是将模型的所有顶点乘于一个变换矩阵,使该模型位于相对于WebGL坐标系中的某个位置。
顶点着色器是可编程的,使用的语言是 GLSL 来进行编写,下面我们主要说一下几种常用的属性类型:
- attribute变量:用户自定义变量,一般是存储顶点属性的变量;
- uniform变量:恒值变量,一般表示每个顶点都一致的变量,比如变换矩阵、光照等;
- varying变量:易变变量,将顶点着色器的数据传递给片段着色器时使用;
- 内置常量:WebGL 内部的常量;
2.图元装配
这个阶段,GPU会将我们传入的顶点装配成三角形、线段或者点;装配好之后,会自动截去不在可视区域内的信息;
3.光栅化
这个阶段,GPU会将装配好的三角形转换成对应的像素,并将这些像素传入下一个阶段;
4.片段着色器
得到光栅化的片段像素位置数据之后,就可以通过片段着色器为这些像素进行上色了,这是第二个可以编程的地方;
我们可以对图片进行采样之后,再这里进行上色;
5.逐片段操作
本步骤包含了多个子操作,每个操作都会影响当前片段最终的显示效果,下面我们看下几个常见的子操作:
1.裁剪测试
会有一个裁剪的范围,如果像素位于该范围之外,会被剔除,不会到达绘制缓存;
2.多重采样片段操作
这一步会修改像素的alpha值和覆盖值,主要用来实现抗锯齿的效果;
3.背面剔除
剔除是一种通过避免渲染背对观察者的几何体面来提高性能的优化措施,比如一个立方体,你不会看到背离你的那一面(总是只有一面在你的前方),因此我们不需要绘制出背面;
4.alpha测试
指的是将一个像素点的alpha值和一个固定值比较,如果比较的结果失败,像素将不会被写到显示输出中;
5.模板测试
模板缓存与颜色缓存的大小一致,模板缓存中的像素点与后台缓存的像素点是一一对应的。
模板缓存允许我们动态地、有针对性地决定是否将某个像素写入后台缓存中。模板缓存用与获得某种特效,如镜面效果或阴影效果。在实现镜面效果时,我们在“镜子”这块区域中绘制某个特定物体的映像,而使用模板缓存来阻止物体映像在“非镜子”的区域中进行绘制;
为了进行这种阻止,就需要使用模板测试。判断是否将某个像素写入后台缓存的决策过程,称为模板测试;
6.alpha融合
融合技术能使我们将当前要进行的光栅化的像素的颜色与先前已经光栅化并处于同一位置的像素的颜色进行合成,即将正在处理的图元颜色值与存储中后台缓存中的像素颜色值进行合成。利用该技术,我们可以获得各种各样的效果,尤其是透明效果。不过值得注意的是,为了场景中绘制透明物体,通常需要对物体按照由后到前的顺序进行混合处理,如果按照任意顺序进行处理将会产生严重的失真。所以在blending(混色)操作之前要来一次深度测试;
7.深度测试
这一步会进行深度测试,抛弃掉位置靠后的像素值,因为这个位置的像素本身就是被更前面的像素覆盖的;
8.融合
这一步会将新的颜色值和已经存在的颜色值进行组合,得出融合后的颜色值,比如,老的颜色是红色,新的是50%透明的黑色,那么融合之后的颜色看起来就应该是暗红色;
5.抖动(Dithering)
这一步是为了解决可使用的颜色过少会出现色带的问题,通过较少的颜色来模拟较多颜色的技术,可以查看这篇文章来理解;
帧缓存
数据经过整个渲染管线处理之后,最终会写入到帧缓存中,帧缓存存储了最终会显示到屏幕上的颜色数据。
帧缓存包含了 3 个具体的缓存:
1.颜色缓存
存储每个像素点的具体颜色值的缓存,常见的具体格式可以分为:
- 16位:RGB565,红色5位,绿色6位,蓝色5位,不保存透明通道(之所以绿色多1位是因为人眼对绿色更加敏感);
- 24位:RGB888,红色8位,绿色8位,蓝色8位,不保存透明通道;
- 32位:RGBA8888,红色8位,绿色8位,蓝色8位,透明通道8位;
2.Z-缓存(深度缓存)
存储每个像素点的深度,用来决定是丢弃当前像素颜色还是保留,假设,新渲染的颜色在旧颜色的前面,那么就覆盖旧颜色,如果新颜色在旧颜色的后面(被遮挡了)则保留旧颜色。
3.模板缓存
用来控制颜色缓存某个位置的写入操作,常用来处理阴影。