v0.7.0: SDL-free wasm worker backend (WebGPU + WebGL2) with on-demand assets

The engine now runs on a plain Web Worker (no SDL, no PROXY_TO_PTHREAD: in a pthread Emscripten proxies every filesystem syscall to the main browser thread, where synchronous XHR - and thus FS.createLazyFile - is forbidden). A page/worker pair transfers an OffscreenCanvas and forwards DOM input; assets load lazily from an embedded manifest, so entering a map fetches only that map and its tiles.

Presentation: ra3.webgpu (WebGPU via Emscripten's emdawnwebgpu port, WGSL shaders, the default on wasm) and ra3.wasmgl (WebGL2, GLSL ES). The legacy SDL ra3.webgl backend is removed.
This commit is contained in:
EnderTheCoder
2026-09-29 12:08:07 +08:00
parent 70d4beca4f
commit 889ce945f2
27 changed files with 2161 additions and 639 deletions
+37 -10
View File
@@ -63,8 +63,8 @@ umbrella module re-exports the SDK; applications import `ra3` only.
| \ v
| ra3.display (backend pick)
| / | \ \
v ra3.ui ra3.vulkan ra3.dx ra3.webgl
| (SDL3) (Vulkan) (D3D11/12) (WebGL2)
v ra3.ui ra3.vulkan ra3.dx ra3.webgpu / ra3.wasmgl
| (SDL3) (Vulkan) (D3D11/12) (wasm workers)
---------------------------------------------------------------------------
v
L2 simulation ra3.logic ra3.modules ra3.combat ra3.movement
@@ -80,7 +80,7 @@ umbrella module re-exports the SDK; applications import `ra3` only.
The current concrete modules (`ra3.core`, `ra3.logic`, `ra3.data`,
`ra3.skirmish`, `ra3.fs`, `ra3.map`, `ra3.terrain`, `ra3.render`, `ra3.ui.*`,
`ra3.vulkan.*`, `ra3.dx.*`, `ra3.webgl.*`, `ra3.display`, `ra3.game`, `ra3.client`, and the
`ra3.vulkan.*`, `ra3.dx.*`, `ra3.webgpu.*`, `ra3.wasmgl.*`, `ra3.display`, `ra3.game`, `ra3.client`, and the
vendored `ender.log`) are the **seeds** of the
target modules below. `ra3.skirmish` and `ra3.game` will be absorbed into
`ra3.ai` / `ra3.match`; new modules are added as their subsystems are recovered.
@@ -595,17 +595,44 @@ Mirrors SAGE `GameEngine/Common`. Everything else speaks this.
- **F5 Null fallback** `[D]`
- `[x]` non-Windows builds link a stub that fails `init`
### M18c `ra3.webgl` — WebGL backend `[P]`
### M18d `ra3.wasmgl` — SDL-free wasm worker backend `[P]`
- **F1 Device & canvas** `[D]`
- `[x]` Emscripten-only; SDL3 canvas + GLES 3.0 (WebGL2) via `-sUSE_SDL=3`
- `[x]` Emscripten-only; engine runs on a plain Web Worker, WebGL2 on an
OffscreenCanvas transferred by the page (no SDL, no `PROXY_TO_PTHREAD`)
- `[x]` `specialHTMLTargets['#canvas']` lets `emscripten_webgl_create_context` find
the worker's OffscreenCanvas
- **F2 2D image path** `[D]`
- `[x]` BGRA texture + fullscreen triangle (GLSL ES 300), `.bgra` swizzle
- `[x]` GLSL ES BGRA texture + fullscreen triangle (`.bgra` swizzle)
- **F3 Terrain presentation** `[D]`
- `[x]` GPU heightfield raymarch (GLSL ES port of `terrain.frag`)
- **F4 Wasm packaging** `[~]`
- `[x]` `openra3.html/.js/.wasm`, assets preloaded into the FS at `/assets`
- `[ ]` async/fetch streaming assets instead of a single preload blob `(v0.6)`
- `[x]` GPU heightfield raymarch (GLSL ES), including the `GL_R16`
(`0x822A`) heightmap and `GL_RGBA16` cell textures
- **F4 On-demand assets** `[D]`
- `[x]` `assets.manifest.json` (from `scripts/make_web_manifest.py`) is embedded;
the worker registers every file with `FS.createLazyFile`, so only opened files
are fetched (a map pulls just its map + tiles)
- **F5 Input** `[D]`
- `[x]` page owns DOM listeners and posts events to the worker's exported
`openra3_*` functions (no DOM callbacks in the worker)
- **F6 Null fallback** `[D]`
- `[x]` non-Emscripten builds link a stub that fails `init`
### M18e `ra3.webgpu` — WebGPU wasm backend `[P]`
- **F1 Device & surface** `[D]`
- `[x]` Emscripten `emdawnwebgpu` port (Dawn C++ wrapper); the worker pre-creates
the device (`Module.preinitializedWebGPUDevice`) and a surface is configured on
the transferred OffscreenCanvas
- **F2 WGSL shaders** `[D]`
- `[x]` web WebGPU is WGSL-only, so the scene/terrain shaders are WGSL ports
(the Vulkan SPIR-V blobs cannot be reused); the uniform layout and terrain data
plumbing are shared with Vulkan/WebGL
- **F3 Terrain** `[D]`
- `[x]` GPU heightfield raymarch in WGSL (R16Uint heightmap, RGBA16Uint cell
record, RGBA8 atlas)
- **F4 Selection & fallback** `[D]`
- `[x]` preferred wasm backend; falls back to `ra3.wasmgl` when no adapter is
available
- **F5 Null fallback** `[D]`
- `[x]` non-Emscripten builds link a stub that fails `init`