3

一、 WebGL

1.1 什么是WebGL

说到 WebGL,就不得不说说 OpenGL。在早期的个人电脑中,使用最广泛的 3D 图形渲染技术是 Direct3D 和 OpenGL。Direct3D 是微软 DirectX 技术的一部分,主要用于 Windows 平台。 OpenGL 作为一种开源的跨平台技术,赢得了众多开发者的青睐。

后来一个特殊的版本——OpenGL ES,它专为嵌入式计算机、智能手机、家用游戏机和其他设备而设计。它从 OpenGL 中删除了许多旧的和无用的功能,同时添加了新功能。例如去掉了矩形等多余的多边形,只保留点、线、三角形等基本图形。这使它在保持轻巧的同时仍然足够强大以渲染精美的 3D 图形。

而 WebGL 是从 OpenGL ES 派生出来的,它专注于 Web 的 3D 图形渲染。下图展示了它们之间的关系:
image.png

1.2 WebGL 历史

下图展示了WebGl的历史:

image.png

从上图可以看出,WebGL 已经很老了。不仅因为它存在已久,还因为它的标准是从 OpenGL 继承而来的,OpenGL 的设计理念可以追溯到 1992 年,而这些古老的理念其实与今天 GPU 的工作原理非常不符。

对于浏览器开发者来说,需要适配 GPU 的不同特性,这给他们带来了很多不便,虽然这些对于上层开发人员来说是看不到的。 

从上图可以看出,2014 年苹果发布了 Metal。 Steve Jobs 是 OpenGL ES 的支持者,他认为这是行业的未来。所以当时苹果设备上的游戏都依赖 OpenGL ES(比如愤怒的小鸟,水果忍者),都是很经典的游戏。但乔布斯去世后,苹果放弃了 OpenGL ES,开发了新的图形框架 Metal。 

微软在 2015 年也发布了自己的 D3D12【Direct3D 12】图形框架。紧随其后的是 Khronos Group,图形界的国际组织,类似于前端圈子里的 W3C、TC39。而 WebGL 是它的标准。甚至也逐渐淡化了 WebGL,转而支持现在的 Vulkan。

迄今为止,Metal、D3D12 [Direct3D 12] 和 Vulkan 并列为现代三大图形框架。这些框架充分释放了 GPU 的可编程能力,让开发者可以最大限度的自由控制 GPU。

需要说明的是,当今的主流操作系统不再支持 OpenGL 作为主要支持。这意味着今天编写的每一行 WebGL 代码都有 90% 的机会不被 OpenGL 绘制。它在 Windows 计算机上使用 DirectX 绘制,在 Mac 计算机上使用 Metal 绘制

二、WebGPU

2.1 什么是WebGPU

WebGPU 是用于 Web 的下一代图形和计算 API。它提供对现代 GPU 的基础访问,从而在 Web 平台上实现高性能 3D 图形、图像处理和通用计算。经过多年的开发和测试,WebGPU 已经到了推荐阶段,可以被主流浏览器采用。谷歌宣布 Chrome 从版本 113 开始提供 WebGPU 支持,从而在 ChromeOS、Windows 和 macOS 设备上实现惊人的视觉效果和复杂的计算。 

WebGPU 为 Web 开发开辟了很多新的可能性。它可以为身临其境的虚拟世界、交互式数据可视化、高级图像和视频编辑、物理模拟、机器学习等提供支持——所有这些都在浏览器中运行。WebGPU 还支持围绕 web 3、隐私和安全性的新用例,这在以前是不可行的。

Web 平台继续突破在线可能性的界限。借助 WebGPU 和 WebXR、WebTransport 和 WebCodecs 等相关标准,未来的 Web 将比以往任何时候都更加强大和开放。虽然这仍是一项新兴技术,但 WebGPU 展示了开放 Web 上图形和计算的广阔前景。 

WebGPU 提供基础 API,需要了解图形编程和 GPU 架构才能有效使用。然而,在库、工具和资源的帮助下,Web 开发人员可以使用 WebGPU。Babylon.js、Three.js、TensorFlow.js 和 Filament 等 WebGPU 采纳者展示了如何将 WebGPU 包装到更高级别的框架中,以构建交互式 3D 场景、运行机器学习模型等。

2.2 WebGU历史

