# 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.