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

5.9 KiB
Raw Blame History

WSG — WGPU Simple Graphics Library

WSG (WGPU Simple Graphics) is a Rust library that wraps wgpu and 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

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(())
}
[dependencies]
wsg-lib = { path = "../lib" }
pollster = { version = "1", features = ["macro"] }
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/ User guide — how to use the API, step by step
docs/tech/ Internal architecture — decisions, specs, targets
docs/ROADMAP.md Roadmap (phases 1-5 ✅, phase 6 in progress)
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

# 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

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


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.