# Meshes, Materials & Import Examples covering **geometry and materials**: the minimal workflow, the 3D MVP, PBR shading, file import, and the low-level (non-`App`) workflow. | Example | Run command | What it shows | |---------|-------------|---------------| | `simple` | `cargo run -p wsg-lib --example simple` | The minimal declarative workflow: a flat two-tone quad, **unlit**, rendered automatically | | `cube` | `cargo run -p wsg-lib --example cube` | The 3D MVP: a textured (checkerboard) cube, lit (directional + point + spot), spinning | | `pbr` | `cargo run -p wsg-lib --example pbr` | PBR metallic/roughness + normal mapping | | `import` | `cargo run -p wsg-lib --example import --features import-obj` | OBJ file import (non-graphical, prints stats to stdout) | | `manual` | `cargo run -p wsg-lib --example manual` | The **advanced** workflow: `Context`/`Renderer`/`PipelineCache` driven by hand, without the `App` facade | > All commands run from the repo root. The `import` example additionally > requires the `import-obj` Cargo feature. --- ## `simple` — Minimal Declarative Workflow The "15 lines, no wgpu" model: `AppBuilder` creates the window + GPU, and `App::run` drives the update → render → present loop. The scene renders **automatically** — the default `AppHandler::render` calls `app.render_scene(frame.view())`. The mesh is a flat two-tone quad declared from a `Geometry` (per-vertex positions + colors) and drawn with the `standard` shader in **unlit** mode (`renderer.set_unlit(true)`): flat 2D is a special case of 3D, one pipeline for all. ```sh cargo run -p wsg-lib --example simple ``` No keys — static render. --- ## `cube` — The 3D MVP A lit unit cube that rotates, **textured** with a procedural 8×8 checkerboard via the diffuse path (bind group `@group(2)`). Follows the declarative workflow (like `simple`): `AppBuilder` + automatic scene, **no wgpu import**. The texture is generated procedurally (RGBA bytes → `Texture::from_rgba8`) to stay self-contained; the default camera at (0, 0, 3) frames the cube, and `update()` rotates the entity via `set_entity_transform` each frame. ```sh cargo run -p wsg-lib --example cube ``` No keys — the cube spins on its own. --- ## `pbr` — PBR Metallic/Roughness + Normal Mapping Demonstrates the Cook-Torrance PBR workflow: GGX distribution + Smith geometry + Schlick Fresnel + hemispheric IBL + normal mapping. ```sh cargo run -p wsg-lib --example pbr ``` | Key | Action | |-----|--------| | Drag (LMB) | Orbit camera | | Wheel | Zoom | | `R` | Reset camera | Scene: 6 PBR materials (mirror metal, smooth plastic, rusty metal, ceramic, bump map, matte floor). The bump-map cube shows procedural sin-wave surface detail. --- ## `import` — OBJ File Import **Non-graphical** example: parses a `.obj` file and prints statistics (vertex count, normals, UVs, indices, bounding box) to stdout. ```sh # With a file: cargo run -p wsg-lib --example import --features import-obj -- /path/to/model.obj # Without argument (demo triangle): cargo run -p wsg-lib --example import --features import-obj ``` No keys — runs and exits. --- ## `manual` — Low-level Workflow (no `App` facade) Demonstrates the API **without** the `App` facade: direct use of `Context`, `Renderer`, `PipelineCache`, `Mesh`, `Material`. Renders a colored quad (unlit). Useful for understanding what the `App` facade encapsulates: - `Context` (*Manager* layer): GPU lifecycle — `Instance`/`Surface`/`Adapter`/ `Device`/`Queue`, `configure()` for the swapchain, per-frame surface texture. - `Renderer` (*Executor* layer): `render(view, mesh, material)` = one object per submission; `present(frame)`. - `PipelineCache`: `register_shader(id, path)` then `Material::new(format, id, &mut cache)`. The window and GPU are created in winit 0.30's `resumed()` callback (`run_app` + `ApplicationHandler`). The two-layer architecture is detailed in [`docs/tech/ARCHI_APP.md`](../../docs/tech/ARCHI_APP.md) and [`FRAME_LOOP.md`](../../docs/tech/FRAME_LOOP.md). ```sh cargo run -p wsg-lib --example manual ``` No keys — static render (unlit quad, 4 colors). > **Tip**: start with the declarative workflow. The manual workflow doesn't > render more pixels — it gives more control over command encoding.