130 lines
4.2 KiB
Markdown
130 lines
4.2 KiB
Markdown
# Quickstart
|
|
|
|
Get a window with a rotating cube on screen in ~30 lines. The full version with comments is
|
|
in the [`simple`](../../lib/examples/meshes/simple.rs) example (2D quad, unlit) and
|
|
[`cube`](../../lib/examples/meshes/cube.rs) (3D cube, lit).
|
|
|
|
## 1. Add the dependency
|
|
|
|
```toml
|
|
# Cargo.toml
|
|
[dependencies]
|
|
wsg-lib = { path = "../lib" }
|
|
glam = "0.29" # Vec3/Quat — re-exported but you need it in your own code
|
|
winit = "0.30" # KeyCode/MouseButton for the input (only if you use app.input)
|
|
```
|
|
|
|
> The workspace pins `glam 0.29` and `winit 0.30`; match these versions to avoid
|
|
> type mismatches.
|
|
|
|
## 2. Implement `AppHandler`
|
|
|
|
Three mandatory methods (`setup`, `update`, `render`) and an optional event hook.
|
|
|
|
```rust
|
|
use glam::{Quat, Vec3};
|
|
use winit::event::MouseButton;
|
|
use winit::keyboard::KeyCode;
|
|
use wsg_lib::camera::CameraController;
|
|
use wsg_lib::prelude::*;
|
|
|
|
struct MyHandler {
|
|
camera: CameraController,
|
|
}
|
|
|
|
impl AppHandler for MyHandler {
|
|
fn new() -> Self {
|
|
Self { camera: CameraController::default() }
|
|
}
|
|
|
|
fn setup(&mut self, app: &mut App) -> Result<(), String> {
|
|
// A cube (primitive) + the standard material.
|
|
app.scene.create_mesh("cube_mesh", cube(1.0), Some("cube_mat"))?;
|
|
app.scene.add_entity("cube", "cube_mesh")?;
|
|
|
|
// A warm directional light + shadows on it.
|
|
app.scene
|
|
.add_directional_light(Vec3::new(1.0, 1.2, 1.0).normalize(), [1.0, 0.98, 0.92], 1.5)?;
|
|
app.scene.set_shadow_caster(Some(0));
|
|
Ok(())
|
|
}
|
|
|
|
fn update(&mut self, app: &mut App) {
|
|
// Spin the cube.
|
|
let mut tf = *app.scene.entity_transform("cube").unwrap();
|
|
tf.rotation = Quat::from_rotation_y(self.t) * tf.rotation;
|
|
app.scene.set_entity_transform("cube", tf);
|
|
self.t += 0.02;
|
|
|
|
// Camera: orbit (left-drag), zoom (wheel), reset (R), presets (1/2/3).
|
|
let (dx, dy) = app.input.mouse_delta();
|
|
if app.input.mouse_button_held(MouseButton::Left) {
|
|
self.camera.orbit(dx, dy);
|
|
}
|
|
let (_, sy) = app.input.scroll_delta();
|
|
self.camera.zoom(sy);
|
|
if app.input.key_pressed(KeyCode::KeyR) {
|
|
self.camera.yaw = 0.6;
|
|
self.camera.pitch = 0.35;
|
|
self.camera.distance = 6.5;
|
|
}
|
|
self.camera.apply_to(app.scene.camera_mut());
|
|
}
|
|
|
|
fn render(&mut self, app: &mut App) -> Result<(), String> {
|
|
// Default implementation: renders the whole scene. Override only for custom passes.
|
|
app.renderer().render_scene(app.context())
|
|
}
|
|
}
|
|
```
|
|
|
|
## 3. Build the app
|
|
|
|
```rust
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
let app = AppBuilder::new()
|
|
.title("My WSG app")
|
|
.size(1024, 768)
|
|
.with_culling(true) // optional: skip off-screen entities
|
|
.with_shadows() // optional: enable shadow mapping
|
|
.build()
|
|
.await?;
|
|
|
|
let mut handler = MyHandler::new();
|
|
app.run(&mut handler).await?;
|
|
Ok(())
|
|
}
|
|
```
|
|
|
|
`AppBuilder` methods you will use early:
|
|
|
|
| Method | Purpose |
|
|
|--------|---------|
|
|
| `.title(…)` / `.size(w, h)` | Window |
|
|
| `.with_vsync(false)` / `.with_frame_limit(n)` | Frame pacing (vsync off + 144 fps cap in the `demo`) |
|
|
| `.with_culling(true)` | Opt-in frustum culling (see [GPU-driven](cameras/gpu-driven.md)) |
|
|
| `.with_shadows()` | Opt-in shadow mapping (see [Shadows](lights/shadows.md)) |
|
|
| `.with_hdr(ToneMapper::Aces)` | Opt-in HDR + tone mapping (see [HDR](effects/hdr.md)) |
|
|
|
|
## 4. Run it
|
|
|
|
```sh
|
|
cargo run -p wsg-lib --example cube # the reference "hello world" of the engine
|
|
```
|
|
|
|
Controls (in the `cube`/`demo` examples): **left-drag** orbit, **wheel** zoom, **R** reset
|
|
camera, **1/2/3** view presets, **H** help overlay, **Esc** quit.
|
|
|
|
## 5. Where to go next
|
|
|
|
- [Meshes](meshes/meshes.md) — entities, transforms, custom geometries
|
|
- [Materials & textures](meshes/materials.md) — diffuse textures, unlit mode
|
|
- [Lights](lights/lights.md) — point/spot lights, ambient
|
|
- [Camera & input](cameras/camera-input.md) — the full input API
|
|
- [GPU-driven](cameras/gpu-driven.md) — culling, LOD, debugging the GPU path
|
|
|
|
## Links
|
|
|
|
- [User README](README.md) · [Meshes](meshes/meshes.md) · [Examples](examples.md)
|
|
- [Root README](../../README.md) · [FRAME_LOOP](../tech/FRAME_LOOP.md)
|