scenix
Modular Rust-native 3D scenes for native and WASM apps.
scenix 1.9.1 is the current stable release. It ships the XR, audio, and
physics bridges — scenix-xr (session plans, controller bays, 26-slot hand
frames, anchors, planes, hit testing, light estimation), scenix-audio
(spatial mixing with Doppler, streamed buffer health, spectrum analysis),
and scenix-physics (a deterministic penalty-based rigid-body solver with
sensors, spatial queries, sleeping, and a jump-capable character
controller) — wired through the scene schema, camera stereo math, debug
helpers, a WebXR fallback plan, and facade feature flags. v1.8.0's
environment crates (terrain, sky, water) keep their GPU draw path,
v1.7.0's deterministic CPU particle systems keep their billboard GPU path,
v1.6.0's typed shader graphs, node materials, and post-node effect language
remain the shading backbone, and v1.5.0's cross-platform controls, input
stack, selection/transform primitives, reusable gizmos, inspector snapshots,
optional egui rendering, and on-demand GPU picking remain the interaction
backbone. CPU authoring stays lightweight by default while GPU, browser, and
UI paths remain opt-in. The 1.9.1 patch picks up Animato 1.7.3, whose
facade is now no_std-capable, so the animato bridge compiles for
bare-metal targets (release notes).
Install
Most applications start with the facade crate:
[]
= "1"
Enable optional systems only when needed:
[]
= { = "1", = ["loader"] }
= { = "1", = ["renderer", "post"] }
= { = "1", = ["animato"] }
= { = "1", = ["nodes"] }
= { = "1", = ["environment"] }
= { = "1", = ["bridges"] }
= { = "1", = ["xr"] }
= { = "1", = ["audio"] }
= { = "1", = ["physics"] }
= { = "1", = ["wasm"] }
= { = "1", = ["interaction"] }
= { = "1", = ["editor", "egui"] }
Focused crates can be used directly:
[]
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
= "1"
For no_std CPU authoring:
[]
= { = "1", = false, = ["libm"] }
= { = "1", = false }
= { = "1", = false }
= { = "1", = false }
= { = "1", = false }
= { = "1", = false }
= { = "1", = false }
= { = "1", = false }
= { = "1", = false }
= { = "1", = false }
= { = "1", = false }
= { = "1", = false }
= { = "1", = false }
scenix-loader, scenix-renderer, scenix-post, scenix-animato, and
scenix-wasm are optional std paths. scenix-animato targets Animato
1.7.3. scenix-nodes is a no_std-capable CPU crate; its renderer, post
stack, and browser preflight integrations are std/wasm32 features of their
host crates.
Feature Flags
| Feature | Default | Description |
|---|---|---|
std |
yes | Standard-library support for CPU crates. |
scene, camera, mesh, material, light, texture |
yes | CPU authoring crates. |
raycaster, helpers |
yes | BVH picking and debug line helper data. |
interaction |
no | Convenience bundle for scene, camera, raycaster, and helpers. |
editor |
no | Inspector snapshots and editor-facing selection/transform data. |
egui |
no | Read-only egui inspector adapter; the host owns its window/render loop. |
loader |
no | Asset packages, asset manager, glTF/GLB extension metadata, OBJ/MTL, STL, image, KTX2, HDR/EXR loading, and exporters. |
renderer |
no | wgpu renderer with surface/headless targets. |
post |
no | Full-screen post-processing stack; use with renderer. |
nodes |
no | Typed shader graphs, node materials, and post node effects with WGSL/GLSL backends under the scenix-nodes crate; enables node-material rendering in renderer and browser preflight in wasm when those features are on. |
particles |
no | Deterministic CPU particle systems under the scenix-particles crate; enables the billboard GPU path (with optional compute simulation) in renderer and browser fallback plans in wasm when those features are on. |
terrain |
no | Heightfields, chunked LOD geometry, splat maps, ray colliders, and chunk streaming under the scenix-terrain crate. |
sky |
no | Procedural sky profiles, sun positions, baked environment maps, and grounded skyboxes under the scenix-sky crate. |
water |
no | Gerstner wave fields, displaced surface meshes, foam/fresnel/underwater math, and mirror helpers under the scenix-water crate. |
environment |
no | Bundles terrain, sky, and water; enables the environment WGSL pipelines (terrain splats, sky dome, water surface) in renderer when that feature is on. |
animato |
no | Animato bridge: procedural tween/spring tracks and the clip-based Animation Runtime (clips, actions, mixer, loop modes, crossfade, additive blending, markers/events, light/morph targets, retargeting, CPU skinning). Targets Animato 1.7.3. |
wasm |
no | Browser canvas wrapper with WebGPU first, WebGL2 full fallback, WebGL1 reduced fallback, and generated demo scene. |
serde |
no | Serialization support where the focused crate supports it. |
Quick Start
Controls and interaction
use ;
let mut input = new;
input.on_pointer_down;
input.on_pointer_move;
input.on_scroll;
let mut controls = new;
let mut camera = default;
controls.update_from_input;
controls.apply_to_perspective;
input.end_frame;
InputState also accepts fixed-capacity touch contacts, two-finger gestures,
four standard gamepads, and pointer-lock relative motion without allocating in
the event/control hot path.
Scene authoring and animation
use BTreeMap;
use ;
#
Headless Rendering
use ;
# async
Loading Assets
use ;
# async
Animation Runtime
The v1.4.0 AnimationMixer plays clip-based animation on top of Animato:
use ;
let mut scene = new;
let node = scene.add;
let clip = empty.with_channel;
let mut mixer = new;
let clip_index = mixer.add_clip;
let action = mixer.add_action;
mixer.action_mut.unwrap.set_loop_mode;
mixer.action_mut.unwrap.play;
// each frame:
// mixer.tick(dt, &mut scene, &mut cameras, &mut materials,
// &mut lights, &mut skeletons, &mut morphs)
Shader nodes and node materials
v1.6.0 adds the optional scenix-nodes crate. Describe shading as a typed
graph, validate it without a GPU, and generate WGSL (renderer contract) or
GLSL ES 3.00 (WebGL tooling) from the same graph:
use ;
// Base color pulses over time, then feeds a Lambert lighting term.
let mut graph = new;
let base = graph.push;
let time = graph.push;
let pulse = graph.add;
let lit = graph.chain;
graph.add_fragment_output;
let material = new;
assert!;
assert!;
let wgsl = generate_material_wgsl.unwrap;
// wgsl.source() matches the renderer bind contract:
// group 0 frame, group 1 object, group 2 material, group 3 lights.
With the renderer feature, Renderer::register_node_material(id, &material)
shades draws through the generated module; graphs that cannot resolve carry a
specific NodeDiagnostic instead of crashing. With the wasm feature,
scenix_wasm::compile_node_material_glsl(json) runs the same preflight in the
browser before anything is uploaded.
Particles
use ;
let emitter = new
.with_rate
.with_lifetime
.with_size
.with_speed
.at
.toward
.with_shape
.with_modifier
.with_modifier
.with_modifier
.with_modifier;
// One deterministic CPU system drives the entire loop.
let mut system = new;
let batch = system.update;
assert!;
// With `renderer` + `particles`, `Renderer::register_particles` +
// `Renderer::update_particles` draw the batch as camera-facing billboards;
// `register_particle_compute` moves the whole simulation onto the GPU.
Raycasting
use BTreeMap;
use ;
let mesh_id = new;
let material_id = new;
let meshes = from;
let mut scene = new;
scene.add;
scene.update_world_transforms;
let camera = new
.position
.target;
let ray = from_camera_ndc;
let mut raycaster = new;
raycaster.build_bvh.unwrap;
assert!;
Workspace
| Crate | Role |
|---|---|
scenix |
Facade crate with stable v1 feature flags. |
scenix-math |
no_std vectors, matrices, quaternions, transforms, rays, and bounds. |
scenix-core |
IDs, colors, errors, and shared traits. |
scenix-input |
Pointer, keyboard, touch, gesture, gamepad, pointer-lock, and viewport state. |
scenix-scene |
Scene graph plus editor metadata, layers, snapping, and selection state. |
scenix-camera |
Cameras plus orbit, fly, arcball, trackball, map, first-person, and pointer-lock controls. |
scenix-mesh |
Geometry buffers, primitives, instancing, batching, and morph targets. |
scenix-material |
GPU-free material descriptions and pipeline keys. |
scenix-nodes |
Optional typed shader graphs, node materials, and post node effects with WGSL/GLSL codegen. |
scenix-particles |
Optional deterministic CPU particle systems with emitter/curve modules and GPU billboard/compute integration. |
scenix-terrain |
Optional CPU heightfields, chunked LOD geometry, splat maps, ray colliders, and chunk streaming. |
scenix-sky |
Optional procedural sky profiles, sun positions, baked environment maps, and grounded skyboxes. |
scenix-water |
Optional Gerstner wave fields, displaced surface meshes, foam/fresnel/underwater math, and mirror helpers. |
scenix-light |
Lights, shadow settings, and light probes. |
scenix-texture |
CPU textures, samplers, atlases, video updates, and mipmaps. |
scenix-loader |
Optional CPU asset packages, asset manager, importers, exporters, diagnostics, and cache. |
scenix-renderer |
Optional wgpu renderer with on-demand ID/normal/depth editor picking. |
scenix-post |
Optional wgpu post-processing effects. |
scenix-raycaster |
BVH ray picking, marquee selection, drag planes, and transform interactions. |
scenix-helpers |
Debug lines, reusable gizmos, selection visuals, snap grids, and optional egui. |
scenix-animato |
Optional Animato bridge. |
scenix-wasm |
Optional browser canvas wrapper with WebGPU and WebGL paths. |
Examples
The facade crate registers the example set from ARCHITECTURE.md:
The browser example lives in examples/wasm_viewer:
Website
The static website is a standalone Leptos CSR app in website/. It is intentionally outside the main workspace so website dependencies do not affect normal library users.
GitHub Pages deployment is handled by .github/workflows/pages.yml, which builds website/dist with Trunk and deploys it at /scenix/. The demo uses scenix-wasm: it tries WebGPU where safe, falls back to a WebGL2 renderer with the same generated scene/material/light controls when WebGPU is unavailable, uses reduced WebGL1 only as a last GPU path, and only uses the Canvas2D preview when both GPU paths are unavailable.
Development Checks
SCENIX_RUN_GPU_TESTS=1 WGPU_BACKEND=vulkan
SCENIX_RUN_GPU_TESTS=1 WGPU_BACKEND=vulkan
RUSTDOCFLAGS="-D warnings"
Documentation
- Developer docs
- Architecture
- Roadmap
- Changelog
- Getting started
- Installation
- Quick start
- Concepts
- Guides
- API reference
- Examples
- Recipes
- Performance
- Deployment
- Migration
- Reference
- v1.9.1 release notes
- v1.9.0 release notes
- v1.8.0 release notes
- v1.7.0 release notes
- v1.6.0 release notes
- v1.5.0 release notes
- v1.4.0 release notes
- v1.3.0 release notes
Known Limitations
- The renderer now uploads material textures, light data, environment descriptors, and render targets through real GPU resources. Advanced physical shading is a pragmatic realtime path, not an offline film renderer.
- Loader APIs produce CPU-side scenix data;
RendererAssetExtis a convenience bridge that still uploads into renderer-owned GPU resources explicitly. - Draco and meshopt compressed glTF assets currently produce explicit diagnostics unless preprocessed by an external converter.
- WebGL2 is the full browser fallback for the generated renderer scene when WebGPU is unavailable. WebGL1 remains a reduced last-resort fallback for older browsers.
- The website demo does not vendor large model assets.
- GPU tests require a Vulkan-capable device or Mesa lavapipe.
License
Licensed under either of:
- Apache License, Version 2.0
- MIT license