WebAssembly 应用程序如何将其原生 Window / OpenGL / Vulkan 调用映射到 DOM 中的画布元素?

Raf*_*kel 6 javascript c sdl emscripten webassembly

我正在阅读有关 WebAssembly 的文章,我很好奇如何将 Vulkan 或 OpenGL 等图形编程移植到画布元素。文档很长,我想我最终会解决这个问题,但我很好奇,并没有在现场找到答案。

到目前为止,我知道它可以将函数导出到 JS,而 JS 会像往常一样做操作 DOM 的肮脏工作。

我可以直接编写 WebGL,但这不是我的观点。我见过移植到 WebAssembly 的游戏,我想知道它是如何工作的。如果 WebAssembly 无法直接访问 DOM,它如何呈现任何内容?通常,图形应用程序使用外部窗口管理器(如GLFWSDL)来创建窗口上下文来绘制您的内容。

如果我确实使用这样的库编译了一个程序,并期望一个带有一些 Window 对象的环境启动,如果 DOM 中没有这样的概念,这些指令将如何映射到画布?我需要以某种方式调整我的 C++ 程序吗?

Raf*_*kel 6

好吧,原来答案在我正在阅读的同一页上,但稍微向下一点。

答案是需要有一个 Javascript “胶水”代码来加载 .wasm 并将本机库调用转换为 DOM 上下文,但您不需要手动编写它。人们使用Emscripten,它包括文件系统模拟,移植到最流行的媒体库,如 ​​SDL,它生成 .wasm 代码和它的 JS 胶水对应物。

Mozilla WebAssembly 页面

Emscripten 工具能够获取几乎任何 C/C++ 源代码并将其编译为 .wasm 模块,以及用于加载和运行模块所需的 JavaScript“胶水”代码,以及用于显示代码结果的 HTML 文档.

简而言之,该过程的工作原理如下:

  1. Emscripten 首先将 C/C++ 提供给 clang+LLVM——一个成熟的开源 C/C++ 编译器工具链,作为 XCode 的一部分在 OSX 上发布。
  2. Emscripten 将 clang+LLVM 的编译结果转换为 .wasm 二进制文件。
  3. WebAssembly 本身目前无法直接访问 DOM;它只能调用 JavaScript,传入整数和浮点原始数据类型。因此,要访问任何 Web API,WebAssembly 需要调用 JavaScript,然后由 JavaScript 调用 Web API。因此,Emscripten 创建了实现这一目标所需的 HTML 和 JavaScript 粘合代码。

限制:

Emscripten 仅支持完全可移植的C 和 C++ 代码,您需要根据其Portability Guidelines启用一些优化。

此外,您需要牢记 Web 平台和 JS 运行时的固有约束,因此您不能直接访问文件系统,也不能进行同步(阻塞)网络调用,如API 限制页面中所述。

OpenGL 和 Vulkan:

对于 OpenGL,特别是,由于代码最终将转换为沙盒 WebGL 上下文,因此您需要将自己限制在 WebGL 提供的内容(即 OpenGL ES 2.0)上。根据优化 WebGL页面,Emscripten 将默认将您的代码转换为WebGL 1,具有较少的功能和不友好的语法,但支持更多平台。但是,您也可以针对 WebGL 2,它提供了更好的 API 和一些硬件优化。

对于 Vulkan,目前没有原生支持,但 W3C 正在讨论发布WebGPU规范。这是他们的 Github 页面,其中包含最新信息和当前浏览器支持页面。

Mozilla还有一个实验性的WebGPU Rust 实现,所以我们已经可以一瞥未来。