réorg doc
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
//! Test dedicated to **spot lights**.
|
||||
//!
|
||||
//! In this example, **only** a spot light is on (the default directional light is
|
||||
//! removed via `clear_lights()`) and the ambient is deliberately **very low**. The cube therefore
|
||||
//! appears nearly black except where the spot's cone reaches it: you clearly see
|
||||
//!
|
||||
//! 1. a **directed beam** (not an omni halo like the point light),
|
||||
//! 2. a **smoothed edge** (penumbra) at the cone's limit,
|
||||
//! 3. the lighting that **follows the cube** as it rotates (the cone is fixed in world space).
|
||||
//!
|
||||
//! Run with: `cargo run -p wsg-lib --example spot_test`
|
||||
use glam::{Quat, Vec3};
|
||||
use wsg_lib::AppHandler;
|
||||
use wsg_lib::app::AppBuilder;
|
||||
use wsg_lib::mesh::cube;
|
||||
use wsg_lib::utils::WsgError;
|
||||
|
||||
/// Test handler: cube rotating slowly on two axes, lit **only** by a spot.
|
||||
struct SpotTest {
|
||||
angle_x: f32,
|
||||
angle_y: f32,
|
||||
}
|
||||
|
||||
impl AppHandler for SpotTest {
|
||||
fn setup(&mut self, app: &mut wsg_lib::App) {
|
||||
app.scene
|
||||
.register_shader("standard", wsg_lib::utils::STANDARD_SHADER_PATH)
|
||||
.unwrap();
|
||||
app.scene.add_material_shader("mat", "standard").unwrap();
|
||||
app.scene
|
||||
.create_mesh("cube_mesh", cube(1.0), Some("mat"))
|
||||
.unwrap();
|
||||
app.scene.add_entity("cube", "cube_mesh").unwrap();
|
||||
|
||||
// Remove the default directional light to isolate the spot.
|
||||
app.scene.clear_lights();
|
||||
// Near-zero ambient: the cube is black outside the beam, the cone stands out.
|
||||
app.scene.set_ambient([0.03, 0.03, 0.03]);
|
||||
|
||||
// The spot is above/behind the camera, aimed at the origin (the cube).
|
||||
// World position (0, 2, 3), cone axis toward (0,0,0).
|
||||
let spot_pos = Vec3::new(0.0, 2.0, 3.0);
|
||||
let spot_dir = (Vec3::ZERO - spot_pos).normalize(); // points at the cube
|
||||
app.scene
|
||||
.add_spot_light(
|
||||
spot_pos,
|
||||
spot_dir,
|
||||
[1.0, 0.9, 0.6], // warm tint
|
||||
2.0, // intensity
|
||||
10.0, // attenuation radius (wide, the cube is at ~3.6)
|
||||
0.45, // half-angle (~26°) — wide enough to cover the cube
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn update(&mut self, app: &mut wsg_lib::App) {
|
||||
// Slow rotation on two axes (X and Y): the cone is fixed in world space,
|
||||
// so a fixed region of the cube stays lit while the cube rotates.
|
||||
// The two axes let you see the beam's effect on the 6 faces without
|
||||
// a favored orientation (a Y rotation alone would leave the +Y/-Y faces fixed).
|
||||
self.angle_x += 0.007;
|
||||
self.angle_y += 0.011;
|
||||
let base = *app
|
||||
.scene
|
||||
.entity_transform("cube")
|
||||
.expect("cube entity present");
|
||||
let mut transform = base;
|
||||
// Y * X composition: the X axis rotates in the frame already oriented by Y,
|
||||
// which gives a precession motion (all vertices pass in front of
|
||||
// the cone in turn).
|
||||
transform.rotation =
|
||||
Quat::from_rotation_y(self.angle_y) * Quat::from_rotation_x(self.angle_x);
|
||||
app.scene.set_entity_transform("cube", transform);
|
||||
}
|
||||
}
|
||||
|
||||
#[pollster::main]
|
||||
async fn main() -> Result<(), WsgError> {
|
||||
let app = AppBuilder::new().title("WSG Spot Test").build().await?;
|
||||
app.run(SpotTest {
|
||||
angle_x: 0.0,
|
||||
angle_y: 0.0,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user