//! This example compares Forward, Forward + Prepass, and Deferred rendering. use std::f32::consts::*; use bevy::{ core_pipeline::{ fxaa::Fxaa, prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass, NormalPrepass}, }, pbr::{ CascadeShadowConfigBuilder, DefaultOpaqueRendererMethod, DirectionalLightShadowMap, NotShadowCaster, NotShadowReceiver, OpaqueRendererMethod, }, prelude::*, render::texture::ImageLoaderSettings, }; fn main() { App::new() .insert_resource(DefaultOpaqueRendererMethod::deferred()) .insert_resource(DirectionalLightShadowMap { size: 4096 }) .add_plugins(DefaultPlugins) .insert_resource(Pause(true)) .add_systems(Startup, (setup, setup_parallax)) .add_systems(Update, (animate_light_direction, switch_mode, spin)) .run(); } fn setup( mut commands: Commands, asset_server: Res, mut materials: ResMut>, mut meshes: ResMut>, ) { commands.spawn(( Camera3dBundle { camera: Camera { // Deferred both supports both hdr: true and hdr: false hdr: false, ..default() }, transform: Transform::from_xyz(0.7, 0.7, 1.0) .looking_at(Vec3::new(0.0, 0.3, 0.0), Vec3::Y), // MSAA needs to be off for Deferred rendering msaa: Msaa::Off, ..default() }, DistanceFog { color: Color::srgb_u8(43, 44, 47), falloff: FogFalloff::Linear { start: 1.0, end: 8.0, }, ..default() }, EnvironmentMapLight { diffuse_map: asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2"), specular_map: asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2"), intensity: 2000.0, ..default() }, DepthPrepass, MotionVectorPrepass, DeferredPrepass, Fxaa::default(), )); commands.spawn(DirectionalLightBundle { directional_light: DirectionalLight { illuminance: 15_000., shadows_enabled: true, ..default() }, cascade_shadow_config: CascadeShadowConfigBuilder { num_cascades: 3, maximum_distance: 10.0, ..default() } .into(), transform: Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 0.0, -FRAC_PI_4)), ..default() }); // FlightHelmet let helmet_scene = asset_server .load(GltfAssetLabel::Scene(0).from_asset("models/FlightHelmet/FlightHelmet.gltf")); commands.spawn(SceneBundle { scene: helmet_scene.clone(), ..default() }); commands.spawn(SceneBundle { scene: helmet_scene, transform: Transform::from_xyz(-4.0, 0.0, -3.0), ..default() }); let mut forward_mat: StandardMaterial = Color::srgb(0.1, 0.2, 0.1).into(); forward_mat.opaque_render_method = OpaqueRendererMethod::Forward; let forward_mat_h = materials.add(forward_mat); // Plane commands.spawn(PbrBundle { mesh: meshes.add(Plane3d::default().mesh().size(50.0, 50.0)), material: forward_mat_h.clone(), ..default() }); let cube_h = meshes.add(Cuboid::new(0.1, 0.1, 0.1)); let sphere_h = meshes.add(Sphere::new(0.125).mesh().uv(32, 18)); // Cubes commands.spawn(PbrBundle { mesh: cube_h.clone(), material: forward_mat_h.clone(), transform: Transform::from_xyz(-0.3, 0.5, -0.2), ..default() }); commands.spawn(PbrBundle { mesh: cube_h, material: forward_mat_h, transform: Transform::from_xyz(0.2, 0.5, 0.2), ..default() }); let sphere_color = Color::srgb(10.0, 4.0, 1.0); let sphere_pos = Transform::from_xyz(0.4, 0.5, -0.8); // Emissive sphere let mut unlit_mat: StandardMaterial = sphere_color.into(); unlit_mat.unlit = true; commands.spawn(( PbrBundle { mesh: sphere_h.clone(), material: materials.add(unlit_mat), transform: sphere_pos, ..default() }, NotShadowCaster, )); // Light commands.spawn(PointLightBundle { point_light: PointLight { intensity: 800.0, radius: 0.125, shadows_enabled: true, color: sphere_color, ..default() }, transform: sphere_pos, ..default() }); // Spheres for i in 0..6 { let j = i % 3; let s_val = if i < 3 { 0.0 } else { 0.2 }; let material = if j == 0 { materials.add(StandardMaterial { base_color: Color::srgb(s_val, s_val, 1.0), perceptual_roughness: 0.089, metallic: 0.0, ..default() }) } else if j == 1 { materials.add(StandardMaterial { base_color: Color::srgb(s_val, 1.0, s_val), perceptual_roughness: 0.089, metallic: 0.0, ..default() }) } else { materials.add(StandardMaterial { base_color: Color::srgb(1.0, s_val, s_val), perceptual_roughness: 0.089, metallic: 0.0, ..default() }) }; commands.spawn(PbrBundle { mesh: sphere_h.clone(), material, transform: Transform::from_xyz( j as f32 * 0.25 + if i < 3 { -0.15 } else { 0.15 } - 0.4, 0.125, -j as f32 * 0.25 + if i < 3 { -0.15 } else { 0.15 } + 0.4, ), ..default() }); } // sky commands.spawn(( PbrBundle { mesh: meshes.add(Cuboid::new(2.0, 1.0, 1.0)), material: materials.add(StandardMaterial { base_color: Srgba::hex("888888").unwrap().into(), unlit: true, cull_mode: None, ..default() }), transform: Transform::from_scale(Vec3::splat(1_000_000.0)), ..default() }, NotShadowCaster, NotShadowReceiver, )); // Example instructions commands.spawn( TextBundle::from_section("", TextStyle::default()).with_style(Style { position_type: PositionType::Absolute, top: Val::Px(12.0), left: Val::Px(12.0), ..default() }), ); } #[derive(Resource)] struct Pause(bool); fn animate_light_direction( time: Res