# WSG Examples Each example is self-contained and demonstrates **one effect or feature** of the library. All use the declarative API (`AppBuilder` + `AppHandler`). ## Running an example ```sh cargo run -p wsg-lib --example ``` | Example | Effect demonstrated | |---------|-------------------| | `demo` | Full showcase (all effects combined) | | `bloom` | Post-process bloom (glow around bright areas) | | `hdr` | HDR + Tone Mapping (ACES) + exposure control | | `emissive` | Emissive materials (increasing intensities 0 → 4.0) | | `shadow` | Shadow mapping (directional shadow) | | `culling` | GPU-driven culling (15×15 grid, off-frustum objects skipped) | | `msaa` | MSAA 4× (multisample anti-aliasing, smooth edges) | | `fog` | Distance fog (3 modes: linear, exp, exp²) | | `dof` | Depth of Field (cinematic bokeh, focus presets) | | `pbr` | PBR metallic/roughness + normal mapping | | `manual` | Low-level workflow (Context + Renderer + PipelineCache) | | `import` | OBJ file import (non-graphical, stdout) | --- ## `demo` — Full Showcase Combines **all** effects: LOD primitives, procedural textures, lights (directional + point + spot), shadows, HDR/ACES, exposure, emissive, bloom, culling. ```sh cargo run -p wsg-lib --example demo ``` ### Keys | Key | Action | |-----|--------| | Drag (LMB) | Orbit camera | | Wheel | Zoom | | `R` | Reset camera | | `1` / `2` / `3` | Presets: front / side / top | | `+` / `-` | Exposure ×1.3 / ÷1.3 | | `0` | Reset exposure | --- ## `bloom` — Post-process Bloom Two emissive spheres (orange intensity 2.0, blue intensity 3.0) produce a visible halo. The cube and floor serve as reference (non-emissive). Bloom is a 4-pass GPU pipeline: threshold → blur H → blur V → composite. ```sh cargo run -p wsg-lib --example bloom ``` ### Keys | Key | Action | |-----|--------| | Drag (LMB) | Orbit camera | | Wheel | Zoom | | `R` | Reset camera | | `+` / `-` | **Bloom threshold** +0.1 / −0.1 | | `[` / `]` | **Bloom intensity** +0.1 / −0.1 | | `I` / `O` | **Bloom radius** +0.5 / −0.5 | | `E` / `Q` | Exposure ×1.3 / ÷1.3 | | `0` | Reset exposure | ### What to observe - **Low threshold** (0.0): the entire image "blooms" (very diffuse effect). - **High threshold** (2.0+): only the bright emissive spheres produce glow. - **Intensity 0.0**: no visible glow (even though the threshold extracts pixels). - **Large radius** (10+): the glow spreads over a large area. --- ## `hdr` — HDR + Tone Mapping Demonstrates HDR rendering with the ACES Filmic curve. Three objects: - **Cube**: normal lighting (no emissive) — LDR reference. - **Bright sphere** (emissive 3.0): without HDR, it would be clamped to white. With ACES, highlights "roll off" smoothly toward white. - **Dark sphere** (emissive 0.3): stays dark even at high exposure. ```sh cargo run -p wsg-lib --example hdr ``` ### Keys | Key | Action | |-----|--------| | Drag (LMB) | Orbit camera | | Wheel | Zoom | | `R` | Reset camera | | `E` | **Exposure ×1.3** (brighter) | | `Q` | **Exposure ÷1.3** (darker) | | `0` | Reset exposure to 1.0 | ### What to observe - At exposure 1.0: the bright sphere is white but with detail (ACES rolloff). - At high exposure (E×E×E): the scene brightens, the bright sphere stays white (saturated), but the cube gains detail. - At low exposure (Q×Q): everything darkens, the bright sphere becomes orange (HDR values > 1.0 are compressed). > **Note**: the tone mapper is compiled into the pipeline at build time. To compare > ACES vs Reinhard, change `ToneMapper::Aces` → `ToneMapper::Reinhard` in the source. --- ## `emissive` — Emissive Materials Five spheres in a row with increasing emissive intensities: | Sphere | Color | Intensity | Effect | |--------|-------|-----------|--------| | 1 | Gray | 0.0 | No glow (reference) | | 2 | Orange | 0.5 | Slight glow | | 3 | Yellow | 1.0 | Visible glow | | 4 | Green | 2.0 | HDR glow (beyond 1.0) | | 5 | Blue | 4.0 | Intense glow (saturation) | With HDR, intensities > 1.0 produce a true "glow" (values exceed [0,1] in linear space). Without HDR, they would be clamped to white. ```sh cargo run -p wsg-lib --example emissive ``` ### Keys | Key | Action | |-----|--------| | Drag (LMB) | Orbit camera | | Wheel | Zoom | | `R` | Reset camera | | `E` / `Q` | Exposure ×1.3 / ÷1.3 | | `0` | Reset exposure | | `C` | **Cycle emissive multiplier** (1× → 2× → 0.5× → ...) | ### What to observe - Sphere 1 (intensity 0) is simply lit by the directional light. - Spheres 2-5 glow with their own light, independent of scene lighting. - `C` doubles or halves all intensities simultaneously (to see the HDR effect). --- ## `shadow` — Shadow Mapping Four objects (cube, sphere, cone, cylinder) on a floor, lit by a directional light that casts shadows. Shadow quality is controlled by `ShadowConfig` (map size, anti-acne bias). ```sh cargo run -p wsg-lib --example shadow ``` ### Keys | Key | Action | |-----|--------| | Drag (LMB) | Orbit camera | | Wheel | Zoom | | `R` | Reset camera | | `1` | Front view | | `2` | Side view | | `3` | **Top view** (see shadow shapes clearly) | | `L` | Change light direction (3 presets) | ### What to observe - The cube rotates slowly → its shadow moves on the floor. - The sphere has a smooth shadow/light transition (soft terminator). - The cone produces a distinct triangular shadow. - In top view (`3`), you see the exact shape of projected shadows. - Shadow map size (1024 default) determines resolution: modify `SHADOW_MAP_SIZE` at the top of the file to test 256 (pixelated) or 2048 (sharp). --- ## `culling` — GPU Frustum Culling A grid of **15×15 = 225 cubes** is placed on a large floor. The GPU-driven culling (compute shader) determines which cubes are visible in the camera frustum and zeros their indirect draw args — **zero CPU cost**. ```sh cargo run -p wsg-lib --example culling ``` ### Keys | Key | Action | |-----|--------| | Drag (LMB) | Orbit camera (look around) | | Wheel | Zoom in/out | | `R` | Reset (top view) | | `1` | Front view (cubes behind are culled) | | `2` | Side view | | `3` | **Top view** (see the full grid) | ### What to observe - In top view (`3`): the entire grid is visible. - Orbit to 90°: cubes behind the camera **are not drawn** (culled). - Zoom very close: only cubes near the near plane are rendered. - Cubes rotate slowly (staggered phases) → culling is dynamic (a cube can enter/leave the frustum during a frame). > **Note**: culling is enabled via `AppBuilder::with_culling(true)`. Changing > it to `false` in the source disables culling (all cubes are always drawn, even off-screen). --- ## `msaa` — MSAA 4× (Anti-aliasing) Demonstrates multisample anti-aliasing: object edges (cube, sphere) are smooth instead of "stair-stepped". The scene contains a cube (sharp edges), a sphere (curved silhouette), and a small cube near the camera (maximum aliasing). ```sh cargo run -p wsg-lib --example msaa ``` ### Keys | Key | Action | |-----|--------| | Drag (LMB) | Orbit camera | | Wheel | Zoom | | `R` | Reset camera | | `M` | Show sample count | ### To compare with/without MSAA Remove the `.with_msaa(4)` line in the source and recompile: the scene is identical, only the edges differ (stair-stepped vs smooth). > **Note**: MSAA is a build-time setting (multisample texture allocation). > It works independently of HDR: with HDR, the MSAA texture is `Rgba16Float` > and resolves into the HDR texture before bloom/TM. --- ## `fog` — Distance Fog Demonstrates the 3 fog modes: **linear**, **exponential**, **exponential²**. The scene contains a row of cubes receding into the distance and scattered spheres on a large floor plane. Fog blends objects toward a background color, creating the illusion of an infinite world. ```sh cargo run -p wsg-lib --example fog --features "all-prims" ``` **Keys**: `1` = linear, `2` = exp, `3` = exp², `4` = off, `R` = reset. > Fog is applied in the main fragment shader (after lighting, before tone mapping). > It uses the Euclidean distance from the fragment to the camera. --- ## `dof` — Depth of Field (cinematic bokeh) Demonstrates depth of field blur: an object at the focus plane stays sharp while foreground and background blur according to their distance from the focus plane. Creates a natural attention effect (cinematic style). The scene contains 20 cubes in a row along Z (z=3 to z=-25.5) and 5 spheres to the sides, on a floor plane. Focus presets at 3m / 8m / 15m. ```sh cargo run -p wsg-lib --example dof --features "all-prims" ``` **Keys**: `1` = cinematic, `2` = subtle, `3` = focus 3m, `4` = focus 15m, `5` = off, `R` = reset. > DoF operates in linear HDR (after bloom, before tone mapping). Two passes: > CoC (depth → per-pixel blur radius) then 12-tap disc blur with variable radius. --- ## `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. --- ## `manual` — Low-level Workflow 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. ```sh cargo run -p wsg-lib --example manual ``` No keys — static render (unlit quad, 4 colors). --- ## `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.