什么是 WebGL ?
WebGL 是一门可以在浏览器中渲染 3D/2D 图形的技术。它提供一套 JavaScript API,使用在 canvas元素上,从而使得 Web 开发者可以在浏览器中无需借助插件即可绘制3D图形。
虽然开发使用的是 JavaScript 接口,但最终调用的是硬件设备底层 OpenGL 库相关的接口,并且有硬件加速,所以 WebGL 渲染要比一般的 Canvas 2D 渲染性能高很多。
WebGL 与 OpenGL、OpenGL ES ?
这里了解一下 OpenGL。根据 MDN 上的描述,OpenGL (Open Graphics Library) 是一套用来渲染2D和3D矢量图形的跨语言的、跨平台的应用程序接口(API) 。其实 OpenGL 是一套规范而不是接口,接口的实现要靠各硬件厂商,这里的硬件厂商主要指 GPU 生产商,因为 OpenGL 库指令是运行在GPU中的,各个 GPU 厂商如果要支持 OpenGL 的话,就需要按照规范去实现自己的 OpenGL 库。各个厂家的 OpenGL 库实际上是他们整合自己的图形知识以及 GPU 硬件指令而实现的,这些实现通常被称为“驱动”,负责将 OpenGL 定义的 API 命令翻译为 GPU 运行指令,所以使用时只需要安装显卡驱动即可。
WebGL 根植于 OpenGL,但它们中间还隔着一个 OpenGL ES。OpenGL ES 是 OpenGL 的子集,专门针对手机/PDA/游戏主机等嵌入式设备设计的。OpenGL ES 主要直接提供 C 语言的 api,其他平台可以根据习惯加一层包装,比如安卓提供了 Java 的包装, IOS 提供了 Objective-C 的包装。而 WebGL 就是基于 OpenGL ES 2.0 的 JavaScript API,也可以说是 OpenGL ES 通过增加一个 JavaScript 绑定而实现了 WebGL。
学习 WebGL 需要学习什么 ?
使用 WebGL 绘图主要利用 WebGL API 和 canvas 元素,WebGL API 是 JavaScript 语言的,这点对于前端而言不在话下的。前面提到 OpenGL 是运行在 GPU 中的,但不是所有编程语言都能运行在 GPU 上,这就需要用到特殊的编程语言,即 着色器语言,着色器语言用于计算机图形编程,运行在GPU中,而平时所说的大多数语言编写的程序都是运行在 CPU 中的。与 OpenGL API 相配合的是着色器语言 GLSL,与 OpenGL ES API、WebGL API 相互配合的是着色器语言 GLSL ES。所以我们还需要学习 GLSL ES 这门语言。
可能有人会疑问,说好的使用 JavaScript 开发,怎么还要学习新编程语言,这个 GLSL ES 也能运行在浏览器中吗?GLSL ES 不能在浏览器环境运行,只是我们会借助 WebGL API 将编写好的 GLSL ES 程序传入底层设备运行,最终借助系统显卡来在浏览器里更流畅地展示图形场景,这样既达到了高性能,又不需要浏览器插件的支持。
WebGL 与 Three.js ?
很多人都听过 Three.js 的大名,知道它是用来做 3D 图形的,其实 Three.js 是基于原生 WebGl API 和 着色器封装得到的 3D 引擎,是一个 JavaScript 库。直接通过原生 WebGL 编写会比较麻烦,还需要写 GLSL ES 的程序,所以开发项目一般直接使用 Three.js 引擎。但是如果想深入 Web3D 应用开发,学习底层 WebGL 和着色器 GLSL 知识还是很有必要的。
小试牛刀
笔者也是刚了解 webgl,这段实践代码也是参考网上资料得来,已经加了注释。直接复制这段 html 代码在浏览器中执行即可,可以自行修改相关参数,查看显示效果,具体知识点留待后续文章记录。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebGL 画一个点</title>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<script>
// 获取画布
const canvas = document.getElementById('canvas');
// 获取 webgl 上下文
const gl = canvas.getContext('webgl');
/* 下面两个着色器源码以字符串形式存着,供 webgl api 调用 */
//顶点着色器源码
const vertexShaderSource = '' +
'void main(){' +
//给内置变量gl_PointSize赋值像素大小
' gl_PointSize=20.0;' +
//顶点位置,位于坐标原点
' gl_Position =vec4(0.0,0.0,0.0,1.0);' +
'}';
//片元着色器源码
const fragShaderSource = '' +
'void main(){' +
//定义片元颜色
' gl_FragColor = vec4(1.0,0.0,0.0,1.0);' +
'}';
//初始化着色器
const program = initShader(gl, vertexShaderSource, fragShaderSource);
// 指定将要用来清空绘图区域的颜色
gl.clearColor(0,1,0,0.5);
// 使用之前指定的颜色,清空绘图区
gl.clear(gl.COLOR_BUFFER_BIT);
//开始绘制,显示器显示结果
gl.drawArrays(gl.POINTS, 0, 1);
//声明初始化着色器函数
function initShader(gl, vertexShaderSource, fragmentShaderSource) {
//创建顶点着色器对象
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
//创建片元着色器对象
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
//引入顶点、片元着色器源代码
gl.shaderSource(vertexShader, vertexShaderSource);
gl.shaderSource(fragmentShader, fragmentShaderSource);
//编译顶点、片元着色器
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
//创建程序对象program
const program = gl.createProgram();
//附着顶点着色器和片元着色器到program
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
//链接program
gl.linkProgram(program);
//使用program
gl.useProgram(program);
//返回程序program对象
return program;
}
</script>
</body>
</html>
结尾
对于 WebGL,我还是挺感兴趣的,希望后面自己能多写几篇记录。
以上关于 WebGL 的记录,都是笔者从网上众多资料中总结而来。如有错误,欢迎指出。