1、WebGL基础入门:什么是WebGL、WebGL与OpenGL的关系、WebGL在现代浏览器中的支持情况、第一个WebGL程序(绘制一个点)
1.1 什么是WebGL?
WebGL,全称是Web Graphics Library。说白了,它就是一套在浏览器里跑3D图形的标准。
我经常跟刚入行的朋友这么解释:WebGL让你能用JavaScript直接调用GPU。你想想看,以前想在网页上搞3D,要么装插件,要么用Flash,麻烦得很。WebGL的出现,彻底改变了这个局面。
它本质上是一个光栅化引擎。什么意思?就是它根据你写的代码,在屏幕上画出一个个像素点。嗯,这里要注意,WebGL本身不帮你管理3D场景、不帮你做碰撞检测,它只负责一件事——画图。
核心要点:WebGL是浏览器与GPU之间的桥梁。你写JavaScript,它帮你翻译成GPU能理解的指令。
1.2 WebGL与OpenGL的关系
这个问题,我面试时经常问候选人。很多人搞混这两者的关系。
简单来说:WebGL是从OpenGL ES衍生出来的。
OpenGL是桌面端的图形标准,功能很全。但移动端设备性能有限,所以有了OpenGL ES(Embedded Systems),砍掉了一些不常用的功能。WebGL 1.0基本就是照着OpenGL ES 2.0来的。
我记得2011年刚接触WebGL时,最大的感受就是——API长得太像了。如果你写过OpenGL,学WebGL基本就是换个语言的事。
| 对比项 | OpenGL | OpenGL ES | WebGL |
|---|---|---|---|
| 运行环境 | 桌面系统 | 移动/嵌入式 | 浏览器 |
| 语言 | C/C++ | C/C++ | JavaScript |
| 版本基础 | 完整版 | ES 2.0/3.0 | 基于ES 2.0/3.0 |
| 着色器语言 | GLSL | GLSL ES | GLSL ES |
个人经验:我建议初学者直接学WebGL,不用先啃OpenGL。因为WebGL的API更精简,调试也方便——浏览器F12就能看,比OpenGL那套调试工具友好多了。
1.3 WebGL在现代浏览器中的支持情况
这个问题,我可以很肯定地告诉你:现在的主流浏览器,全都支持WebGL。
具体来说:
- Chrome:从2011年起就支持了,现在WebGL 2.0也没问题
- Firefox:同样很早就支持了
- Safari:iOS 8之后全面支持,macOS上也没问题
- Edge:新版Edge基于Chromium,支持度跟Chrome一样
为什么会这样?因为WebGL已经是W3C的标准了。浏览器厂商不实现这个标准,用户就会跑掉。
不过有一点要注意——WebGL 2.0的支持度不如1.0那么普及。我在项目中遇到过一些老设备,比如2013年的iPad,它只支持WebGL 1.0。所以做产品时,我一般会先检测一下设备能力。
避坑指南:我曾经在一个项目中,直接用了WebGL 2.0的特性,结果客户的老电脑上白屏了。后来我加了个降级方案——检测到不支持2.0就自动切到1.0。这个习惯我一直保留到现在。
1.4 第一个WebGL程序:绘制一个点
好了,理论说完了,咱们直接上手写代码。
第一个程序,我习惯画一个点。为什么?因为这是最简单的WebGL程序,能让你看清整个流程。
WebGL的渲染流程,说白了就三步:
- 写着色器——告诉GPU怎么处理数据
- 传数据——把顶点位置等信息传给GPU
- 画出来——调用绘制命令
来看代码:
<!DOCTYPE html>
<html>
<head>
<title>我的第一个WebGL程序</title>
</head>
<body>
<canvas id="glCanvas" width="500" height="500"></canvas>
<script>
// 1. 获取canvas并创建WebGL上下文
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');
if (!gl) {
alert('你的浏览器不支持WebGL!');
}
// 2. 顶点着色器——告诉GPU点的位置
const vsSource = `
void main() {
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
gl_PointSize = 10.0;
}
`;
// 3. 片元着色器——告诉GPU点的颜色
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
// 4. 编译着色器
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
}
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);
// 5. 创建程序并链接
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// 6. 清空画布并绘制
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, 1);
</script>
</body>
</html>
这段代码运行后,你会在黑色画布的正中间看到一个红色的点。
我来解释一下关键部分:
- gl_Position:这是顶点着色器的内置变量,表示点的位置。vec4(0.0, 0.0, 0.0, 1.0)就是原点位置。
- gl_PointSize:点的大小,单位是像素。我设了10个像素。
- gl_FragColor:片元着色器的内置变量,表示颜色。vec4(1.0, 0.0, 0.0, 1.0)就是红色。
- drawArrays:真正开始画。gl.POINTS表示画点,0表示从第0个顶点开始,1表示画1个点。
小技巧:如果你看不到这个点,检查一下gl_PointSize是不是设得太小了。我刚开始学的时候,设了个1像素的点,找了半天才看到。
1.5 总结
这一章我们走完了WebGL的完整流程。从概念到代码,从理论到实践。
你想想看,虽然只是画了一个点,但背后的流程——创建上下文、写着色器、编译链接、绘制——这套框架,以后画任何复杂的3D模型,都是这个套路。
下一章,我们会在这个基础上,画一个三角形。三角形可是3D图形的基本单元,所有复杂的模型都是由三角形拼出来的。
嗯,今天就到这里。代码自己动手敲一遍,比看十遍都管用。