WebGPU 的诞生源于对更现代和高效的 Web 图形 API 的需求,以取代基于 OpenGL API 家族的 WebGL。WebGL 在网页上实现了许多令人惊叹的体验,例如 Google 地球、交互式音乐视频、3D 房地产漫游等,但它也存在一些限制和挑战,例如:

  • 缺乏对新 GPU 功能的支持,如计算着色器、光线追踪、可变速率着色等。
  • 由于需要验证每个API的调用,并在CPU和GPU内存之间复制数据,因此CPU开销和内存使用量会很高。
  • 由于 OpenGL 对不同的浏览器和平台上的支持和优化不同,导致性能和行为可能会不一致。

2016 年,谷歌向 WebGL 工作组展示了一个 PPT,探讨了构建一个最终取代 WebGL 的新 API 的基本思想和原则,又名“WebGL Next”。该演示文稿提出了一个低级 API,它将公开现代 GPU 的底层功能,例如命令缓冲区、管道、描述符等。API 也将是显式的,这意味着开发人员将对 GPU 资源的使用方式有更多的控制权 管理和同步。

2017 年,Apple 的 WebKit 团队提议创建 W3C 社区组来设计 API。同时,他们基于 Apple Metal 中的概念,宣布了一项名为“WebGPU”的概念和提案的技术证明。WebGPU 名称后来被社区采纳为未来标准名称。最初的提案已重命名为“WebMetal”以避免进一步混淆。
 

W3C 社区小组开始着手定义 WebGPU 规范和 API,Mozilla、Apple、Intel 和 Microsoft 等主要公司都做出了贡献。该小组还收到了 Web 开发人员和行业专家的反馈。目标是创建一个高效、安全、可移植的API:

  • 安全:API 应防止常见错误,如内存泄漏、数据竞争或无效操作等,这些错误可能会导致崩溃或安全问题。
  • 可移植:API 应该在不同的浏览器和平台上一致地工作,而不需要特定于供应商的扩展或解决方法。
  • 表现力:API 应允许开发人员充分利用现代 GPU 的潜力,而不影响性能或灵活性。

Chromium 团队于 2017 年初展示了名为 NXT 的第一个概念原型。NXT 实现了一个新的 API,它可以在带有 OpenGL 的 Chromium 中运行,或者与 OpenGL 和 Metal 独立运行。NXT 借鉴了所有 Vulkan、Direct3D 12 和 Metal 原生 API 的概念。

2020 年,WebGPU 进入第一个公共工作草案阶段,这意味着该规范足够稳定,可以接受公众审查和反馈。该规范定义了 JavaScript API 和基于 SPIR-V 的 WebGPU 着色语言 (WGSL),旨在与现有的着色语言(如 HLSL 和 GLSL)兼容。

在2021年,WebGPU 达到了候选推荐阶段,这意味着规范已经可以进行实现测试和互操作性评估。规范还定义了一些可选特性,这些特性可以根据浏览器的平台支持进行启用,例如深度钳位、各向异性滤波、纹理压缩 BC 等。
 

2023 年,WebGPU 进入提议推荐阶段,这意味着该规范已准备好接受 W3C 主席的认可。该规范还定义了一些实验性功能,浏览器可以在标志或前缀下启用这些功能,例如光线追踪或可变速率着色。

2023 年 4 月 6 日,Google 宣布 Chromium/Chrome 浏览器将从 Chromium/Chrome 113 开始在支持 Vulkan 的 ChromeOS 设备、macOS 和具有 Direct3D 12 的 Windows 设备上启用 WebGPU 支持。对包括 Linux 和 Android 在内的其他平台的 WebGPU 支持将在之后进行添加。

2.3 WebGPU对Web开发的影响

