119 lines
4.2 KiB
Markdown
119 lines
4.2 KiB
Markdown
# 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.
|