readmes
This commit is contained in:
@@ -1,28 +1,28 @@
|
||||
# WSG — WGPU Simple Graphics Library
|
||||
|
||||
**WSG** (WGPU Simple Graphics) est une bibliothèque Rust qui wrap [wgpu](https://github.com/gfx-rs/wgpu) et [winit](https://crates.io/crates/winit) pour dessiner en 3D **sans toucher wgpu directement**.
|
||||
**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**.
|
||||
|
||||
## Ce que vous obtenez
|
||||
## What you get
|
||||
|
||||
- **Une fenêtre 3D en ~30 lignes** — pas de wgpu, pas de winit dans votre code
|
||||
- **Éclairage Phong** (directional, point, spot) + **ombres portées** (shadow mapping)
|
||||
- **HDR + Tone Mapping** (ACES Filmic / Reinhard) — opt-in, zéro coût si désactivé
|
||||
- **Pipeline GPU-driven** — world matrices + frustum culling sur le GPU, indirect draws
|
||||
- **LOD** (Level of Detail) — dégradation automatique de la géométrie selon la distance
|
||||
- **Primitives procédurales** — cube, sphère, cylindre, cône, tore, plan
|
||||
- **Import de fichiers** — parser OBJ intégré (glTF en cours)
|
||||
- **Caméra orbitale** + input unifié (clavier/souris)
|
||||
- **LOD, culling, HDR, ombres** : tout est **opt-in** — ce que vous n'activez pas ne coûte rien
|
||||
- **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
|
||||
|
||||
## Forces
|
||||
## Strengths
|
||||
|
||||
| Force | Détail |
|
||||
|-------|--------|
|
||||
| **Zéro wgpu dans votre code** | L'API déclarative (`AppBuilder` + `AppHandler`) encapsule tout |
|
||||
| **Opt-in = zéro coût** | Un effet non activé n'alloue rien, n'exécute rien |
|
||||
| **Features Cargo** | Ne compilez que les primitives/import dont vous avez besoin |
|
||||
| **Un seul shader** | Le `standard` shader (Phong) couvre 90 % des cas ; mode unlit pour la 2D |
|
||||
| **GPU-driven** | Le CPU envoie des transforms, le GPU fait le reste (matrices, culling, draws) |
|
||||
| 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
|
||||
|
||||
@@ -31,9 +31,9 @@ use wsg_lib::prelude::*;
|
||||
use wsg_lib::app::AppBuilder;
|
||||
use wsg_lib::utils::WsgError;
|
||||
|
||||
struct MaScene;
|
||||
struct MyScene;
|
||||
|
||||
impl AppHandler for MaScene {
|
||||
impl AppHandler for MyScene {
|
||||
fn setup(&mut self, app: &mut wsg_lib::App) {
|
||||
app.scene
|
||||
.register_shader("standard", wsg_lib::utils::STANDARD_SHADER_PATH)
|
||||
@@ -42,7 +42,7 @@ impl AppHandler for MaScene {
|
||||
.create_material("mat", "standard", None)
|
||||
.unwrap();
|
||||
|
||||
// Un cube lit par Phong, posé au-dessus d'un plan
|
||||
// A Phong-lit cube, sitting on a ground plane
|
||||
app.scene
|
||||
.create_mesh("cube", cube(1.0), Some("mat"))
|
||||
.unwrap();
|
||||
@@ -61,10 +61,10 @@ impl AppHandler for MaScene {
|
||||
|
||||
fn main() -> Result<(), WsgError> {
|
||||
let mut app = AppBuilder::new()
|
||||
.title("Ma scène WSG")
|
||||
.with_hdr(ToneMapper::Aces) // optionnel : HDR + tone mapping
|
||||
.title("My WSG scene")
|
||||
.with_hdr(ToneMapper::Aces) // optional: HDR + tone mapping
|
||||
.build()?;
|
||||
app.run(MaScene);
|
||||
app.run(MyScene);
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
@@ -76,81 +76,91 @@ pollster = { version = "1", features = ["macro"] }
|
||||
```
|
||||
|
||||
```sh
|
||||
cargo run --example demo # le showcase complet (6 primitives, 3 lumières, ombres, HDR)
|
||||
cargo run --example demo # full showcase (6 primitives, 3 lights, shadows, HDR)
|
||||
```
|
||||
|
||||
## Fonctionnalités
|
||||
## Features
|
||||
|
||||
| Catégorie | Ce qui est disponible |
|
||||
|-----------|----------------------|
|
||||
| **Géométrie** | 6 primitives procédurales + import OBJ + `Geometry` custom |
|
||||
| **Rendu** | Phong (lit), unlit (2D flat), HDR + tone mapping (ACES/Reinhard) |
|
||||
| **Lumières** | Directional, point, spot (8 max) + ambient |
|
||||
| **Ombres** | Shadow mapping (directional/spot), slope-scaled bias, PCF |
|
||||
| **LOD** | Décimation quadric auto, hystérésis, 1 buffer multi-niveaux |
|
||||
| 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 |
|
||||
| **Caméra** | Orbitale (drag/zoom/reset) + presets (front/side/top) |
|
||||
| **Input** | Clavier (pressed/held/released), souris (delta, scroll, boutons) |
|
||||
| **Textures** | RGBA8 (de bytes, de fichier, placeholder blanc) |
|
||||
| **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
|
||||
|
||||
| Où | Quoi |
|
||||
|----|------|
|
||||
| [docs/user/](docs/user/README.md) | **Guide utilisateur** (EN) — comment utiliser l'API, pas à pas |
|
||||
| [docs/tech/](docs/tech/ARCHI_APP.md) | **Architecture interne** (FR) — décisions, specs, cibles |
|
||||
| [docs/ROADMAP.md](docs/ROADMAP.md) | Feuille de route (phases 1-5 ✅, phase 6 en cours) |
|
||||
| [docs/PLAN.md](docs/PLAN.md) | Livre de recette (historique des étapes) |
|
||||
| `cargo doc -p wsg-lib --no-deps` | **Référence API** (rustdoc, 100 % couvert) |
|
||||
| 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) |
|
||||
|
||||
## Exemples
|
||||
## Examples
|
||||
|
||||
| Exemple | Ce qu'il montre |
|
||||
|---------|----------------|
|
||||
| `demo` | Le showcase : 6 primitives, 3 lumières, ombres, HDR, LOD, caméra orbitale |
|
||||
| `cube` | MVP 3D : un cube lit par Phong, texture checkerboard |
|
||||
| `simple` | Minimal : un quad coloré en mode unlit (2D) |
|
||||
| `shadow_test` | Ombres portées isolées |
|
||||
| `spot_test` | Spotlight isolé |
|
||||
| `import` | Import de fichier OBJ (feature `import-obj`) |
|
||||
| `manual` | Workflow low-level (Context/Renderer/PipelineCache, sans App) |
|
||||
| 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) |
|
||||
|
||||
## Features Cargo
|
||||
## Cargo Features
|
||||
|
||||
```toml
|
||||
# Default : toutes les primitives
|
||||
# Default: all primitives
|
||||
wsg-lib = { path = "../lib" }
|
||||
|
||||
# Minimal : juste le cube
|
||||
# Minimal: just the cube
|
||||
wsg-lib = { path = "../lib", default-features = false, features = ["prim-cube"] }
|
||||
|
||||
# Avec import OBJ
|
||||
# With OBJ import
|
||||
wsg-lib = { path = "../lib", features = ["import-obj"] }
|
||||
```
|
||||
|
||||
| Feature | Active |
|
||||
|---------|--------|
|
||||
| Feature | Enables |
|
||||
|---------|---------|
|
||||
| `prim-cube`, `prim-plane`, `prim-sphere`, `prim-cylinder`, `prim-cone`, `prim-torus` | Primitives |
|
||||
| `all-prims` (default) | Les 6 primitives |
|
||||
| `import-obj` | Parser Wavefront OBJ |
|
||||
| `all-prims` (default) | All 6 primitives |
|
||||
| `import-obj` | Wavefront OBJ parser |
|
||||
| `import-gltf` | glTF (stub) |
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
cargo build --workspace # tout
|
||||
cargo test --workspace # 116 tests
|
||||
cargo check --all-targets # vérification rapide
|
||||
cargo run -p wsg-lib --example demo # lancer le showcase
|
||||
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
|
||||
```
|
||||
|
||||
## Projet
|
||||
## Project
|
||||
|
||||
- **Langage** : Rust 2024
|
||||
- **Dépendances** : wgpu 30, winit 0.30, glam (math)
|
||||
- **Pas publié sur crates.io** (dépendance par path)
|
||||
- **Status** : MVP complet (phases 1-5 ✅), post-MVP en cours (phase 6)
|
||||
- **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)
|
||||
|
||||
---
|
||||
|
||||
*Documentation détaillée (architecture, status, API reference, workflow manuel) : [README_DETAILS.md](README_DETAILS.md)*
|
||||
*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.
|
||||
|
||||
Reference in New Issue
Block a user