WebGPU 对 Web 3 开发有这深远的影响,因为它实现了 WebGL 不可能或不可行的新可能性和场景。以下是WebGPU 的一些用例:

  • 高性能图形和计算:WebGPU 允许开发人员利用现代 GPU 的强大功能在 Web 上创建令人惊叹的视觉效果和复杂的模拟。WebGPU 可以处理大量数据和并行计算,例如粒子系统、流体动力学、物理引擎、机器学习等。WebGPU 还可以支持高级渲染技术,例如光线追踪、阴影、反射、环境遮挡等。
  • 跨平台兼容性:WebGPU 在不同的浏览器和平台上一致地工作,不需要供应商特定的扩展或解决方法。WebGPU 还可以在支持 Vulkan、Metal 或 Direct3D 12 的移动设备上运行,这些设备涵盖了大多数现代智能手机和平板电脑。这意味着开发人员可以创建在任何设备上都能流畅运行的 Web 应用。
  • 面向未来:WebGPU 旨在可扩展并适应未来的 GPU 功能和技术。WebGPU 可以将新功能公开为可选扩展或实验性功能,浏览器可以根据其平台支持启用这些功能。这意味着开发人员可以使用最新和最强大的 GPU 功能,而无需等待标准赶上或冒兼容性问题的风险。
  • Web 3:WebGPU 可以使 Web 应用与去中心化网络和协议进行交互,例如区块链、IPFS 等。WebGPU 还可以支持 Web 上的安全和可验证计算,例如零知识证明、同态加密等。这意味着开发人员可以创建更透明、更可靠、更有弹性的 Web 应用。
  • 元宇宙:WebGPU 可以使 Web 应用能够在 Web 上创建身临其境的交互式虚拟世界和体验。WebGPU 可以支持大型场景和环境、复杂的动画和交互、逼真的光照和材料、空间音频和触觉等。这意味着开发人员可以创建更具吸引力、社交性和趣味性的 Web 应用。 

三、WebGL vs WebGPU

作为WebGL 的继承者,WebGPU是一种在浏览器中使用 GPU 的全新 API,它承诺将于 2022 年第一季度在常规 Chrome 中可用。与 WebGL 相比,WebGPU 承诺具有更好的性能和与现代硬件的更好兼容性,但 WebGPU 最知名的功能是用于在 GPU 上执行计算的特殊 API。以下图形演示了在进行矩阵计算时对性能的消耗。

image.png

WebGPU 在不同行业和应用程序中有许多潜在用例。其中一些包括:游戏、虚拟和增强现实、机器学习、科学模拟以及数字媒体和广告。WebGPU 可以创建在网络浏览器中运行的高性能、跨平台游戏。开发人员可以使用光线追踪和异步计算等现代图形硬件功能来创建与桌面游戏类似的更具沉浸感和逼真的游戏体验。到目前为止,游戏是非常特定于平台的。

大多数桌面游戏都是为 Windows 开发的,而将 Mac 和 Linux 用户抛在后面。如果 WebGPU 成功成为桌面游戏的标准,开发人员可以创建一个可以跨平台运行的版本。基于浏览器的游戏的另一个好处是不再需要像 Steam 这样的集中式店面来分发游戏。开发人员可以直接在浏览器中出售对他们游戏的访问权限,并消除中间商。
 

目前,没有主要的在线游戏专门使用 WebGPU,因为该 API 仍处于开发的早期阶段。然而,一些实验性游戏和演示已经使用 API 创建,展示了高性能基于 Web 图形的潜力。特别感兴趣的一个项目是 Ambient,这是一个由 Rust、WebAssembly 和 WebGPU 提供支持的多人游戏引擎。它刚刚在本月 22 日宣布,他们目前有一段展示演示链接的视频。如果想在不下载 Chrome 的实验版本的情况下查看一些 WebGPU 渲染,参考链接:https://toji.github.io/webgpu-metaballs/

对于想在计算机上使用 WebGPU 的人,需要先从此处下载Chrome Canary 。安装后,在搜索栏中输入 about://flags 并按回车键。然后使用 Unsafe WebGPU 的搜索栏并切换启用,并确保在完成后禁用此功能,因为浏览时可能不安全。

image.png

现在,就可以在机器上运行 WebGPU 了。WebGPU 的一个很酷的例子是由 Brandon Jones 创建的名为WebGPU Meatballs的演示,如下图。

image.png
 

四、WebGPU快速上手

要开始使用 WebGPU,需要一个支持它的浏览器(例如 Chrome 113 或更高版本)和一个具有兼容 GPU 的设备(例如支持 Vulkan 的 Chromebook)。还需要一些 JavaScript 和图形编程的基本知识。

以下是使用 WebGPU 在 canvas 元素上绘制三角形的例子,代码如下:

