wander
is a GPU-based rendering framework designed to be fully embeddable in any application.
Use wander
to run renderlets
in any software - self contained, portable modules of graphics data and code compiled to WebAssembly.
Let's discuss the intersection of Wasm and Graphics!
With renderlet, developers can build modern, interactive visualizations that run on any platform.
Many visual apps need a high-performance rendering engine that works in a browser or in a native app, where a JavaScript library won't scale, but a game engine is not the right application model.
wander
is designed to be a rendering engine for any high-performance application. It primarily is designed as the runtime to run renderlet
bundles, but also can be used more generically as a WebAssembly-based rendering engine that uses the GPU.
The wander
SDK brings all of the benefits of renderlets
into your own application:
- High performance 2D and 3D graphics
- Fully portable rendering pipelines
- Any app, device, client, or server
- Sandboxed third party code execution
- Self contained rendering modules
- Reuse your graphics code as building blocks
- No game engine / platform dependencies
- No GPU expertise required
Use wander
to build things like:
- Modern CAD Apps: Use code to allow objects to describe how to render themselves
- Procedural Modeling and DataViz: Execute runtime code to view your data in new ways
- Product Visualization: Interact with dynamic objects in 3D on any device
- Composable User Interfaces: Render any UI module on top of an existing canvas or in any scene
- Interactive Animations: Like Adobe Flash, but with an actual programming language and GPUs
- Low/No-Code Graphics: Make a graphics pipelines out of existing building blocks
API | Windows | Linux/Android | macOS/iOS | Web (wasm) |
---|---|---|---|---|
OpenGL | ✅ (GL 3.3) | 🛠️ (GL ES 3.0+) | ✅ | 📐 (WebGL2) |
DX11 | ✅ | |||
DX12 | 🛠️ | |||
WebGPU | 🛠️ | |||
Vulkan | 📐 | 📐 | 📐 | |
Metal | 📐 |
✅ = Currently supported 🛠️ = In progress, coming soon 📐 = In design or planned for the future
wander
is delivered as a cross-platform C++ library. Simply add wander.h/wander.cpp to your build chain along with the included dependencies such as wasmtime
.
The basic API flow is:
const auto pal = wander::Factory::CreatePal(
wander::EPalType::D3D11, baseDevice, baseDeviceContext);
auto runtime = wander::Factory::CreateRuntime(pal);
auto renderlet_id = runtime->LoadFromFile(L"Building.wasm", "run");
auto tree_id = runtime->Render(renderlet_id);
auto tree = runtime->GetRenderTree(tree_id);
- Create a PAL object based on your device's underlying GPU API
- Create a global
runtime
object. This is not currently thread safe - Load a
renderlet
file (with an optional entry point name) and get it ready to run - Run it! For static content this can be done once, but dynamic content could be per frame
- Get a (non-owning) pointer to the output
Drawing the data is as simple as iterating the render tree:
deviceContext->PSSetShaderResources(0, 1, &textureViewWhite);
for (auto i = 0; i < tree->Length(); ++i)
{
tree->NodeAt(i)->RenderFixedStride(runtime, stride);
}
There's no need to manage the underlying graphics data / buffers - wander
takes care of it.
To delete/free old content, simple call:
runtime->DestroyRenderTree(tree_id);
Also, wander can tear down every object automatically on unload or close:
runtime->Release();
Examples are provided in the examples folder for D3D11 and OpenGL 3.3 (Mac/Windows/Linux).
CMake support is not yet implmented, but you can follow platform-specific examples below to integrate into your own app.
wander
has experimental support for 2D vector operations using rive-renderer
Currently this is only supported in the Windows / Direct3D11 backend. We are working on a WebGPU
build, and MacOS will require us to implement a Metal
backend.
It is non-trivial to build rive-renderer
on Windows. We have provided a GitHub release with precompiled binaries / .lib files in the D3D11 example. If you want to build yourself, here's some tips:
- Ensure you have a
MinGW
toolchain installed - Clone this repo with
--recurvsive
-rive-renderer
will be subbomduled inlibs
, and will haverive-cpp
submoduled inlibs/rive-renderer/submodules/rive-cpp
- Follow the basic instructions using
MinGW
for commands in theREADME
forrive-renderer
- You may manually have to run CMake for glfw:
cmake ../glfw -DBUILD_SHARED_LIBS=OFF -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DGLFW_BUILD_WAYLAND=OFF -A x64
- For premake,
set PREMAKE_PATH=<path>wander\libs\rive-renderer\submodules\rive-cpp\build
- Then,
premake5 vs2022 --toolset=msc --with_rive_text --config=release --out=out/release
(or debug) - Open the output
rive.sln
, and switch every project toMD
/MDd
to match most apps - For
path_fiddle
, upgrade to C++20 and on linker and C++ settings disable warnings as errors (/WX-
) - Now build all in Visual Studio or via MSBuild - the DX11 example will automatically pull from the submodule paths
To use this, RLT_RIVE
globally in your project (the DX11 example does this automatically in the Release build), and wander
will automatically link to the output .lib
s.
You can read more about the rive-renderer
integration here.
Ensure you have the latest Visual Studio 2022 and Windows 11 SDK, and use the Examples.sln
.
The DX11 example includes experimental rive-renderer
support for 2D vectors.
Ensure you have a working clang
installation, then simply use the Makefile
:
make run
This should produce a new opengl
binary under /src/examples/OpenGL
and run it with the default scene.
First, build the build container. From the repository root:
podman build -t wander/buildimage -f ./Dockerfile
Then, use this container to build or rebuild the examples. To build the OpenGL example on Linux:
podman run --mount=type=bind,source="$(pwd)",target=/src,relabel=shared,U=true -w /src/examples/OpenGL wander/buildimage make buildlinux
This should produce a new opengl
binary under /src/examples/OpenGL
. Take a look at the Makefile
for more info.
An example renderlet
is provided in the examples - a 3D procedural model of a building - building.wasm
.
We are currently working on a compiler and tool to make it easy to build your own renderlets.
If you want to experiment with building your own through raw wasm code, the wire format and signatures can be found here.
This format can and will change over time, so please only experiment with this if you are ok with breaking your renderlet on upgrade!
Feature | Supported | Coming Soon | Future |
---|---|---|---|
Untyped buffers | ✅ | ||
Vertex buffers | ✅ | ||
Geometry/Mesh support | ✅ | ||
Materials | ✅ (*) | ||
Index buffers | 🛠️ | ||
Texture data | 🛠️ | ||
CMake / x-platform build | 🛠️ | ||
C API / other langs | 🛠️ | ||
Buffer format specs | 📐 | ||
Dynamic render trees | 📐 | ||
Conditional rendering | 📐 | ||
Shaders | 📐 | ||
Distributed GPU compute | 📐 | ||
Web build | 🛠️ | ||
Renderlet compiler toolset (easily build your own renderlets) |
🛠️ (*) |
*unstable API
Feature requests welcome, please submit an issue!
Current (V1) architecture allows arbitray data to be generated on the CPU in Wasm which is automatically uploaded to the GPU via the wander
SDK through the PAL.
The host app must know the "shape" of the data and bind a shader stage to the host graphics API to render the geometry / texture data to the Canvas.
Example - CAD, where arbitrary parts can generate geometry of a known format that the host app has the capability to shade
Future (V2) architecture allows arbitrary data to be fully rendered to an application's back buffer / canvas via an attachment to the graphics API exposed to Wasm.
V2 will enable fully arbitrary rendering of any data onto any Canvas. V2 has a dependency on the upcoming wasi-gpu
spec.
Example - Full 3rd-party UGC/Content - Rendering arbitrary 2D gauges (like Flash) / 3D content (avatars) onto an existing Canvas layer in an app