WebGL - 简介

你好,未来的 WebGL 巫师们!欢迎你们开始这场进入网页 3D 图形世界的激动人心的旅程。我很高兴能作为你们的向导,一起探索 WebGL 这个迷人的领域。作为一个教授计算机图形学超过十年的人,我可以向你们保证,尽管前面的道路可能看起来令人却步,但它也是非常有益的。所以,系好安全带,让我们一起跳进去!

WebGL - Introduction

什么是 OpenGL?

在我们深入了解 WebGL 之前,让我们快速了解一下它的前身,OpenGL。想象你是一位试图绘制杰作的艺术家。OpenGL 就像你神奇的颜料和画笔套装,让你能在计算机屏幕上创作出令人惊叹的视觉艺术。

OpenGL,全称 Open Graphics Library,是一个跨平台的 API(应用程序编程接口),用于渲染 2D 和 3D 向量图形。自 1992 年以来,它一直存在,并且成为无数游戏、模拟和视觉应用程序的基础。

这里有一个简单的类比:如果你的计算机屏幕是一块画布,那么 OpenGL 就是帮助程序员以惊人的细节和速度在这块画布上绘画的工具集。

什么是 WebGL?

现在,让我们将焦点转移到我们节目的明星:WebGL。如果说 OpenGL 是桌面应用程序的画笔,那么 WebGL 就是网络的画笔。它是一个 JavaScript API,允许你在不需要任何插件的情况下,直接在网页中创建令人惊叹的 3D 图形。

WebGL 将 OpenGL ES 2.0(面向嵌入式系统的 OpenGL 版本)的力量带到了网络,允许开发者通过 JavaScript 直接利用 GPU(图形处理单元)。

下面是一个简单的 WebGL “Hello, World!” 示例:

<canvas id="glCanvas" width="640" height="480"></canvas>
<script>
function main() {
const canvas = document.getElementById("glCanvas");
const gl = canvas.getContext("webgl");

if (gl === null) {
alert("无法初始化 WebGL。您的浏览器或计算机可能不支持它。");
return;
}

gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
}

window.onload = main;
</script>

这段代码在你的网页上创建了一个黑色画布。它可能看起来不多,但这是你进入 WebGL 世界的第一步!

谁开发了 WebGL

WebGL 由 Khronos Group 开发,他们也是 OpenGL 的幕后团队。WebGL 首次在 2011 年推出,自那时起,它彻底改变了我们对网络图形的看法。

有趣的事实:WebGL 的开发受到了 Vladimir Vukićević 在 Mozilla 的实验的启发。他创建了一个暴露 OpenGL ES 给 JavaScript 的画布元素,这为 WebGL 的诞生奠定了基础。

渲染

渲染是将 2D 或 3D 模型生成图像的过程。在 WebGL 中,这个过程是实时发生的,这意味着图像是在你与之交互时即时生成的。

下面是一个渲染红色三角形的简单示例:

// 顶点着色器程序
const vsSource = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;

// 片段着色器程序
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

// ...(初始化代码)

// 绘制场景
function drawScene(gl, programInfo, buffers) {
gl.clearColor(0.0, 0.0, 0.0, 1.0);  // 清除为黑色,完全不透明
gl.clearDepth(1.0);                 // 清除所有内容
gl.enable(gl.DEPTH_TEST);           // 启用深度测试
gl.depthFunc(gl.LEQUAL);            // 近处的物体遮挡远处的物体

// 在开始绘制之前清除画布
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

// ...(设置场景)

{
const numComponents = 2;  // 每次迭代提取 2 个值
const type = gl.FLOAT;    // 缓冲区中的数据是 32 位浮点数
const normalize = false;  // 不标准化
const stride = 0;         // 从一组值到下一组值需要多少字节
const offset = 0;         // 缓冲区内部从哪里开始
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
numComponents,
type,
normalize,
stride,
offset);
gl.enableVertexAttribArray(
programInfo.attribLocations.vertexPosition);
}

// 告诉 WebGL 在绘制时使用我们的程序
gl.useProgram(programInfo.program);

{
const offset = 0;
const vertexCount = 3;
gl.drawArrays(gl.TRIANGLES, offset, vertexCount);
}
}

这段代码设置了必要的着色器和缓冲区,以在屏幕上渲染一个简单的红色三角形。

GPU

GPU 代表图形处理单元。它是一种专用处理器,旨在处理渲染图形时涉及的复杂数学运算。虽然 CPU 非常适合通用计算,但 GPU 在并行执行许多简单计算方面表现出色,这对于图形工作来说非常理想。

可以这样想:如果渲染一个复杂的 3D 场景就像绘制一幅巨大的壁画,那么 CPU 就像一位极其有才华的艺术家,而 GPU 就像数千名普通艺术家一起工作。

GPU 加速计算

GPU 加速计算指的是将 GPU 与 CPU 结合使用,以加速科学、分析、工程、消费和企业应用程序。在 WebGL 的背景下,这意味着你的图形计算被卸载到 GPU,从而释放 CPU 用于其他任务,并带来更平滑、更快的图形。

支持的浏览器

WebGL 的美妙之处在于它在现代浏览器中的广泛支持。截至 2023 年,WebGL 受以下浏览器支持:

浏览器 版本
Chrome 9+
Firefox 4+
Safari 5.1+
Opera 12+
Internet Explorer 11+
Microsoft Edge 12+

WebGL 的优势

WebGL 提供了许多优势:

  1. 跨平台兼容性:一次编写,到处运行(只要有浏览器)。
  2. 无需插件:它内置在浏览器中。
  3. 硬件加速:利用 GPU 提高性能。
  4. 与网络技术集成:可以与其他网络 API 结合,提供丰富的交互体验。
  5. 开放标准:任何人都可以为其发展做出贡献。

环境设置

设置你的 WebGL 环境出奇地简单。你所需要的只是:

  1. 一个现代的网络浏览器
  2. 一个文本编辑器(我推荐 Visual Studio Code)
  3. 一个本地网络服务器(你可以使用 Python 的内置服务器或 Node.js 的 http-server)

以下是一个简单的设置过程:

  1. 为你的项目创建一个新目录
  2. 创建一个 HTML 文件(例如,index.html)和一个 JavaScript 文件(例如,script.js
  3. 在你的 HTML 文件中,包含你的 JavaScript 文件并设置一个画布:
<!DOCTYPE html>
<html>
<head>
<title>我的第一个 WebGL 项目</title>
</head>
<body>
<canvas id="glCanvas" width="640" height="480"></canvas>
<script src="script.js"></script>
</body>
</html>
  1. 在你的 JavaScript 文件中,初始化 WebGL:
function main() {
const canvas = document.getElementById("glCanvas");
const gl = canvas.getContext("webgl");

if (gl === null) {
alert("无法初始化 WebGL。您的浏览器或计算机可能不支持它。");
return;
}

// WebGL 代码放在这里
}

window.onload = main;

就这样!你现在准备好开始你的 WebGL 之旅了。记住,学习 WebGL 就像学习骑自行车——一开始可能会摇摇晃晃,但经过练习,你很快就能自如地驰骋。祝你编程愉快!

Credits: Image by storyset