大家好,我是前端西瓜哥。
本文讲解如何用 WebGL 绘制一个点。
WebGL
WebGL 是浏览器支持的一种绘制图形的 API,是一个标准。我们可以通过 Canvas 元素 在网页的特定区域绘制 2D 和 3D 图形。
相比 Canvas 2D,WebGL 利用了 GPU 的计算能力,绘制速度更快,性能更优。
WebGL 基于 OpenGL 发展而来,某种意义上就是 Web 版的 OpenGL,但是阉割了一些功能。
更具体点,是来自 OpenGL 的一个特殊版本 OpenGL ES 2.0,全称为 OpenGL for Embedded Systems,“用于嵌入式系统的 OpenGL”。
使用 WebGL,除了浏览器正统脚本语言 JavaScript,还要使用一种 名为 GLSL ES 的类 C 着色器语言。
绘制过程和着色器
将代码描述的效果真正绘制到屏幕上的过程,称为 渲染管线。
管线(pipeling)这个词有点奇怪,因为它没有对应的比较好的翻译,是一个直译。
管线指的是 数据处理的流水线,这个流水线上有很多处理器,会将数据一步步地进行处理,最终得到一个成品。渲染管线,就是渲染过程中执行的一个个步骤。
渲染管线的流程为:
- 顶点处理阶段。接收顶点信息,比如我要画一个三角形,三个点的位置在哪里,尺寸、颜色分别是多少。
- 图形装配。多个点组合成怎样的图形。我们会用 API 进行指定,比如点、线段、三角形。
- 光栅化。将顶点转换为需要绘制的像素信息,比如位置、深度。
- 片元处理阶段。设置像素的颜色信息。
这四个流程中,我们能操作的是第 1 和第 4 步。
绘制一个点
Demo 地址:
https://codesandbox.io/s/webgl-hui-zhi-yi-ge-dian-2-bpwz8p。
下面我们来讲解如何绘制一个点。
首先是 WebGL 绘制的地方 Canvas。我们需要在 HTML 中添加一个 Canvas 元素,然后在 JavaScript 中获取这个元素,并拿到 WebGL 渲染上下文。
如果你用过 Canvas 2D,它对应的上下文变量命名通常是 ctx(context)。但对于 WebGL,我们通常会跟随 OpenGL 的习惯,将变量命名为 gl(OpenGL 的 gl,Graphics Library 的意思)。
接着是顶点着色器。
顶点着色器,用于设置图形的顶点相关的信息,设置好顶点,WebGL 才能确定好图形的位置等信息,好绘制出来。
着色器的代码是在 JavaScript 脚本中,用字符串来写 glsl。
顶点着色器
先是顶点着色器。
gl_Postion 和 gl_PointSize 是 WebGL 顶点着色器的内部变量,用于设置点的位置和点的大小。
vec4 表示矢量类型,同时也是内置函数,调用它就能得到一个 vec4 类型。
这里设置了顶点的位置 (0.0, 0.0, 0.0, 1.0)。WebGL 使用的是三维坐标系,并使用右手坐标系,就是 x 轴指向右侧,y 轴指向上方,z 轴指向观察者。原点就在画布的正中央。
三维中,一个点只要三个维度 x、y、z 就够了,但引入了第四个维度 w,从笛卡尔坐标升维为齐次坐标,作用是方便做矩阵变换和透视投影。齐次坐标 (x, y, z, w)
等价于三维坐标 (x/w, y/w, z/w)
。w 通常会设置为 1。
需要注意的是,着色器中的的数值需要加上小数点,表示用的是浮点数类型。这和 JavaScript 随便写都会变成浮点数不一样。
片元着色器
然后是片元着色器。
顶点着色器确定图形的点的位置,片元着色器则是用于设置多个顶点围成的图形的像素点的 颜色。
gl_FragColor 是片元着色器的内部变量,这里设置为红色。
创建渲染器
因为是入门文章,细节不展开讲了。
总之下面这段代码,将前面声明的顶点着色器和片元着色器的两段源码,进行了编译。
清空缓存
首先第一行代码将背景色设置为黑色。当然你也可以设置为其他颜色,比如绿色 (0, 1, 0, 1)。
第二行是清空缓存区,填充背景色。
绘制点
该 API 用于调用绘制指令,有三个参数:
- mode。绘制怎样的图元。比如点(gl.POINTS)、各种类型的线段、各种类型的三角形。也就这三种图元。再复杂的图形也是由一个个三角形组成的。这里用到的微积分的思想,将三维物体不断的细分,其实就是一个个非常小的平面组成的,三个点确定一个平面,也就是三角形。正方形也是两个三角形组成。
- first。从哪个顶点开始绘制,通常是 0。本文只是画一个点,这个参数没太大意义,存在多个顶点时才有用,虽然也少用。
- count。使用到几个顶点。
绘制结果如下:
结尾
下一篇画个三角形。