OK, it turns out the answer was on the same page I was reading, but a little bit down further.
The answer is that it's necessary to have a Javascript "glue" code to load .wasm and convert native library calls to the DOM context, but you do not need to write it by hand. People use Emscripten, which includes filesystem emulation, porting to the most popular media libraries like SDL, and it generates both .wasm code and its JS glue counterpart.
From the Mozilla WebAssembly page:
The Emscripten tool is able to take just about any C/C++ source code
and compile it into a .wasm module, plus the necessary JavaScript
"glue" code for loading and running the module, and an HTML document
to display the results of the code.
In a nutshell, the process works as follows:
- Emscripten first feeds the C/C++ into clang+LLVM — a mature open-source C/C++ compiler toolchain, shipped as part of XCode on OSX
for example.
- Emscripten transforms the compiled result of clang+LLVM into a .wasm binary.
- By itself, WebAssembly cannot currently directly access the DOM; it can only call JavaScript, passing in integer and floating point
primitive data types. Thus, to access any Web API, WebAssembly needs
to call out to JavaScript, which then makes the Web API call.
Emscripten therefore creates the HTML and JavaScript glue code needed
to achieve this.
Limitations:
Emscripten only supports fully portable C and C++ code, and you need to enable some optimizations according to their Portability Guidelines.
Also, you need to keep in mind the inherent constraints of the Web platform and JS runtime, so you do not have direct access to the filesystem and you cannot make synchronous (blocking) networking calls, as detailed in API Limitations page.
OpenGL & Vulkan:
For OpenGL, specifically, as the code will eventually translate to a sandboxed WebGL context, you need to limit yourself to what WebGL offers (i.e OpenGL ES 2.0). According to Optimizing WebGL page, Emscripten will convert your code to WebGL 1 by default, with fewer capabilities and unfriendlier syntax, but supported by more platforms. However, you can also target WebGL 2, which offers a nicer API and a couple of hardware optimizations.
For Vulkan, there's currently no native support, but there is an ongoing discussion in W3C for publishing a WebGPU specification. This is their Github page with up-to-date information and the current browser support page.
There is also an experimental WebGPU Rust implementation by Mozilla, so we can already have a glimpse of the future.
UPDATE MAY 2023: Chrome has just released WebGPU