From 804fca6eefbecfd636f3d7dd6abca397d9990345 Mon Sep 17 00:00:00 2001 From: IceSentry Date: Fri, 15 Nov 2024 23:14:25 -0500 Subject: [PATCH 01/17] wip --- Cargo.toml | 12 ++ examples/shader/custom_render_phase.rs | 176 +++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 examples/shader/custom_render_phase.rs diff --git a/Cargo.toml b/Cargo.toml index 56aac74f53cb9..a1d38c2b15b7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2608,6 +2608,18 @@ description = "A shader that renders a mesh multiple times in one draw call usin category = "Shaders" wasm = true +[[example]] +name = "custom_render_phase" +path = "examples/shader/custom_render_phase.rs" +doc-scrape-examples = true + +[package.metadata.example.custom_render_phase] +name = "Custom Render Phase" +description = "Shows how to make a complete render phase" +category = "Shaders" +wasm = true + + [[example]] name = "automatic_instancing" path = "examples/shader/automatic_instancing.rs" diff --git a/examples/shader/custom_render_phase.rs b/examples/shader/custom_render_phase.rs new file mode 100644 index 0000000000000..b2e362cc07bb3 --- /dev/null +++ b/examples/shader/custom_render_phase.rs @@ -0,0 +1,176 @@ +use bevy::{ + core_pipeline::oit::OrderIndependentTransparencySettings, prelude::*, scene::SceneInstance, + window::WindowResized, +}; +use bevy_render::camera::Viewport; +use rand::Rng; + +fn main() { + App::new() + .add_plugins(DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + resolution: Vec2::new(1920.0, 1080.0).into(), + ..default() + }), + ..default() + })) + .add_systems(Startup, setup) + .add_systems( + Update, + (exit, set_camera_viewports, rotate, replace_scene_materials), + ) + .run(); +} + +fn setup( + mut commands: Commands, + asset_server: Res, + mut meshes: ResMut>, + mut materials: ResMut>, +) { + // circular base + //commands.spawn(( + // Mesh3d(meshes.add(Circle::new(4.0))), + // MeshMaterial3d(materials.add(Color::WHITE)), + // Transform::from_rotation(Quat::from_rotation_x(-std::f32::consts::FRAC_PI_2)), + //)); + // light + commands.spawn(( + PointLight { + shadows_enabled: true, + ..default() + }, + Transform::from_xyz(4.0, 8.0, 4.0), + )); + + commands.spawn(( + SceneRoot( + asset_server + .load(GltfAssetLabel::Scene(0).from_asset("models/reconstructed_engine.glb")), + ), + //Transform::from_scale(Vec3::splat(0.035)), + Transform::from_scale(Vec3::splat(0.85)), + Rotate, + ReplaceStandardMaterial, + )); + + let camera_pos = + Transform::from_xyz(0.0, 5.0, 10.0).looking_at(Vec3::new(0.0, 0.5, 0.0), Vec3::Y); + let text = ["OIT enabled", "OIT disabled"]; + for index in 0..2 { + let mut camera = commands.spawn(( + Camera3d::default(), + camera_pos.clone(), + Camera { + order: index as isize, + ..default() + }, + CameraPosition { + pos: UVec2::new((index % 2) as u32, (index / 2) as u32), + }, + Msaa::Off, + )); + if index == 0 { + camera.insert(OrderIndependentTransparencySettings { + layer_count: 32, + //alpha_threshold: 0.05, + ..default() + }); + } + let camera_id = camera.id(); + // Set up UI + commands + .spawn(( + TargetCamera(camera_id), + Node { + width: Val::Percent(100.), + height: Val::Percent(100.), + ..default() + }, + )) + .with_children(|parent| { + parent.spawn(( + Text::new(text[index]), + TextFont { + font_size: 24.0, + ..default() + }, + Node { + position_type: PositionType::Absolute, + top: Val::Px(12.), + left: Val::Px(12.), + ..default() + }, + )); + }); + } +} + +fn exit(input: Res>) { + if input.just_pressed(KeyCode::KeyQ) { + std::process::exit(0); + } +} + +#[derive(Component)] +struct CameraPosition { + pos: UVec2, +} + +fn set_camera_viewports( + windows: Query<&Window>, + mut resize_events: EventReader, + mut query: Query<(&CameraPosition, &mut Camera)>, +) { + // We need to dynamically resize the camera's viewports whenever the window size changes + // so then each camera always takes up half the screen. + // A resize_event is sent when the window is first created, allowing us to reuse this system for initial setup. + for resize_event in resize_events.read() { + let window = windows.get(resize_event.window).unwrap(); + let size = UVec2::new(window.physical_size().x / 2, window.physical_size().y); + + for (camera_position, mut camera) in &mut query { + camera.viewport = Some(Viewport { + physical_position: camera_position.pos * size, + physical_size: size, + ..default() + }); + } + } +} +#[derive(Component)] +struct Rotate; + +fn rotate(mut q: Query<&mut Transform, With>, time: Res