反正不管你信不信,我觉得WebGL是接下来一个时代的流量入口啦,谁不喜欢酷炫的东西,所以本着跟着时代步伐的精神,终于开始进行WebGL的学习啦(饶过我JS的学习还没有结束,JS学习笔记的剩余内容会在后期更新啦!)
1. WebGL历史
WebGL是基于OpenGL ES进行开发的,WebGL1.0版本基于OpenGL ES2.0,而WebGL2.0会基于OpenGL ES3.0。
那么OpenGL ES是撒?OpenGL ES是OpenGL的一个子库,主要是针对嵌入式计算机,智能手机和游戏设备等的子库。
最后OpenGL又是什么呢?OpenGL是计算机三维图形渲染的两大技术之一,另一个技术是大家都很熟悉了Directive3D(微软DirectiveX的一部分,反正经常会报错),Directive主要是针对Window系统的渲染,而OpenGL则被设计在跨平台的操作上了。
总的来说借鉴一下书上的OpenGL世代图,大致也就是这样:
OpenGL 1.0 ——> OpenGL ES 1.1
OpenGL 2.0 ——> OpenGL ES 2.0 ——> WebGL 1.0
OpenGL 3.3 ——> OpenGL ES 3.0 ——> WebGL 2.0
OpenGL 4.3
最后补充一点,在OpenGL2.0版本以后我们才可以对着色器(Shader)进行操作,操作着色器的语言是GLSL语言/GLSL ES语言(和C语言一样)
2. WebGL程序组成
先来看一个最简单的例子(在画布上画一个红色对点):
html部分:
script部分:
根据这个例子,我将整个WebGL程序分成了以下对几个部分
2.1 Javascript主程序
包含两个主要部分Canvas和WebGL API,WebGL利用了HTML5的Canvas来绘制3D图形
2.1.1 Canvas
Canvas是HTML5引入,用于构建2D,3D的图形,可以在标签中增加文本,来判断浏览器是否支持
,因为不支持的浏览器将显示这些文本信息,而支持的将默认显示一个空的画布。
要使用WebGL,首先要利用Canvas获取到上下文,主要按照三步进行操作
- 获取页面的Canvas元素
- 利用Canvas元素获取上下文(WebGL现在可以直接使用getContext('webgl')来获取,对于2d的我们常用getContext('2d')方法获取Canvas上下文)
- 利用WebGL API来操作绘制图形
2.2.2 WebGL API
WebGL API是WebGL编程的最主要部分,因为包含的API太多了,我也是新入门,所以目前暂时提及几个在例子中用到的主要函数:
// 清空缓冲区相关
gl.clearColor: 设置webgl颜色缓冲区清除后画布颜色
gl.clear: 清除webgl的缓冲区,可以有三个参数,分别为颜色缓冲(COLOR_BUFFER_BIT),深度缓冲区(DEPTH_BUFFER_BIT),模板缓冲区(STENCIL_BUFFER_BIT)
gl.drawArrays:利用缓冲区数据绘制图形
// 构建程序相关
gl.createProgram: 创建一个program对象
gl.attachShader: 将程序对象和shader进行绑定
gl.linkProgram: 编译程序?
gl.useProgram:设置使用的webgl program对象
// Shader构建相关
gl.createShader: 根据类型构建Shader
gl.shaderSource: 加载Shader的GLSL资源
gl.compileShader: 编译Shader返回shader对象
// 操作GLSL中变量相关,通常命名为:<方法名><变量个数><变量类型>
gl.getAttribLocation: 获取程序中的attribute变量的位置
gl.vertex[1,2,3,4]f: 设置attribute的值的函数族
gl.getUniformLocation: 获取程序中uniform变量的位置
gl.uniform[1,2,3,4]f: 设置uniform的值的函数族
2.2 GLSL
构成WebGL的第二部分是GLSL程序,WebGL构建需要两个着色器Vertex Shader(顶点着色器)和Fragment Shader(片元着色器)
注:我其实比较喜欢用英文而不喜欢用中文来表述这两个着色器,因为现在英文文档较多,知道英文名比中文名要好。
2.2.1 Vertex Shader
中文译名顶点着色器,顾名思义,主要是用来描述顶点信息(位置,尺寸等)可以看到例子中描述了gl_Position
(顶点位置)和gl_PointSize
(顶点大小,颜色?),这里的gl_Position
和gl_PointSize
是GLSL中的内置变量。
2.2.2 Fragment Shader
中文译名片元着色器,用途是用来描述绘制的图形过程和光照等信息,例子中指定了整个片段的颜色信息,gl_FragColor
也是GLSL中的内置变量。
2.2.3 GLSL中的变量
按照前面例子的写法,我们绘制的点的位置和大小,颜色,硬编码写到GLSL程序中,而没办法通过页面操作进行改变了,那么如果我们想要GLSL和web页面惊醒交互,按么我们就要使用GLSL变量。
GLSL中变量的声明包含三部分:
<存储限定符><变量类型><变量名>
其中存储限定符有三个attribute
(只用于vertex source中),uniform
(可用于vertex和fragment source中),以及varying
(用于vertex和fragment之间的数据传递);
变量类型有float
,vec[1,2,3,4]
(分别代表有多少个矢量组成的数据结构);
变量名通常根据存储限定符来进行定义attribute
就是a_
,uniform
就是u_
于是代码就可以根据以下进行调整,来设置变量:
let vertex_source = `
attribute vec4 a_Position;
void main() {
gl_Position = a_Position;
}
`
let fragment_source = `
precision mediump float; // 必须要,指定精度
uniform vec4 u_FragColor;
void main() {
gl_FragColor = u_FragColor;
}
`
3. WebGL其他
3.1 坐标系转换
为了完成接下来的例子,我们还需要说明关于WebGL中的坐标系转换。
首先,WebGL使用的是笛卡尔坐标系,也就是说右手坐标系。就是x轴的正向是大拇指方向,y轴正向是四指方向,z轴方向为穿过掌背到掌心;
其次,WebGL中的坐标系的值是从[-1.0, 1.0]
的范围,原点为canvas图形中心点;
最后,对于我们使用的web页面坐标系,最左上角为原点位置,面对屏幕时,x正方向往右,y轴正方向往下
所以,我们要设置正确的WebGL点的坐标位置时,我们要将web页面的坐标信息转换为WebGL的坐标信息,转换过程如下:
let rect = canvas.getBoundingClientRect();
x = (x - rect.left - rect.width/2) / (rect.width/2);
y = (rect.height/2 - (y - rect.top)) / (rect.height/2);
3.2 根据鼠标点击绘制点的完整例子
最后附上一个完整的入门例子:
4. 总结
因为还是入门,所以能做的东西很有限,只能绘制简单的二维图形,还完全没有发挥WebGL三维图形构建的技术,之后会持续更新学习进度的。
5. 参考
《WebGL编程指南》
MDN-WebGL-Start