- 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)
4.7 KiB
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 (uv_texture.jpg UV atlas) cube, lit (directional + point + spot), spinning |
pbr |
cargo run -p wsg-lib --example pbr |
PBR metallic/roughness + normal mapping (real cave.jpg albedo + caveNormal.jpg) |
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
importexample additionally requires theimport-objCargo 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.
cargo run -p wsg-lib --example simple
No keys — static render.
cube — The 3D MVP
A lit unit cube that rotates, textured with the uv_texture.jpg asset — an
8×8 UV atlas visualization (labelled cells + corner coordinates) that makes
exactly where each face's UVs land visible. The texture is loaded from
assets/textures/ via Texture::from_file (path resolved against
CARGO_MANIFEST_DIR), registered by id (add_texture) and bound through
add_material_texture (diffuse path, bind group @group(2)). Follows the
declarative workflow (like simple): AppBuilder + automatic scene, no wgpu
import; the default camera at (0, 0, 3) frames the cube, and update()
rotates the entity via set_entity_transform each frame.
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.
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,
cave, textured floor). The floor is a 20×20 plane with the ground.jpeg
albedo; the cave cube pairs cave.jpg (albedo) with caveNormal.jpg
(normal map, pre-encoded sRGB before upload — see the Texture assets section
in the parent README) and shows real surface detail under the light.
import — OBJ File Import
Non-graphical example: parses a .obj file and prints statistics
(vertex count, normals, UVs, indices, bounding box) to stdout.
# 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)thenMaterial::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 and
FRAME_LOOP.md.
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.