Files
wsg/README.md
T
Jérôme Bousquié 83daeb4c7d readmes
2026-09-25 14:54:27 +02:00

167 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.