cyberpcangel.com/graphics/cvcgl
cvcGL · WebAssembly examples

Real-time C++ graphics running in your browser, built on the libcvc cvcGL scene graph — hosted by CyberPC Angel.

guest@cyberpcangel:~/cvcgl$ ls examples/ 

cvcGL is libcvc's Qt-free scene graph: a reactive tree of geometry, volume and grid nodes over cvc::state, rendered by VTK. The same C++ example programs that open a desktop window compile, unchanged in any structural way, to WebAssembly — VTK 9.5's Emscripten backend renders into a WebGL2 canvas, and the browser build of each example lives on this site.

Examples

lsystem_forest: a procedural island of L-system trees under a drifting volumetric cloud

lsystem_forest

An island you can fly over: L-system-grown trees swaying in the wind (procedural bark, merged to two actors), a travelling-wave sea and a drifting L-system + fBm cloud volume — both GPU ray-cast — shadow maps, and a quaternion orbit/fly camera. 100% procedural; no assets are downloaded.

run it →
nav_city_swarm: hundreds of coloured vehicles crossing a procedural city under fog

nav_city_swarm

The GRL-SNAM reactive swarm, rendered natively: 800 vehicles cross a varied-height city under fog (grouped belief, 12 planes) with no global plan — goal pyramids that sink on arrival, breadcrumb trails accumulating the street-flow, fleet fog coverage painted on the ground, state-coloured agents (white = escaping, green = arrived) and a live arrivals HUD. The cvc::nav runtime — no Python, no libtorch. Every parameter is live in the on-screen menu — agent count, belief mode, fog, sensor range — and Apply / Restart rebuilds the world so you can watch shared belief beat private belief on the same city. Press 2 for the top-down view.

run it →
nav_fog_ghost: an agent detouring a phantom wall, fog cone and belief grid on the ground

nav_fog_ghost

Fog of war: one vehicle believes a phantom wall its stale map shows but reality lacks. The ghost stands as a translucent amber 3-D wall that erodes cell by cell as the sensor clears it; the ground paints honest epistemics (never-seen black, remembered dim, in-view lit, belief as an LED grid), a blue plan line bows around the phantom vs the yellow driven trail, and a caption arc narrates the detour, the discovery, and the payoff. The menu switches between three limited-belief scenarios — ghost (a stale map lies), dynamic (the world changes after the plan is made) and traffic (other vehicles the map never had) — and restarts the run in place.

run it →

Controls, menus and phones

Every demo above carries a real UI, not a text overlay. It is Dear ImGui composited into VTK's own framebuffer by cvc::gl::ImGuiOverlay, with widgets (cvc::gl::ui) bound straight to cvc::state paths — so a slider, a script and a replicated peer all write the same state node, and the menus work identically native and in the browser.

How these builds work

Each example is a single self-contained .wasm (plus a small JS loader) produced by emcmake from the normal libcvc CMake tree:

Porting notes (what WebGL2 actually required)

The port needed three real fixes, all upstreamed to the libcvc / libcvc-deps trees; details in the PRs:

IssueFix
Under GLES3, VTK swaps in a different polydata mapper whose lighting normal is normalizedNormalVCVSOutput; custom //VTK::Normal::Impl shader replacements that assign the desktop name write to an in varying — an ESSL error that NVIDIA's desktop compiler silently tolerates. The example selects the mapper variant's writable normal at compile time; desktop GLSL is unchanged.
VTK's volume ray-cast shader composer emits mat4 globals initialized from uniforms — illegal in ESSL 3.00, killing every shaded/scattering volume (the sea and the clouds). A small VTK patch moves the assignments into an init helper called at the top of the ray-cast setup.
Boost refuses to compile without -pthread, but a single-threaded wasm build must not use it. Build against Emscripten's single-threaded pthread stubs (BOOST_HAS_PTHREADS), skip the scene's publisher thread, and drain its queue from the frame loop.

Build it yourself

# toolchain + wasm deps straight from the cvcpkg catalog
cvcpkg install emsdk --platform linux --prefix ./emsdk
cvcpkg install boost zstd cgal --platform wasm --arch wasm32 --link static --prefix ./deps-wasm
# vtk needs the rendering-enabled wasm build (libcvc-deps: recipes/vtk, >= 9.5.0+cvc.3)
cvcpkg build vtk --platform wasm --local --prefix ./deps-wasm

# then, from the libcvc repo root:
CVC_EMSDK_DIR=$PWD/emsdk CVC_WASM_DEPS=$PWD/deps-wasm \
  ./src/cvcGL/examples/wasm/build-wasm-demo.sh
python3 -m http.server -d build-wasm/bin 8811

Or, once the bundles are published, as a package:

cvcpkg install cvcgl-examples --prefix ./deps
cvcpkg install cvcgl-examples --platform wasm --arch wasm32 --link static --prefix ./deps
./deps/bin/cvcgl-examples-web   # serves the demo and opens your browser