e5f3636b424093d714c561d9b9fea0f26ae630cc
- 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 — WGPU Simple Graphics Library
WSG (WGPU Simple Graphics) is a Rust library that wraps wgpu and winit to draw 3D without touching wgpu directly.
What you get
- A 3D window in ~30 lines — no wgpu, no winit in your code
- Phong lighting (directional, point, spot) + shadows (shadow mapping)
- HDR + Tone Mapping (ACES Filmic / Reinhard) — opt-in, zero cost when disabled
- GPU-driven pipeline — world matrices + frustum culling on the GPU, indirect draws
- LOD (Level of Detail) — automatic geometry degradation based on distance
- Procedural primitives — cube, sphere, cylinder, cone, torus, plane
- File import — built-in OBJ parser (glTF in progress)
- Orbital camera + unified input (keyboard/mouse)
- LOD, culling, HDR, shadows: everything is opt-in — what you don't enable costs nothing
Strengths
| Strength | Detail |
|---|---|
| Zero wgpu in your code | The declarative API (AppBuilder + AppHandler) encapsulates everything |
| Opt-in = zero cost | A disabled effect allocates nothing, executes nothing |
| Cargo features | Only compile the primitives/importers you need |
| One shader | The standard shader (Phong) covers 90% of cases; unlit mode for 2D |
| GPU-driven | CPU sends transforms, GPU does the rest (matrices, culling, draws) |
Quickstart
use wsg_lib::prelude::*;
use wsg_lib::app::AppBuilder;
use wsg_lib::utils::WsgError;
struct MyScene;
impl AppHandler for MyScene {
fn setup(&mut self, app: &mut wsg_lib::App) {
app.scene
.register_shader("standard", wsg_lib::utils::STANDARD_SHADER_PATH)
.unwrap();
app.scene
.create_material("mat", "standard", None)
.unwrap();
// A Phong-lit cube, sitting on a ground plane
app.scene
.create_mesh("cube", cube(1.0), Some("mat"))
.unwrap();
app.scene
.add_entity("my_cube", "cube")
.unwrap();
app.scene
.create_mesh("ground", plane(10.0, 10.0, 1, 1), Some("mat"))
.unwrap();
app.scene
.add_entity("floor", "ground")
.unwrap();
}
}
fn main() -> Result<(), WsgError> {
let mut app = AppBuilder::new()
.title("My WSG scene")
.with_hdr(ToneMapper::Aces) // optional: HDR + tone mapping
.build()?;
app.run(MyScene);
Ok(())
}
[dependencies]
wsg-lib = { path = "../lib" }
pollster = { version = "1", features = ["macro"] }
cargo run -p wsg-lib --example demo # full showcase (6 primitives, 3 lights, shadows, HDR)
Features
| Category | What's available |
|---|---|
| Geometry | 6 procedural primitives + OBJ import + custom Geometry |
| Rendering | Phong (lit), unlit (2D flat), PBR metallic/roughness, HDR + tone mapping |
| Lights | Directional, point, spot (8 max) + ambient |
| Shadows | Shadow mapping (directional/spot), slope-scaled bias, PCF |
| LOD | Auto quadric decimation, hysteresis, 1 buffer multi-level |
| GPU-driven | Compute pass (matrices + culling) → indirect draws |
| Post-process | Bloom, Depth of Field, Fog (3 modes), MSAA 4× |
| Camera | Orbital (drag/zoom/reset) + presets (front/side/top) |
| Input | Keyboard (pressed/held/released), mouse (delta, scroll, buttons) |
| Textures | RGBA8 (from bytes, from file, white placeholder) |
Documentation
| Where | What |
|---|---|
| docs/user/ | User guide — how to use the API, step by step |
| docs/tech/ | Internal architecture — decisions, specs, targets |
| lib/examples/ | Examples — 4 category folders (meshes/lights/cameras/effects), each with a README |
| docs/ROADMAP.md | Roadmap (phases 1-5 ✅, phase 6 in progress) |
| docs/PLAN.md | Recipe book (step history) |
cargo doc -p wsg-lib --no-deps |
API reference (rustdoc, 100% covered) |
Examples
Sixteen examples in lib/examples/, organized into four category folders —
each folder has its own README (run commands, keys, what to observe):
lib/examples/README.md. All run from the repo root
with cargo run -p wsg-lib --example <name> (feature-gated ones need
--features, e.g. import → --features import-obj).
| Folder | Example | What it shows |
|---|---|---|
meshes/ |
simple |
Minimal declarative workflow (flat unlit quad, ~15 lines) |
cube |
Textured, lit, spinning cube (the 3D MVP) | |
pbr |
PBR metallic/roughness + normal mapping | |
import |
OBJ file import (feature import-obj) |
|
manual |
Low-level workflow (Context/Renderer/PipelineCache, no App) | |
lights/ |
shadow |
Shadow mapping in isolation |
shadow_test |
Dedicated shadow test (directional caster + PCF) | |
spot_test |
Isolated spot light (beam, penumbra) | |
emissive |
Emissive materials + runtime exposure control | |
cameras/ |
culling |
GPU-driven frustum culling (15×15 grid) |
effects/ |
demo |
Full showcase: 6 primitives, 3 lights, shadows, HDR, LOD, orbital camera |
bloom |
HDR bloom post-process | |
hdr |
HDR + tone mapping (ACES/Reinhard) | |
msaa |
4× multisample anti-aliasing | |
fog |
3 fog modes (linear, exponential, exponential²) | |
dof |
Depth of field with focus presets |
Cargo Features
# Default: all primitives
wsg-lib = { path = "../lib" }
# Minimal: just the cube
wsg-lib = { path = "../lib", default-features = false, features = ["prim-cube"] }
# With OBJ import
wsg-lib = { path = "../lib", features = ["import-obj"] }
| Feature | Enables |
|---|---|
prim-cube, prim-plane, prim-sphere, prim-cylinder, prim-cone, prim-torus |
Primitives |
all-prims (default) |
All 6 primitives |
import-obj |
Wavefront OBJ parser |
import-gltf |
glTF (stub) |
Build
cargo build --workspace # everything
cargo test --workspace # 127 tests
cargo check --all-targets # quick check
cargo run -p wsg-lib --example demo # run the showcase
Project
- Language: Rust 2024
- Dependencies: wgpu 30, winit 0.30, glam (math)
- Not published on crates.io (path dependency)
- Status: MVP complete (phases 1-5 ✅), post-MVP in progress (phase 6)
Detailed documentation (architecture, status, API reference, manual workflow): README_DETAILS.md
This project was heavily developed using OpenCode, Pi Code, and JCode AI agents running on local Qwen3-27b_Q4 and DeepSeek V4 Flash Q4 instances. The project organization and architecture are the author's own design.
Description
Languages
Rust
92.9%
WGSL
7.1%