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的渲染流程,说白了就三步:

  1. 写着色器——告诉GPU怎么处理数据
  2. 传数据——把顶点位置等信息传给GPU
  3. 画出来——调用绘制命令

来看代码:

<!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图形的基本单元,所有复杂的模型都是由三角形拼出来的。

嗯,今天就到这里。代码自己动手敲一遍,比看十遍都管用。