//! Illustrates different lights of various types and colors, some static, some moving over //! a simple scene. use std::f32::consts::PI; use bevy::{pbr::CascadeShadowConfigBuilder, prelude::*}; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .add_systems(Update, (movement, animate_light_direction)) .run(); } #[derive(Component)] struct Movable; /// set up a simple 3D scene fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, asset_server: Res, ) { // ground plane commands.spawn(PbrBundle { mesh: meshes.add(shape::Plane::from_size(10.0).into()), material: materials.add(StandardMaterial { base_color: Color::WHITE, perceptual_roughness: 1.0, ..default() }), ..default() }); // left wall let mut transform = Transform::from_xyz(2.5, 2.5, 0.0); transform.rotate_z(PI / 2.); commands.spawn(PbrBundle { mesh: meshes.add(Mesh::from(shape::Box::new(5.0, 0.15, 5.0))), transform, material: materials.add(StandardMaterial { base_color: Color::INDIGO, perceptual_roughness: 1.0, ..default() }), ..default() }); // back (right) wall let mut transform = Transform::from_xyz(0.0, 2.5, -2.5); transform.rotate_x(PI / 2.); commands.spawn(PbrBundle { mesh: meshes.add(Mesh::from(shape::Box::new(5.0, 0.15, 5.0))), transform, material: materials.add(StandardMaterial { base_color: Color::INDIGO, perceptual_roughness: 1.0, ..default() }), ..default() }); // Bevy logo to demonstrate alpha mask shadows let mut transform = Transform::from_xyz(-2.2, 0.5, 1.0); transform.rotate_y(PI / 8.); commands.spawn(( PbrBundle { mesh: meshes.add(Mesh::from(shape::Quad::new(Vec2::new(2.0, 0.5)))), transform, material: materials.add(StandardMaterial { base_color_texture: Some(asset_server.load("branding/bevy_logo_light.png")), perceptual_roughness: 1.0, alpha_mode: AlphaMode::Mask(0.5), cull_mode: None, ..default() }), ..default() }, Movable, )); // cube commands.spawn(( PbrBundle { mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), material: materials.add(StandardMaterial { base_color: Color::PINK, ..default() }), transform: Transform::from_xyz(0.0, 0.5, 0.0), ..default() }, Movable, )); // sphere commands.spawn(( PbrBundle { mesh: meshes.add(Mesh::from(shape::UVSphere { radius: 0.5, ..default() })), material: materials.add(StandardMaterial { base_color: Color::LIME_GREEN, ..default() }), transform: Transform::from_xyz(1.5, 1.0, 1.5), ..default() }, Movable, )); // ambient light commands.insert_resource(AmbientLight { color: Color::ORANGE_RED, brightness: 0.02, }); // red point light commands .spawn(PointLightBundle { // transform: Transform::from_xyz(5.0, 8.0, 2.0), transform: Transform::from_xyz(1.0, 2.0, 0.0), point_light: PointLight { intensity: 1600.0, // lumens - roughly a 100W non-halogen incandescent bulb color: Color::RED, shadows_enabled: true, ..default() }, ..default() }) .with_children(|builder| { builder.spawn(PbrBundle { mesh: meshes.add(Mesh::from(shape::UVSphere { radius: 0.1, ..default() })), material: materials.add(StandardMaterial { base_color: Color::RED, emissive: Color::rgba_linear(7.13, 0.0, 0.0, 0.0), ..default() }), ..default() }); }); // green spot light commands .spawn(SpotLightBundle { transform: Transform::from_xyz(-1.0, 2.0, 0.0) .looking_at(Vec3::new(-1.0, 0.0, 0.0), Vec3::Z), spot_light: SpotLight { intensity: 1600.0, // lumens - roughly a 100W non-halogen incandescent bulb color: Color::GREEN, shadows_enabled: true, inner_angle: 0.6, outer_angle: 0.8, ..default() }, ..default() }) .with_children(|builder| { builder.spawn(PbrBundle { transform: Transform::from_rotation(Quat::from_rotation_x(PI / 2.0)), mesh: meshes.add(Mesh::from(shape::Capsule { depth: 0.125, radius: 0.1, ..default() })), material: materials.add(StandardMaterial { base_color: Color::GREEN, emissive: Color::rgba_linear(0.0, 7.13, 0.0, 0.0), ..default() }), ..default() }); }); // blue point light commands .spawn(PointLightBundle { // transform: Transform::from_xyz(5.0, 8.0, 2.0), transform: Transform::from_xyz(0.0, 4.0, 0.0), point_light: PointLight { intensity: 1600.0, // lumens - roughly a 100W non-halogen incandescent bulb color: Color::BLUE, shadows_enabled: true, ..default() }, ..default() }) .with_children(|builder| { builder.spawn(PbrBundle { mesh: meshes.add(Mesh::from(shape::UVSphere { radius: 0.1, ..default() })), material: materials.add(StandardMaterial { base_color: Color::BLUE, emissive: Color::rgba_linear(0.0, 0.0, 7.13, 0.0), ..default() }), ..default() }); }); // directional 'sun' light commands.spawn(DirectionalLightBundle { directional_light: DirectionalLight { shadows_enabled: true, ..default() }, transform: Transform { translation: Vec3::new(0.0, 2.0, 0.0), rotation: Quat::from_rotation_x(-PI / 4.), ..default() }, // The default cascade config is designed to handle large scenes. // As this example has a much smaller world, we can tighten the shadow // bounds for better visual quality. cascade_shadow_config: CascadeShadowConfigBuilder { first_cascade_far_bound: 4.0, maximum_distance: 10.0, ..default() } .into(), ..default() }); // camera commands.spawn(Camera3dBundle { transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y), ..default() }); // example instructions commands.spawn( TextBundle::from_section( "Use arrow keys to move objects", TextStyle { font_size: 20.0, ..default() }, ) .with_style(Style { position_type: PositionType::Absolute, top: Val::Px(12.0), left: Val::Px(12.0), ..default() }), ); } fn animate_light_direction( time: Res