v0.6.0: WebAssembly build with a WebGL backend (playable in the browser)
- ra3.webgl: a Web peer of Vulkan/Direct3D (SDL3 canvas + GLES3/WebGL2), with 2D blit and the GPU terrain raymarch; GLSL ES shaders; null fallback off Emscripten. backend::webgl + default_backend() (webgl under Emscripten). - Emscripten toolchain + Dockerfile.wasm + scripts/build-wasm.sh; import std, global -fexceptions, and Asyncify so the blocking frame loop yields to the browser (display::sleep_frame calls emscripten_sleep). - apps/web/shell.html + apps/web/serve.py (Range-capable dev server). - Assets: browsers forbid synchronous on-demand reads on the main thread (and FS.createLazyFile / the WasmFS fetch backend are worker-only; SDL3's Emscripten backend is main-thread DOM only, so the engine cannot run in a worker). The wasm build therefore preloads a compact per-map set via OPENRA3_WEB_ASSETS. - New openra3 textures --map ID lists the loose terrain TGAs a map resolves to (terrain::resolve_texture_files, shared with load_textures_from_dir). - Fixes: webgl heightmap used GL_R16 = 0x8229 (that is R8) -> upload rejected, terrain flattened to water; now 0x822A. Logger uses a stdout console sink on the web (stderr maps to console.error); a GL error check logs bad uploads. - CI: wasm image + build jobs.
This commit is contained in:
@@ -18,16 +18,16 @@ Ghidra.
|
||||
|
||||
## Status
|
||||
|
||||
OpenRA3 is at **v0.5.0**. The engine compiles and runs headless, and a **minimal
|
||||
OpenRA3 is at **v0.6.0**. The engine compiles and runs headless, and a **minimal
|
||||
skirmish** is playable: it reads a real multiplayer map out of your install,
|
||||
recovers the player start waypoints, and simulates two sides building a base,
|
||||
extracting ore and fighting until one side is wiped out. The balance is the
|
||||
**retail Red Alert 3 balance**, pinned in `ra3.data` from EA's open RA3 XML:
|
||||
damage types, `ArmorTemplate` percentages, weapon target masks, build costs and
|
||||
the ore economy. Presentation offers **Vulkan** (`ra3.vulkan`) and **Direct3D 11 / 12**
|
||||
(`ra3.dx`) GPU backends with an SDL software blit and null fallbacks; the
|
||||
backend is selectable from the in-game menu and the software renderer still
|
||||
produces headless images. Terrain tiles
|
||||
the ore economy. Presentation offers **Vulkan** (`ra3.vulkan`), **Direct3D 11 / 12**
|
||||
(`ra3.dx`) and **WebGL 2** (`ra3.webgl`, the wasm build) GPU backends with an SDL
|
||||
software blit and null fallbacks; the backend is selectable from the in-game menu
|
||||
and the software renderer still produces headless images. Terrain tiles
|
||||
cross-fade the way the retail `Terrain.fx` does (a per-cell blend ramp plus a
|
||||
gutter-padded atlas), so material boundaries are smooth instead of a grid of
|
||||
hard lines. An in-window **menu** lists the maps by their localized name and
|
||||
@@ -85,7 +85,7 @@ built-in test map so the project still builds and runs in CI.
|
||||
| `src/core/ra3.core.cppm` | fundamental types, math, strings, random, message stream |
|
||||
| `src/logic/ra3.logic.cppm` | objects, players, teams, spatial partition, game loop |
|
||||
| `src/client/ra3.client.cppm` | `display` abstraction + shared interactive loops + client facade |
|
||||
| `src/display/ra3.display.cppm` | picks the backend (Vulkan/D3D11/D3D12, then SDL) for the app |
|
||||
| `src/display/ra3.display.cppm` | picks the backend (Vulkan/D3D11/D3D12/WebGL, then SDL) for the app |
|
||||
| `src/game/ra3.game.cppm` | RA3 sides, player templates, skirmish defaults |
|
||||
| `src/data/ra3.data.cppm` | retail RA3 balance: damage types, armour, weapons, units, economy |
|
||||
| `src/fs/ra3.fs.cppm` | `BIG4` archives, RefPack codec, local install locator |
|
||||
@@ -96,6 +96,7 @@ built-in test map so the project still builds and runs in CI.
|
||||
| `src/ui/ra3.ui.*.cppm` | SDL3 window viewer and menu (null backend when SDL3 is absent) |
|
||||
| `src/vulkan/ra3.vulkan.*.cppm` | Vulkan presentation backend and menu (null fallback without a loader) |
|
||||
| `src/dx/ra3.dx.*.cppm` | Direct3D 11/12 presentation backend (runtime HLSL; null fallback off Windows) |
|
||||
| `src/webgl/ra3.webgl.*.cppm` | WebGL2 presentation backend for the wasm build (GLSL ES; null fallback off Emscripten) |
|
||||
| `third_party/libenderlog/` | vendored C++26 module logger (`import ender.log;`, MIT) with a native stack fallback for libc++ |
|
||||
| `src/ra3.cppm` | umbrella module re-exporting the SDK |
|
||||
| `apps/openra3/main.cpp` | `menu` / `maps` / `skirmish` / `render` CLI |
|
||||
@@ -139,6 +140,9 @@ scripts/build-windows.sh
|
||||
|
||||
# Windows (arm64) -> build/windows-arm64/bin/openra3.exe + SDL3.dll, .zip (cross)
|
||||
scripts/build-windows-arm64.sh
|
||||
|
||||
# WebAssembly -> build/wasm/bin/openra3.html (+ .js/.wasm)
|
||||
scripts/build-wasm.sh
|
||||
```
|
||||
|
||||
Every target is cross-built from x86_64 Linux in its own image: llvm-mingw for
|
||||
@@ -176,6 +180,37 @@ openra3.exe render --game-dir "C:\Red Alert 3" --vulkan
|
||||
Vulkan is provided by **vendored volk + headers** (`third_party/`), resolved at
|
||||
runtime, so neither image needs a Vulkan SDK.
|
||||
|
||||
## WebAssembly
|
||||
|
||||
OpenRA3 also builds to **WebAssembly** with Emscripten (`scripts/build-wasm.sh`),
|
||||
producing `openra3.html` + `.js` + `.wasm`. The browser gets the same GPU renderer
|
||||
as the desktop builds: a **`ra3.webgl`** backend peers with Vulkan/Direct3D — SDL3
|
||||
provides the canvas and input, and GLES 3.0 / WebGL2 runs the 2D blit and the
|
||||
terrain raymarcher (GLSL ES ports of the desktop shaders).
|
||||
|
||||
Browsers forbid synchronous on-demand file reads on the main thread, so the
|
||||
assets are **preloaded into the module's filesystem** at build time. Bundle a
|
||||
compact per-map set (one map plus the tiles it uses) rather than the whole dump:
|
||||
|
||||
```bash
|
||||
# 1. which loose TGAs does the map resolve to?
|
||||
openra3 textures --map map_mp_2_feasel1 # prints paths under assets/terrain
|
||||
|
||||
# 2. stage one map + those tiles (+ maps/map_names.tsv) into a directory, then
|
||||
OPENRA3_WEB_ASSETS=/path/to/that/set scripts/build-wasm.sh
|
||||
|
||||
# 3. serve the build output (a Range-capable server is included)
|
||||
python3 apps/web/serve.py --root build/wasm/bin --port 8199
|
||||
# open http://localhost:8199/openra3.html
|
||||
```
|
||||
|
||||
The engine's frame loops are blocking; the wasm build yields to the browser via
|
||||
Asyncify (`display::sleep_frame` calls `emscripten_sleep`), so the page repaints
|
||||
and handles input. Log records go to `console.log` at their real level (the
|
||||
console sink uses stdout on the web instead of stderr). Without
|
||||
`OPENRA3_WEB_ASSETS` the module still loads and starts, but exits at the menu
|
||||
because no maps are found.
|
||||
|
||||
## Packages
|
||||
|
||||
CPack produces the release artifacts; the Docker images and CI run it for every
|
||||
|
||||
Reference in New Issue
Block a user