Update deprecated rand methods (thread_rng→rng, gen_range→random_range, gen_bool→random_bool). Prefix unused struct fields with underscore (scanner_camera_buffer, color). Allow dead_code on App struct for fields only read in wasm cfg blocks.
wgpu-demo
A minimal 3D tech demo using Rust + wgpu + winit, compiled to WASM via Trunk.
Flat-shaded colorful spheres and octahedra floating in space. WASD + mouse to fly around.
Prerequisites
# Install trunk (WASM bundler)
cargo install trunk
# Add the WASM target
rustup target add wasm32-unknown-unknown
Run in browser (WASM)
trunk serve
Then open http://127.0.0.1:8080 — click to capture the mouse, WASD to move, mouse to look, Space/Shift for up/down, Escape to release cursor.
Run natively (desktop)
cargo run --release
Same controls. Native build uses Vulkan/Metal/DX12 via wgpu.
Deploy
trunk build --release
This produces a dist/ folder you can deploy to any static host (Vercel, Netlify, GitHub Pages, etc).
Project structure
src/
main.rs — Entry point, winit event loop, input handling, WASM bootstrap
renderer.rs — wgpu device/surface/pipeline setup, render loop
camera.rs — FPS camera with mouse look
mesh.rs — Procedural icosphere + octahedron generation (flat-shaded)
scene.rs — Scene population: random placement of colored shapes
shader.wgsl — Vertex + fragment shader with directional + specular lighting
Notes
- The renderer writes per-object model transforms via
queue.write_buffereach draw call. This is fine for ~30 objects but you'd want instanced rendering or a dynamic uniform buffer for hundreds+. web-timeis used instead ofstd::time::Instantbecause the latter panics on WASM.- On WASM, wgpu uses WebGPU if available, falling back to WebGL2 via the GL backend.
- Binary size: release builds with
opt-level = "s"+ LTO are typically 1-3 MB gzipped.
Description
Languages
Rust
84.6%
HTML
7.5%
Nix
5.7%
WGSL
2%
Just
0.2%