diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index a1665032a7..973ce35f6b 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -11,6 +11,20 @@ pub struct Camera { pub name: Option, #[property(ignore)] pub window: WindowId, + #[property(ignore)] + pub depth_calculation: DepthCalculation, +} + +#[derive(Debug)] +pub enum DepthCalculation { + Distance, + ZDifference, +} + +impl Default for DepthCalculation { + fn default() -> Self { + DepthCalculation::Distance + } } #[derive(Default)] @@ -55,8 +69,11 @@ pub fn camera_system( for (mut camera, mut camera_projection) in &mut query.iter() { if let Some(window) = windows.get(camera.window) { - camera_projection.update(window.width as usize, window.height as usize); - camera.projection_matrix = camera_projection.get_projection_matrix(); + if changed_window_ids.contains(&window.id) { + camera_projection.update(window.width as usize, window.height as usize); + camera.projection_matrix = camera_projection.get_projection_matrix(); + camera.depth_calculation = camera_projection.depth_calculation(); + } } } } diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index 1c596f42dd..8faea7ee18 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -1,10 +1,12 @@ use bevy_math::{Mat4, PerspectiveRh}; use bevy_property::{Properties, Property}; use serde::{Deserialize, Serialize}; +use super::DepthCalculation; pub trait CameraProjection { fn get_projection_matrix(&self) -> Mat4; fn update(&mut self, width: usize, height: usize); + fn depth_calculation(&self) -> DepthCalculation; } #[derive(Debug, Clone, Properties)] @@ -23,6 +25,10 @@ impl CameraProjection for PerspectiveProjection { fn update(&mut self, width: usize, height: usize) { self.aspect_ratio = width as f32 / height as f32; } + + fn depth_calculation(&self) -> DepthCalculation { + DepthCalculation::Distance + } } impl Default for PerspectiveProjection { @@ -84,6 +90,10 @@ impl CameraProjection for OrthographicProjection { } } } + + fn depth_calculation(&self) -> DepthCalculation { + DepthCalculation::ZDifference + } } impl Default for OrthographicProjection { diff --git a/crates/bevy_render/src/camera/visible_entities.rs b/crates/bevy_render/src/camera/visible_entities.rs index ea55afb128..4176e66ef4 100644 --- a/crates/bevy_render/src/camera/visible_entities.rs +++ b/crates/bevy_render/src/camera/visible_entities.rs @@ -1,4 +1,4 @@ -use super::Camera; +use super::{Camera, DepthCalculation}; use crate::Draw; use bevy_core::FloatOrd; use bevy_ecs::{Entity, Query}; @@ -26,7 +26,7 @@ pub fn visible_entities_system( mut draw_query: Query<(Entity, &Draw)>, draw_transform_query: Query<(&Draw, &Transform)>, ) { - for (_camera, camera_transform, mut visible_entities) in &mut camera_query.iter() { + for (camera, camera_transform, mut visible_entities) in &mut camera_query.iter() { visible_entities.value.clear(); let camera_position = camera_transform.value.w_axis().truncate(); @@ -40,7 +40,10 @@ pub fn visible_entities_system( let order = if let Ok(transform) = draw_transform_query.get::(entity) { let position = transform.value.w_axis().truncate(); // smaller distances are sorted to lower indices by using the distance from the camera - FloatOrd((camera_position - position).length()) + FloatOrd(match camera.depth_calculation { + DepthCalculation::ZDifference => camera_position.z() - position.z(), + DepthCalculation::Distance => (camera_position - position).length(), + }) } else { let order = FloatOrd(no_transform_order); no_transform_order += 0.1; diff --git a/crates/bevy_ui/src/lib.rs b/crates/bevy_ui/src/lib.rs index 2c274166f1..29b42152ff 100644 --- a/crates/bevy_ui/src/lib.rs +++ b/crates/bevy_ui/src/lib.rs @@ -32,15 +32,20 @@ use update::ui_z_system; #[derive(Default)] pub struct UiPlugin; +pub mod stage { + pub const UI: &'static str = "ui"; +} + impl AppPlugin for UiPlugin { fn build(&self, app: &mut AppBuilder) { app.init_resource::() - .add_system_to_stage(stage::PRE_UPDATE, ui_focus_system.system()) + .add_stage_before(bevy_app::stage::POST_UPDATE, stage::UI) + .add_system_to_stage(bevy_app::stage::PRE_UPDATE, ui_focus_system.system()) // add these stages to front because these must run before transform update systems - .add_system_to_stage_front(stage::POST_UPDATE, flex_node_system.system()) - .add_system_to_stage_front(stage::POST_UPDATE, ui_z_system.system()) - .add_system_to_stage_front(stage::POST_UPDATE, widget::text_system.system()) - .add_system_to_stage_front(stage::POST_UPDATE, widget::image_node_system.system()) + .add_system_to_stage(stage::UI, widget::text_system.system()) + .add_system_to_stage(stage::UI, widget::image_node_system.system()) + .add_system_to_stage(stage::UI, ui_z_system.system()) + .add_system_to_stage(stage::UI, flex_node_system.system()) .add_system_to_stage(bevy_render::stage::DRAW, widget::draw_text_system.system()); let resources = app.resources(); diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index ee7a187fc7..e1a94ce560 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -3,10 +3,17 @@ use bevy_asset::{Assets, Handle}; use bevy_ecs::Resources; use bevy_render::{ camera::ActiveCameras, + pass::{ + LoadOp, Operations, PassDescriptor, RenderPassColorAttachmentDescriptor, + RenderPassDepthStencilAttachmentDescriptor, TextureAttachment, + }, pipeline::*, - render_graph::{base, CameraNode, PassNode, RenderGraph, RenderResourcesNode, WindowSwapChainNode, WindowTextureNode}, + render_graph::{ + base, CameraNode, PassNode, RenderGraph, RenderResourcesNode, WindowSwapChainNode, + WindowTextureNode, + }, shader::{Shader, ShaderStage, ShaderStages}, - texture::TextureFormat, prelude::{Color, MainPass}, pass::{RenderPassColorAttachmentDescriptor, PassDescriptor, TextureAttachment, LoadOp, Operations, RenderPassDepthStencilAttachmentDescriptor}, + texture::TextureFormat, }; pub const UI_PIPELINE_HANDLE: Handle = @@ -121,11 +128,9 @@ impl UiRenderGraphBuilder for RenderGraph { // setup ui camera self.add_system_node(node::UI_CAMERA, CameraNode::new(camera::UI_CAMERA)); - self.add_node_edge(node::UI_CAMERA, node::UI_PASS) - .unwrap(); + self.add_node_edge(node::UI_CAMERA, node::UI_PASS).unwrap(); self.add_system_node(node::NODE, RenderResourcesNode::::new(true)); - self.add_node_edge(node::NODE, node::UI_PASS) - .unwrap(); + self.add_node_edge(node::NODE, node::UI_PASS).unwrap(); let mut active_cameras = resources.get_mut::().unwrap(); active_cameras.add(camera::UI_CAMERA); self diff --git a/crates/bevy_ui/src/update.rs b/crates/bevy_ui/src/update.rs index 4d041c199a..aa66b223d1 100644 --- a/crates/bevy_ui/src/update.rs +++ b/crates/bevy_ui/src/update.rs @@ -12,7 +12,7 @@ pub fn ui_z_system( mut node_query: Query<(Entity, &Node, &mut LocalTransform)>, children_query: Query<&Children>, ) { - let mut window_z = 0.0; + let mut current_global_z = 0.0; // PERF: we can probably avoid an allocation here by making root_node_query and node_query non-overlapping let root_nodes = (&mut root_node_query.iter()) @@ -24,11 +24,11 @@ pub fn ui_z_system( &children_query, &mut node_query, entity, - Some(window_z), - Some(window_z), + Some(current_global_z), + Some(current_global_z), &mut update_node_entity, ) { - window_z = result; + current_global_z = result; } } } @@ -36,18 +36,20 @@ pub fn ui_z_system( fn update_node_entity( node_query: &mut Query<(Entity, &Node, &mut LocalTransform)>, entity: Entity, - _parent_result: Option, + parent_result: Option, previous_result: Option, ) -> Option { let mut transform = node_query.get_mut::(entity).unwrap(); let mut z = UI_Z_STEP; - if let Some(previous_z) = previous_result { - z += previous_z; + let parent_global_z = parent_result.unwrap(); + if let Some(previous_global_z) = previous_result { + z += previous_global_z - parent_global_z; }; + let global_z = z + parent_global_z; let mut position = transform.w_axis(); position.set_z(z); transform.set_w_axis(position); - return Some(z); + return Some(global_z); }