167 lines
5.9 KiB
Markdown
167 lines
5.9 KiB
Markdown
# WSG — WGPU Simple Graphics Library
|
||
|
||
**WSG** (WGPU Simple Graphics) is a Rust library that wraps [wgpu](https://github.com/gfx-rs/wgpu) and [winit](https://crates.io/crates/winit) to draw 3D **without touching wgpu directly**.
|
||
|
||
## What you get
|
||
|
||
- **A 3D window in ~30 lines** — no wgpu, no winit in your code
|
||
- **Phong lighting** (directional, point, spot) + **shadows** (shadow mapping)
|
||
- **HDR + Tone Mapping** (ACES Filmic / Reinhard) — opt-in, zero cost when disabled
|
||
- **GPU-driven pipeline** — world matrices + frustum culling on the GPU, indirect draws
|
||
- **LOD** (Level of Detail) — automatic geometry degradation based on distance
|
||
- **Procedural primitives** — cube, sphere, cylinder, cone, torus, plane
|
||
- **File import** — built-in OBJ parser (glTF in progress)
|
||
- **Orbital camera** + unified input (keyboard/mouse)
|
||
- **LOD, culling, HDR, shadows**: everything is **opt-in** — what you don't enable costs nothing
|
||
|
||
## Strengths
|
||
|
||
| Strength | Detail |
|
||
|----------|--------|
|
||
| **Zero wgpu in your code** | The declarative API (`AppBuilder` + `AppHandler`) encapsulates everything |
|
||
| **Opt-in = zero cost** | A disabled effect allocates nothing, executes nothing |
|
||
| **Cargo features** | Only compile the primitives/importers you need |
|
||
| **One shader** | The `standard` shader (Phong) covers 90% of cases; unlit mode for 2D |
|
||
| **GPU-driven** | CPU sends transforms, GPU does the rest (matrices, culling, draws) |
|
||
|
||
## Quickstart
|
||
|
||
```rust
|
||
use wsg_lib::prelude::*;
|
||
use wsg_lib::app::AppBuilder;
|
||
use wsg_lib::utils::WsgError;
|
||
|
||
struct MyScene;
|
||
|
||
impl AppHandler for MyScene {
|
||
fn setup(&mut self, app: &mut wsg_lib::App) {
|
||
app.scene
|
||
.register_shader("standard", wsg_lib::utils::STANDARD_SHADER_PATH)
|
||
.unwrap();
|
||
app.scene
|
||
.create_material("mat", "standard", None)
|
||
.unwrap();
|
||
|
||
// A Phong-lit cube, sitting on a ground plane
|
||
app.scene
|
||
.create_mesh("cube", cube(1.0), Some("mat"))
|
||
.unwrap();
|
||
app.scene
|
||
.add_entity("my_cube", "cube")
|
||
.unwrap();
|
||
|
||
app.scene
|
||
.create_mesh("ground", plane(10.0, 10.0, 1, 1), Some("mat"))
|
||
.unwrap();
|
||
app.scene
|
||
.add_entity("floor", "ground")
|
||
.unwrap();
|
||
}
|
||
}
|
||
|
||
fn main() -> Result<(), WsgError> {
|
||
let mut app = AppBuilder::new()
|
||
.title("My WSG scene")
|
||
.with_hdr(ToneMapper::Aces) // optional: HDR + tone mapping
|
||
.build()?;
|
||
app.run(MyScene);
|
||
Ok(())
|
||
}
|
||
```
|
||
|
||
```toml
|
||
[dependencies]
|
||
wsg-lib = { path = "../lib" }
|
||
pollster = { version = "1", features = ["macro"] }
|
||
```
|
||
|
||
```sh
|
||
cargo run --example demo # full showcase (6 primitives, 3 lights, shadows, HDR)
|
||
```
|
||
|
||
## Features
|
||
|
||
| Category | What's available |
|
||
|----------|-----------------|
|
||
| **Geometry** | 6 procedural primitives + OBJ import + custom `Geometry` |
|
||
| **Rendering** | Phong (lit), unlit (2D flat), PBR metallic/roughness, HDR + tone mapping |
|
||
| **Lights** | Directional, point, spot (8 max) + ambient |
|
||
| **Shadows** | Shadow mapping (directional/spot), slope-scaled bias, PCF |
|
||
| **LOD** | Auto quadric decimation, hysteresis, 1 buffer multi-level |
|
||
| **GPU-driven** | Compute pass (matrices + culling) → indirect draws |
|
||
| **Post-process** | Bloom, Depth of Field, Fog (3 modes), MSAA 4× |
|
||
| **Camera** | Orbital (drag/zoom/reset) + presets (front/side/top) |
|
||
| **Input** | Keyboard (pressed/held/released), mouse (delta, scroll, buttons) |
|
||
| **Textures** | RGBA8 (from bytes, from file, white placeholder) |
|
||
|
||
## Documentation
|
||
|
||
| Where | What |
|
||
|-------|------|
|
||
| [docs/user/](docs/user/README.md) | **User guide** — how to use the API, step by step |
|
||
| [docs/tech/](docs/tech/ARCHI_APP.md) | **Internal architecture** — decisions, specs, targets |
|
||
| [docs/ROADMAP.md](docs/ROADMAP.md) | Roadmap (phases 1-5 ✅, phase 6 in progress) |
|
||
| [docs/PLAN.md](docs/PLAN.md) | Recipe book (step history) |
|
||
| `cargo doc -p wsg-lib --no-deps` | **API reference** (rustdoc, 100% covered) |
|
||
|
||
## Examples
|
||
|
||
| Example | What it shows |
|
||
|---------|---------------|
|
||
| `demo` | Full showcase: 6 primitives, 3 lights, shadows, HDR, LOD, orbital camera |
|
||
| `bloom` | HDR bloom post-process |
|
||
| `hdr` | HDR + tone mapping (ACES/Reinhard) |
|
||
| `emissive` | Emissive materials + runtime exposure control |
|
||
| `shadow` | Shadow mapping in isolation |
|
||
| `culling` | GPU-driven frustum culling (15×15 grid) |
|
||
| `msaa` | 4× multisample anti-aliasing |
|
||
| `fog` | 3 fog modes (linear, exponential, exponential²) |
|
||
| `dof` | Depth of field with focus presets |
|
||
| `pbr` | PBR metallic/roughness + normal mapping |
|
||
| `import` | OBJ file import (feature `import-obj`) |
|
||
| `manual` | Low-level workflow (Context/Renderer/PipelineCache, no App) |
|
||
|
||
## Cargo Features
|
||
|
||
```toml
|
||
# Default: all primitives
|
||
wsg-lib = { path = "../lib" }
|
||
|
||
# Minimal: just the cube
|
||
wsg-lib = { path = "../lib", default-features = false, features = ["prim-cube"] }
|
||
|
||
# With OBJ import
|
||
wsg-lib = { path = "../lib", features = ["import-obj"] }
|
||
```
|
||
|
||
| Feature | Enables |
|
||
|---------|---------|
|
||
| `prim-cube`, `prim-plane`, `prim-sphere`, `prim-cylinder`, `prim-cone`, `prim-torus` | Primitives |
|
||
| `all-prims` (default) | All 6 primitives |
|
||
| `import-obj` | Wavefront OBJ parser |
|
||
| `import-gltf` | glTF (stub) |
|
||
|
||
## Build
|
||
|
||
```sh
|
||
cargo build --workspace # everything
|
||
cargo test --workspace # 127 tests
|
||
cargo check --all-targets # quick check
|
||
cargo run -p wsg-lib --example demo # run the showcase
|
||
```
|
||
|
||
## Project
|
||
|
||
- **Language**: Rust 2024
|
||
- **Dependencies**: wgpu 30, winit 0.30, glam (math)
|
||
- **Not published on crates.io** (path dependency)
|
||
- **Status**: MVP complete (phases 1-5 ✅), post-MVP in progress (phase 6)
|
||
|
||
---
|
||
|
||
*Detailed documentation (architecture, status, API reference, manual workflow): [README_DETAILS.md](README_DETAILS.md)*
|
||
|
||
---
|
||
|
||
> This project was heavily developed using OpenCode, Pi Code, and JCode AI agents running on local Qwen3-27b_Q4 and DeepSeek V4 Flash Q4 instances. The project organization and architecture are the author's own design.
|