// 获取 canvas 元素的引用
const canvas = document.getElementById("canvas");
// 从 canvas 获取 WebGPU 上下文
const context = canvas.getContext("webgpu");
// 从上下文中获取默认适配器 (GPU)
const adapter = await context.getAdapter();
// 从适配器获取设备(GPU 的逻辑表示)
const device = await adapter.requestDevice();
// 从上下文中创建交换链(一组用于显示帧的缓冲区)
const swapChainFormat = "bgra8unorm";
const swapChain = context.configureSwapChain({
  device,
  format: swapChainFormat,
});
// 从设备创建着色器模块(着色器代码的容器)
const shaderModule = device.createShaderModule({
  code: `
    // 顶点着色器
    [[stage(vertex)]]
    fn main([[builtin(vertex_index)]] index: u32) -> [[builtin(position)]] vec4<f32> {
      // 定义三角形顶点的位置
      var positions: array<vec2<f32>, 3> = array<vec2<f32>, 3>(
        vec2<f32>(0.0, 0.5),
        vec2<f32>(-0.5, -0.5),
        vec2<f32>(0.5, -0.5),
      );
      // 返回当前顶点的位置
      return vec4<f32>(positions[index], 0.0, 1.0);
    }
    // 片段着色器
    [[stage(fragment)]]
    fn main() -> [[location(0)]] vec4<f32> {
      // 返回三角形的颜色(红色)
      return vec4<f32>(1.0, 0.0, 0.0, 1.0);
    }
  `,
});
// 从设备创建管道(用于渲染的一系列操作)
const pipeline = device.createRenderPipeline({
  // 指定顶点阶段(着色器模块和入口点)
  vertex: {
    module: shaderModule,
    entryPoint: "main",
  },
  // 指定片段阶段(着色器模块和入口点)
  fragment: {
    module: shaderModule,
    entryPoint: "main",
    // 指定输出格式和位置
    targets: [
      {
        format: swapChainFormat,
      },
    ],
  },
  // 指定原始拓扑(顶点如何连接)
  primitive: {
    topology: "triangle-list",
  },
});
// 从设备创建命令编码器(用于记录命令的辅助对象)
const commandEncoder = device.createCommandEncoder();
// 从交换链中获取当前纹理(缓冲区)
const texture = swapChain.getCurrentTexture();
// 从命令编码器创建渲染通道(一组用于渲染的命令)
const renderPass = commandEncoder.beginRenderPass({
  // 指定输出纹理和颜色
  colorAttachments: [
    {
      view: texture.createView(),
      loadValue: [0.5, 0.5, 0.5, 1], // gray
      storeOp: "store",
    },
  ],
});
// 为渲染过程设置 pipeline
renderPass.setPipeline(pipeline);
// 绘制三角形(3 个顶点,1 个实例)
renderPass.draw(3, 1, 0, 0);
// 结束渲染过程
renderPass.endPass();
// 从命令编码器获取命令缓冲区(命令的容器)
const commandBuffer = commandEncoder.finish();
// 将命令缓冲区提交到设备队列(要执行的命令列表)
device.queue.submit([commandBuffer]);
// 请求一个动画帧来渲染下一帧
requestAnimationFrame(render);

 

五、WebGPU资源与工具

5.1 WebGPU学习资源

要构建 WebGPU,需要一些工具和资源来完成开发过程,需要用到的一些工具和资源如下:

 

  • WebGPU 示例:WebGPU 示例和演示的集合,展示了如何使用 WebGPU 的各种功能和技术。可以浏览代码、在线运行示例或将它们下载到本地计算机。这些示例还包括一个 WebGPU 帮助程序库,可以简化一些常见的任务和操作。地址:https://austineng.github.io/webgpu-samples/
  • WebGPU Playground:WebGPU 的在线编辑器和 Playground,可让在浏览器中编写和运行 WebGPU 代码。还可以与其他人共享代码。地址:https://webgpu-playground.netlify.app/
  • WebGPU 文档:WebGPU 的官方文档,解释了 API 的概念、术语和功能。还可以在 WebGPU 上找到指向其他资源和教程的链接。地址:https://gpuweb.github.io/gpuweb/
  • WebGPU 着色语言规范:WGSL 的官方规范,WebGPU 的着色语言,它定义了 WGSL 的语法、语义和特性。还可以找到指向 WGSL 的其他资源和工具的链接。地址:https://gpuweb.github.io/gpuweb/wgsl/
  • WGSL Playground:WGSL 的在线编辑器,可让在浏览器中编写和运行 WGSL 代码。还可以与其他人共享代码。地址:https://timjones.io/wgsl-playground/

