- meshes/cube: procedural checkerboard -> uv_texture.jpg (8x8 UV grid) - meshes/pbr: floor -> ground.jpeg, bump cube -> cave.jpg + caveNormal.jpg (normal map pre-encoded via sRGB OETF to cancel the GPU sRGB decode) - lights/shadow: ground -> ground.jpeg, cube -> uv_texture.jpg - effects/demo: ground -> ground.jpeg, cube -> uv_texture.jpg - effects/fog: ground -> ground.jpeg (tiled 80x80), cubes -> stonewall.jpg - effects/dof: ground -> ground.jpeg, cubes -> uv_texture.jpg - cameras/culling: shared cube mesh -> uv_texture.jpg - add lib/examples/assets/textures/ (19 assets, 6.5 MB) - document assets + usage in examples READMEs, docs/user/examples.md, docs/user/meshes/materials.md (CARGO_MANIFEST_DIR pattern, sRGB caveat)
WSG Examples
The examples are organized into four category folders, one per theme. Each
folder has its own README.md documenting its examples in detail (what they
demonstrate, how to run them, keyboard controls, what to observe).
| Folder | Theme | Examples |
|---|---|---|
| meshes/ | Geometry, materials, file import, low-level workflow | simple, cube, pbr, import, manual |
| lights/ | Light types, shadow mapping, emissive materials | shadow, shadow_test, spot_test, emissive |
| cameras/ | Camera-driven rendering (frustum culling) | culling |
| effects/ | HDR, tone mapping, post-process, full showcase | demo, bloom, hdr, msaa, fog, dof |
Running an example
Example names are stable — from the repo root:
cargo run -p wsg-lib --example <name>
Examples gated behind a Cargo feature need the feature too:
cargo run -p wsg-lib --example import --features import-obj
All examples are self-contained: hard-coded geometries, and textures that are
either procedural or shipped in assets/textures/. All use the
declarative API (AppBuilder + AppHandler) except manual, which demonstrates
the low-level workflow instead.
Texture assets
A few examples (the multi-mesh / multi-effect ones) use real image files from
assets/textures/, loaded with Texture::from_file. The paths are resolved
against CARGO_MANIFEST_DIR at compile time, so the examples work from any
working directory:
const TEXTURES: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/assets/textures");
Texture::from_file(&device, &queue, "label", &format!("{TEXTURES}/ground.jpeg"))
Assets used by the examples:
| Asset | Size | Used by | Role |
|---|---|---|---|
uv_texture.jpg |
437×438 | cube, demo, shadow, dof, culling |
8×8 UV atlas visualization (labelled cells + corner coordinates) — makes UV mapping and culling decisions explicit |
ground.jpeg |
512×512 | demo, pbr, shadow, fog, dof |
Seamless ground albedo, tiled via the Repeat sampler |
stonewall.jpg |
300×225 | fog |
Distinctive cube texture — the fog falloff reads clearly on it |
cave.jpg + caveNormal.jpg |
600×450 | pbr |
Albedo + normal-map pair for the PBR normal-mapping demo |
The remaining assets in the folder (rock.jpg, seamlessRoad.jpg, stalag.jpg /
stalagNormal.jpg, stars1.jpg, sprite/heightmap PNGs, …) are available for
experiments. Two notes:
Textureuploads toRgba8UnormSrgb— correct for albedo maps (the GPU sRGB-decodes on sample). A normal map is linear data, sopbrpre-encodes its channels with the sRGB OETF before upload (load_normal_map): the GPU decode then restores the original values (EOTF∘OETF = identity).- The texture sampler is
Linear+Repeat, so any texture tiles automatically when UVs exceed [0,1] (the 80×80 fog floor uses this to tileground.jpeg).
Where do the files live? Examples live in subfolders (
examples/<folder>/<name>.rs). Cargo only auto-discovers top-levelexamples/*.rs, so every example is declared explicitly inlib/Cargo.tomlwith itspath. This keeps--example <name>working while allowing the folder organization.
Suggested learning path
simple— the minimal declarative workflow (flat unlit quad, ~15 lines)cube— the 3D MVP: a textured, lit, spinning cubepbr— PBR materials and normal mappingspot_test,shadow_test— isolated light and shadow behaviorhdr→emissive→bloom— the HDR chain, step by stepculling— GPU-driven frustum cullingdemo— everything combinedmanual— what theAppfacade actually encapsulates
Adding your own example
- Create
lib/examples/<folder>/my_example.rs(pick the matching category; add a new folder + README if needed). - Declare it in
lib/Cargo.toml(Cargo won't discover it otherwise):[[example]] name = "my_example" path = "examples/<folder>/my_example.rs" - Keep it self-contained: hard-coded geometries; textures are procedural
or come from
assets/textures/(resolved viaCARGO_MANIFEST_DIR, see Texture assets above). - Document it in the folder's
README.md(and indocs/user/examples.md).