A high-performance 3D model viewer built with Rust (WebAssembly) and JavaScript, featuring real-time rendering with PBR (Physically Based Rendering) materials and interactive camera controls.
- WebAssembly-powered 3D engine 🦀 written in Rust for optimal performance
- Software rasterization with custom rendering pipeline
- PBR material support ✨ with multiple texture maps:
- 🎨 Diffuse maps (albedo/color)
- 🔍 Normal maps (surface detail)
- ✨ Specular maps (reflectivity)
- 💡 Emission maps (self-illumination)
- Real-time lighting ⚡ calculations
- Z-buffer depth testing for proper occlusion
- Keyboard navigation ⌨️:
WASD
- Move camera (left/right/forward/backward)QE
- Move camera up/downArrow keys
- Fine camera rotationSpace
- Toggle automatic model rotation
- OBJ file format 📄 support
- Multiple pre-loaded models 🎭:
- Head, Car, Cube, Diablo, Iron-man, Pony-car, Shovel-knight, Spaceship, Suzuki
- Configurable parameters ⚙️:
- Model scale and rotation
- Camera movement speed
- Individual texture map toggles
The project consists of three main components:
- Language: Rust
- Build: WebAssembly via
wasm-pack
- Purpose: High-performance 3D rendering engine
- Key modules:
image.rs
- Main rendering engine and pixel buffer managementcamera.rs
- Camera transformations and view matricesworld.rs
- Scene management and object handlingobject.rs
- 3D object representation and transformationsraster.rs
- Software rasterization algorithmstexture.rs
- Texture sampling and filteringtypes.rs
- Mathematical types and structures
- Language: JavaScript (ES6+)
- Build: WebPack
- Purpose: User interface and WebAssembly integration
- Key features:
- WebAssembly module loading and memory management
- Canvas-based rendering output
- Real-time user input handling
- Texture loading and processing via
image-js
- FPS monitoring and performance metrics
- Language: TypeScript
- Runtime: Node.js with Express
- Purpose: Asset serving and model data API
- Endpoints:
/raw/model?model-name=<name>
- Parsed OBJ model data as JSON/source/<model>/<file>
- Static texture and model files
- Rust (latest stable) - Install Rust
- wasm-pack - Install wasm-pack
- Node.js (v14+) - Install Node.js
-
Clone the repository
git clone <repository-url> cd webasm-3d-viewer
-
Build the core project
cd core webasm-pack build
-
Build the client project
cd ../client npm install npm run build
-
Start the server
cd ../server npm install npm start
-
Open your browser Navigate to
http://localhost:5000
Customize the viewer experience with URL parameters:
http://localhost:5000/?model-name=Car&model-scale=0.2&model-rotation=true
Available parameters:
model-name
- Model to load (default: "Head")camera-speed
- Camera movement sensitivity (default: 0.05)rotation-speed
- Auto-rotation speed (default: 0.1)model-scale
- Model scale factor (default: 0.1)model-rotation
- Enable auto-rotation (default: false)normal-map
- Use normal maps (default: true)diffuse-map
- Use diffuse maps (default: true)specular-map
- Use specular maps (default: true)emission-map
- Use emission maps (default: true)
- WASD: Move camera position
- QE: Move camera up/down
- Arrow Keys: Fine camera rotation
- Space: Toggle model auto-rotation
-
Place model files in
/server/public/source/<ModelName>/
:Model.obj
- The 3D modelDiffuse map.png
- Base color textureNormal map.png
- Normal map textureSpecular map.png
- Specular reflection mapEmission map.png
- (Optional) Emission texture
-
Use the model by setting
?model-name=<ModelName>
in the URL
- Adjust
model-scale
for very large/small models - Reduce texture resolution for better performance
- Disable unused texture maps via URL parameters
- Monitor FPS counter in the top-left corner
- Check browser console for WebAssembly loading errors
- Verify model files are properly formatted OBJ files
- Ensure texture files are valid PNG images
- Use browser developer tools to monitor memory usage
- Model Loading: OBJ files parsed server-side to JSON
- Texture Loading: PNG textures loaded via
image-js
- Geometry Processing: Vertices, normals, and UV coordinates processed
- Rasterization: Custom software rasterizer in Rust/WASM
- Shading: Per-pixel lighting with PBR material model
- Output: Direct pixel buffer rendering to HTML5 Canvas
- WebAssembly: Near-native performance for computation-heavy operations
- Memory Management: Direct memory access between WASM and JavaScript
- Real-time: 60 FPS target with dynamic quality adjustment
- Browser Compatibility: Modern browsers with WebAssembly support
- Vertex Data: Interleaved position, normal, and UV coordinates
- Pixel Buffer: RGBA8 format directly accessible from JavaScript
- Texture Storage: Managed in WebAssembly linear memory
- Z-Buffer: 32-bit floating-point depth values
This project is available under dual licensing:
- Apache License 2.0 (
LICENSE-APACHE
) - MIT License (
LICENSE-MIT
)
Zakhar Kot - [email protected]
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
- Hardware-accelerated WebGPU rendering pipeline
- GLTF model format support
- Advanced lighting models (IBL, shadows)