Files
Jérôme Bousquié 5ae978da23 doc
2026-09-21 10:07:32 +02:00

4.7 KiB

Quickstart

Goal: a window showing an object, with the render loop handled by the library. You will only write three things: a struct implementing AppHandler, your scene declaration in setup(), and your main().

Prerequisites

  • A recent Rust toolchain (the library is edition 2024 — run rustup update if needed).
  • A windowing environment (X11/Wayland on Linux, or native macOS/Windows).
  • WSG is not published on crates.io: it is consumed by file path.

1. Dependencies

In your application's Cargo.toml:

[dependencies]
wsg-lib = { path = "/path/to/wsg/lib" }
pollster = { version = "1", features = ["macro"] }   # for #[pollster::main] (AppBuilder is async)

2. The minimal application

This snippet is the simple example from the repo, almost verbatim: a flat two-tone quad, rendered automatically every frame.

use wsg_lib::app::AppBuilder;
use wsg_lib::resources::Geometry;
use wsg_lib::utils::WsgError;
use wsg_lib::AppHandler;

struct MyQuad;

impl AppHandler for MyQuad {
    fn setup(&mut self, app: &mut wsg_lib::App) {
        // Flat 2D: the `standard` shader in unlit mode returns the vertex color as-is.
        app.renderer_mut().set_unlit(true);
        app.scene
            .register_shader("standard", wsg_lib::utils::STANDARD_SHADER_PATH)
            .unwrap();

        let geometry = Geometry::new(vec![
            [-0.5,  0.5, 0.0],
            [ 0.5,  0.5, 0.0],
            [ 0.5, -0.5, 0.0],
            [-0.5, -0.5, 0.0],
        ])
        .with_normals(vec![[0.0, 0.0, 1.0]; 4])
        .with_colors(vec![
            [1.0, 0.0, 0.0, 1.0], // red
            [0.0, 1.0, 0.0, 1.0], // green
            [0.0, 0.0, 1.0, 1.0], // blue
            [1.0, 1.0, 0.0, 1.0], // yellow
        ])
        .with_indices(vec![0, 1, 2, 0, 2, 3]);

        // `None`: the scene injects its default material (`standard`) at render time.
        app.scene.create_mesh("quad_mesh", geometry, None).unwrap();
        app.scene.add_entity("quad", "quad_mesh").unwrap();
    }
}

#[pollster::main]
async fn main() -> Result<(), WsgError> {
    let app = AppBuilder::new().title("WSG Simple").build().await?;
    app.run(MyQuad)
}

Note: no wgpu or winit imports — the App facade encapsulates them entirely.

3. What the library does for you

The full lifecycle, as driven by App::run (technical details in FRAME_LOOP):

AppBuilder::build()          creates the event loop
        │
App::run(handler)            starts the loop
        │
resumed (winit)              window + GPU (Instance/Surface/Adapter/Device/Queue) + Renderer
        │
handler.setup(&mut app)      ← you declare the scene here (once, GPU ready)
        │
        ▼  per frame, in a loop:
        input.begin_frame()   current frame's keyboard/mouse state
handler.update(&mut app)      ← your logic (motion, input, …)
        input.end_frame()
handler.render(app, frame)    ← default: app.render_scene(frame.view())
        │                       (the whole scene is drawn automatically, one pass per frame)
        └─ present → next frame

So you implement:

Hook When Role Default
setup(&mut self, app) once, GPU ready declare shaders, materials, textures, meshes, entities, lights, camera empty
update(&mut self, app) every frame, before render animate: transforms, input, lights… empty
render(&mut self, app, frame) every frame, after update default: draws the whole scene; override for custom rendering app.render_scene(frame.view())

Golden rule: mutate the scene in update() (and setup()), only read it in render() (model detailed in ARCHI_RENDU).

4. Running it

From the WSG repo root (the examples live in lib/examples/):

Command What you see
cargo run -p wsg-lib --example simple the quad above (flat 2D, unlit)
cargo run -p wsg-lib --example cube a textured, lit, spinning cube (3D)
cargo run -p wsg-lib --example demo the full showcase: 6 primitives + lights + shadows + orbital camera

For your own application: create a crate, add the §1 dependency, paste the §2 code into src/main.rs, and cargo run.

5. Where to go next