From ca8625c407cbd3fc0a7e4855044da698cf9390c0 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Tue, 23 Jun 2020 15:58:06 -0700 Subject: [PATCH] render: ActiveCameras resource and system --- .../bevy_render/src/base_render_graph/mod.rs | 6 +- .../bevy_render/src/camera/active_cameras.rs | 44 ++++++++++++ crates/bevy_render/src/camera/mod.rs | 2 + crates/bevy_render/src/entity.rs | 4 +- crates/bevy_render/src/lib.rs | 13 ++++ .../src/render_graph/nodes/camera_node.rs | 69 ++++++++++--------- crates/bevy_ui/src/render/mod.rs | 8 ++- 7 files changed, 106 insertions(+), 40 deletions(-) create mode 100644 crates/bevy_render/src/camera/active_cameras.rs diff --git a/crates/bevy_render/src/base_render_graph/mod.rs b/crates/bevy_render/src/base_render_graph/mod.rs index 7add9c11c5..8d7d4dac00 100644 --- a/crates/bevy_render/src/base_render_graph/mod.rs +++ b/crates/bevy_render/src/base_render_graph/mod.rs @@ -34,7 +34,7 @@ pub mod node { pub const SHARED_BUFFERS: &str = "shared_buffers"; } -pub mod uniform { +pub mod camera { pub const CAMERA: &str = "Camera"; pub const CAMERA2D: &str = "Camera2d"; } @@ -62,11 +62,11 @@ impl BaseRenderGraphBuilder for RenderGraph { fn add_base_graph(&mut self, config: &BaseRenderGraphConfig) -> &mut Self { self.add_node(node::TEXTURE_COPY, TextureCopyNode::default()); if config.add_3d_camera { - self.add_system_node(node::CAMERA, CameraNode::new(uniform::CAMERA)); + self.add_system_node(node::CAMERA, CameraNode::new(camera::CAMERA)); } if config.add_2d_camera { - self.add_system_node(node::CAMERA2D, CameraNode::new(uniform::CAMERA2D)); + self.add_system_node(node::CAMERA2D, CameraNode::new(camera::CAMERA2D)); } self.add_node(node::SHARED_BUFFERS, SharedBuffersNode::default()); diff --git a/crates/bevy_render/src/camera/active_cameras.rs b/crates/bevy_render/src/camera/active_cameras.rs new file mode 100644 index 0000000000..e2208308a8 --- /dev/null +++ b/crates/bevy_render/src/camera/active_cameras.rs @@ -0,0 +1,44 @@ +use crate::Camera; +use legion::{ + entity::Entity, + prelude::Read, + systems::{Query, ResMut, SubWorld}, +}; +use std::collections::HashMap; + +#[derive(Default)] +pub struct ActiveCameras { + pub cameras: HashMap>, +} + +impl ActiveCameras { + pub fn add(&mut self, name: &str) { + self.cameras.insert(name.to_string(), None); + } + + pub fn set(&mut self, name: &str, entity: Entity) { + self.cameras.insert(name.to_string(), Some(entity)); + } + + pub fn get(&self, name: &str) -> Option { + self.cameras.get(name).and_then(|e| e.clone()) + } +} + +pub fn active_cameras_system( + world: &mut SubWorld, + mut active_cameras: ResMut, + query: &mut Query>, +) { + for (name, active_camera) in active_cameras.cameras.iter_mut() { + if let None = active_camera { + for (camera_entity, camera) in query.iter_entities(world) { + if let Some(ref current_name) = camera.name { + if current_name == name { + *active_camera = Some(camera_entity); + } + } + } + } + } +} diff --git a/crates/bevy_render/src/camera/mod.rs b/crates/bevy_render/src/camera/mod.rs index ef6647284c..b9837db8ee 100644 --- a/crates/bevy_render/src/camera/mod.rs +++ b/crates/bevy_render/src/camera/mod.rs @@ -1,7 +1,9 @@ +mod active_cameras; mod camera; mod projection; mod visible_entities; +pub use active_cameras::*; pub use camera::*; pub use projection::*; pub use visible_entities::*; diff --git a/crates/bevy_render/src/entity.rs b/crates/bevy_render/src/entity.rs index 49ae1a374a..c55c5df4f7 100644 --- a/crates/bevy_render/src/entity.rs +++ b/crates/bevy_render/src/entity.rs @@ -33,7 +33,7 @@ impl Default for PerspectiveCameraEntity { fn default() -> Self { PerspectiveCameraEntity { camera: Camera { - name: Some(base_render_graph::uniform::CAMERA.to_string()), + name: Some(base_render_graph::camera::CAMERA.to_string()), ..Default::default() }, perspective_projection: Default::default(), @@ -81,7 +81,7 @@ impl Default for OrthographicCameraEntity { fn default() -> Self { OrthographicCameraEntity { camera: Camera { - name: Some(base_render_graph::uniform::CAMERA2D.to_string()), + name: Some(base_render_graph::camera::CAMERA2D.to_string()), ..Default::default() }, orthographic_projection: Default::default(), diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 56d5570749..e8b687b94a 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -94,7 +94,12 @@ impl AppPlugin for RenderPlugin { .init_resource::() .init_resource::() .init_resource::() + .init_resource::() .add_system_to_stage(bevy_app::stage::PRE_UPDATE, clear_draw_system.system()) + .add_system_to_stage( + bevy_app::stage::POST_UPDATE, + camera::active_cameras_system.system(), + ) .add_system_to_stage( bevy_app::stage::POST_UPDATE, camera::camera_system::(), @@ -125,6 +130,14 @@ impl AppPlugin for RenderPlugin { let resources = app.resources(); let mut render_graph = resources.get_mut::().unwrap(); render_graph.add_base_graph(config); + let mut active_cameras = resources.get_mut::().unwrap(); + if config.add_3d_camera { + active_cameras.add(base_render_graph::camera::CAMERA); + } + + if config.add_2d_camera { + active_cameras.add(base_render_graph::camera::CAMERA2D); + } } } } diff --git a/crates/bevy_render/src/render_graph/nodes/camera_node.rs b/crates/bevy_render/src/render_graph/nodes/camera_node.rs index 6cc0ec59d9..08c859516c 100644 --- a/crates/bevy_render/src/render_graph/nodes/camera_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/camera_node.rs @@ -2,7 +2,7 @@ use crate::{ render_graph::{CommandQueue, Node, ResourceSlots, SystemNode}, render_resource::{BufferInfo, BufferUsage, RenderResourceBinding, RenderResourceBindings}, renderer::{RenderContext, RenderResourceContext}, - Camera, + ActiveCameras, Camera, }; use bevy_core::bytes::AsBytes; @@ -12,17 +12,17 @@ use std::borrow::Cow; pub struct CameraNode { command_queue: CommandQueue, - uniform_name: Cow<'static, str>, + camera_name: Cow<'static, str>, } impl CameraNode { - pub fn new(uniform_name: T) -> Self + pub fn new(camera_name: T) -> Self where T: Into>, { CameraNode { command_queue: Default::default(), - uniform_name: uniform_name.into(), + camera_name: camera_name.into(), } } } @@ -44,13 +44,14 @@ impl SystemNode for CameraNode { fn get_system(&self) -> Box { let mut camera_buffer = None; let mut command_queue = self.command_queue.clone(); - let uniform_name = self.uniform_name.clone(); + let camera_name = self.camera_name.clone(); (move |world: &mut SubWorld, + active_cameras: Res, render_resource_context: Res>, // PERF: this write on RenderResourceAssignments will prevent this system from running in parallel // with other systems that do the same mut render_resource_bindings: ResMut, - query: &mut Query<(Read, Read)>| { + _query: &mut Query<(Read, Read)>| { let render_resource_context = &**render_resource_context; if camera_buffer.is_none() { let size = std::mem::size_of::<[[f32; 4]; 4]>(); @@ -60,7 +61,7 @@ impl SystemNode for CameraNode { ..Default::default() }); render_resource_bindings.set( - &uniform_name, + &camera_name, RenderResourceBinding::Buffer { buffer, range: 0..size as u64, @@ -69,34 +70,38 @@ impl SystemNode for CameraNode { ); camera_buffer = Some(buffer); } - let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); - if let Some((camera, transform)) = query - .iter(world) - .find(|(camera, _)| camera.name.as_ref().map(|n| n.as_str()) == Some(&uniform_name)) + let (camera, transform) = if let Some(camera_entity) = active_cameras.get(&camera_name) { - let camera_matrix: [f32; 16] = - (camera.view_matrix * transform.value).to_cols_array(); + ( + world.get_component::(camera_entity).unwrap(), + world.get_component::(camera_entity).unwrap(), + ) + } else { + return; + }; - let tmp_buffer = render_resource_context.create_buffer_mapped( - BufferInfo { - size: matrix_size, - buffer_usage: BufferUsage::COPY_SRC, - ..Default::default() - }, - &mut |data, _renderer| { - data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes()); - }, - ); + let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); + let camera_matrix: [f32; 16] = (camera.view_matrix * transform.value).to_cols_array(); - command_queue.copy_buffer_to_buffer( - tmp_buffer, - 0, - camera_buffer.unwrap(), - 0, - matrix_size as u64, - ); - command_queue.free_buffer(tmp_buffer); - } + let tmp_buffer = render_resource_context.create_buffer_mapped( + BufferInfo { + size: matrix_size, + buffer_usage: BufferUsage::COPY_SRC, + ..Default::default() + }, + &mut |data, _renderer| { + data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes()); + }, + ); + + command_queue.copy_buffer_to_buffer( + tmp_buffer, + 0, + camera_buffer.unwrap(), + 0, + matrix_size as u64, + ); + command_queue.free_buffer(tmp_buffer); }) .system() } diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index 70f2479abd..a8cc20d50a 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -4,7 +4,7 @@ use bevy_render::{ pipeline::{state_descriptors::*, PipelineDescriptor}, render_graph::{nodes::CameraNode, RenderGraph}, shader::{Shader, ShaderStage, ShaderStages}, - texture::TextureFormat, + texture::TextureFormat, ActiveCameras, }; use legion::prelude::Resources; @@ -60,7 +60,7 @@ pub mod node { pub const UI_CAMERA: &'static str = "ui_camera"; } -pub mod uniform { +pub mod camera { pub const UI_CAMERA: &'static str = "UiCamera"; } @@ -70,12 +70,14 @@ pub trait UiRenderGraphBuilder { impl UiRenderGraphBuilder for RenderGraph { fn add_ui_graph(&mut self, resources: &Resources) -> &mut Self { - self.add_system_node(node::UI_CAMERA, CameraNode::new(uniform::UI_CAMERA)); + self.add_system_node(node::UI_CAMERA, CameraNode::new(camera::UI_CAMERA)); self.add_node_edge(node::UI_CAMERA, base_render_graph::node::MAIN_PASS) .unwrap(); let mut pipelines = resources.get_mut::>().unwrap(); let mut shaders = resources.get_mut::>().unwrap(); pipelines.set(UI_PIPELINE_HANDLE, build_ui_pipeline(&mut shaders)); + let mut active_cameras = resources.get_mut::().unwrap(); + active_cameras.add(camera::UI_CAMERA); self } }