web: scaffold IfcViewerWeb (Emscripten clear-color renderer)

First Emscripten target. main_web.cpp brings up a wgpu instance against
a <canvas id="viewer-canvas">, requests adapter+device asynchronously
via the standard webgpu.h callback chain, configures the surface, and
clears to the BonsaiViewer slate background on each RAF tick. No
sidecar load, no pipelines, no scene state yet — the goal is to end-
to-end verify the build + canvas + wgpu plumbing.

src/ifcviewer-web/ is a separate CMake root (not a subdir under the
desktop cmake/CMakeLists.txt) so the web build doesn't have to opt out
of Qt / OpenCASCADE / IfcGeom find_packages it can't satisfy. It adds
src/ifcviewer EXCLUDE_FROM_ALL and consumes only IfcViewerCore.

src/ifcviewer/CMakeLists.txt now gates the wgpu-native fetch + the
Qt-using IfcViewer target + install commands behind NOT EMSCRIPTEN.
The wgpu_native link target still resolves under Emscripten as an
INTERFACE library that activates --use-port=emdawnwebgpu (Dawn's
webgpu.h, replaces the legacy -sUSE_WEBGPU=1).

Build:
    source path/to/emsdk_env.sh
    emcmake cmake -S src/ifcviewer-web -B build-web -G Ninja
    ninja -C build-web
    python3 -m http.server --directory build-web 8080
    # open http://localhost:8080/IfcViewerWeb.html in a WebGPU-capable
    # browser (Chrome 113+, Edge 113+).

Phase B step 3 of #45.
This commit is contained in:
Dion Moult
2026-06-04 18:58:34 +10:00
parent c098146c35
commit e55a360aa2
4 changed files with 375 additions and 5 deletions
+49
View File
@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>IfcViewer (web)</title>
<style>
html, body { margin: 0; height: 100%; background: #0f1117; color: #c8ccd6;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
#viewer-canvas { display: block; width: 100vw; height: 100vh; outline: none;
background: #1a1d24; }
#status { position: fixed; top: 8px; left: 12px; font-size: 12px;
background: rgba(20,22,28,.72); padding: 4px 8px; border-radius: 4px;
pointer-events: none; }
#status.error { background: rgba(120,30,30,.85); color: #fff; }
</style>
</head>
<body>
<canvas id="viewer-canvas" width="1280" height="800"></canvas>
<div id="status">Starting…</div>
<script>
// Emscripten Module hook: route stderr to the status overlay so any
// wgpu init failure (no WebGPU, canvas missing, etc.) is visible
// without opening devtools.
var statusEl = document.getElementById('status');
var Module = {
canvas: document.getElementById('viewer-canvas'),
print: function(t) { console.log(t); },
printErr: function(t) {
console.warn(t);
// First non-empty stderr line replaces the "Starting…" tag; subsequent
// lines append. Anything containing "fail" / "error" flips us into
// the red error chip.
statusEl.textContent = t;
if (/fail|error|null/i.test(t)) statusEl.classList.add('error');
},
onRuntimeInitialized: function() {
statusEl.textContent = 'wasm loaded — waiting for WebGPU';
}
};
if (!navigator.gpu) {
statusEl.textContent = 'navigator.gpu is missing — open in a browser with WebGPU enabled';
statusEl.classList.add('error');
}
</script>
<!-- IfcViewerWeb.js is emitted alongside this shell by the emcc build;
`--shell-file` injects this HTML around it. -->
{{{ SCRIPT }}}
</body>
</html>