使用这些工具和资源,可以了解有关 WebGPU 的更多信息并创建自己的示例和应用。

5.2 WebGPU工具

以下是WebGPU开发中需要用到的一些工具和第三方库:

Babylon.js

一个功能强大且功能丰富的 Web 3D 引擎,支持将 WebGPU 作为渲染后端,官网:https://www.babylonjs.com/。使用示例:

const engine = new BABYLON.WebGPUEngine(canvas);
await engine.initAsync();


const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 3, new BABYLON.Vector3(0, 0, 0), scene);
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter: 2}, scene);
const material = new BABYLON.StandardMaterial("material", scene);
material.diffuseColor = new BABYLON.Color3(1, 0, 0);
sphere.material = material;
engine.runRenderLoop(() => {
    scene.render();
});

Three.js

一个流行的轻量级 Web 3D 库,支持将 WebGPU 作为实验性渲染器。官网:https://threejs.org/,使用示例:

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGPURenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({color: 0x00ff00});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
function animate() {
  requestAnimationFrame(animate);
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  renderer.render(scene, camera);
}
animate();

 

Filament

基于物理的实时渲染引擎,适用于 Android、iOS、Windows、Linux、macOS 和 WebGL/WebGPU,支持高质量图形和光照效果,官网:https://google.github.io/filament/。使用示例:

const engine = Filament.Engine.create(canvas);
const scene = engine.createScene();
const camera = engine.createCamera();
const view = engine.createView();
view.setCamera(camera);
view.setScene(scene);
const skybox = engine.createSkyFromKtx('venetian_crossroads_2k_ibl.ktx');
scene.setSkybox(skybox);
const indirectLight = engine.createIblFromKtx('venetian_crossroads_2k_ibl.ktx');
scene.setIndirectLight(indirectLight);
const material = engine.createMaterial('lit.filamat');
const renderable = Filament.EntityManager.get().create();
scene.addEntity(renderable);
Filament.fetch('DamagedHelmet.glb', (buffer) => {
  const loader = new Filament.gltfio.AssetLoader(engine);
  const asset = loader.createAssetFromBinary(buffer);
  loader.delete();
  asset.getEntities().forEach((entity) => {
    scene.addEntity(entity);
  });
});
function render() {
  requestAnimationFrame(render);
  view.setViewport([0, 0, canvas.width, canvas.height]);
  renderer.render(view);
}
render();

TensorFlow.js

一个用于机器学习的 JavaScript 库,支持 WebGPU 作为加速计算的后端,官网:https://www.tensorflow.org/js/。使用示例:

import * as tf from '@tensorflow/tfjs';
import '@tensorflow/tfjs-backend-webgpu';
await tf.ready();
tf.setBackend('webgpu');
const a = tf.tensor([1, 2, 3, 4]);
const b = tf.tensor([5, 6, 7, 8]);
const c = a.add(b);
c.print();

这些只是使用 WebGPU 的一些示例和项目。随着 WebGPU 得到更广泛的采用和支持们可以期待在未来看到更多使用 WebGPU 的惊人和创新的 Web 应用。

六、总结

实验证明,WebGPU 计算着色器实际上比使用像素着色器的 WebGL 计算快 3.5 倍,同时在要处理的数据量方面具有更高的限制,而且它不会阻塞主线程。WebGPU 为 Web 平台上的高级图形和高性能计算提供了无限可能。尽管目前浏览器支持仍然有限,但 WebGPU 在如今是非常值得探索的,并且在未来只会变得更加强大和广泛支持。Web 作为 3D、可视化、模拟等领域的一个引人注目的选择继续向前发展。
 

参考:

WebGPU 令人兴奋的 Web 发展


xiangzhihong
5.9k 声望15.3k 粉丝

著有《React Native移动开发实战》1,2,3、《Kotlin入门与实战》《Weex跨平台开发实战》、《Flutter跨平台开发与实战》1,2和《Android应用开发实战》