render: ActiveCameras resource and system
This commit is contained in:
parent
b6dbbf04db
commit
ca8625c407
@ -34,7 +34,7 @@ pub mod node {
|
|||||||
pub const SHARED_BUFFERS: &str = "shared_buffers";
|
pub const SHARED_BUFFERS: &str = "shared_buffers";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod uniform {
|
pub mod camera {
|
||||||
pub const CAMERA: &str = "Camera";
|
pub const CAMERA: &str = "Camera";
|
||||||
pub const CAMERA2D: &str = "Camera2d";
|
pub const CAMERA2D: &str = "Camera2d";
|
||||||
}
|
}
|
||||||
@ -62,11 +62,11 @@ impl BaseRenderGraphBuilder for RenderGraph {
|
|||||||
fn add_base_graph(&mut self, config: &BaseRenderGraphConfig) -> &mut Self {
|
fn add_base_graph(&mut self, config: &BaseRenderGraphConfig) -> &mut Self {
|
||||||
self.add_node(node::TEXTURE_COPY, TextureCopyNode::default());
|
self.add_node(node::TEXTURE_COPY, TextureCopyNode::default());
|
||||||
if config.add_3d_camera {
|
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 {
|
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());
|
self.add_node(node::SHARED_BUFFERS, SharedBuffersNode::default());
|
||||||
|
44
crates/bevy_render/src/camera/active_cameras.rs
Normal file
44
crates/bevy_render/src/camera/active_cameras.rs
Normal file
@ -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<String, Option<Entity>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Entity> {
|
||||||
|
self.cameras.get(name).and_then(|e| e.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn active_cameras_system(
|
||||||
|
world: &mut SubWorld,
|
||||||
|
mut active_cameras: ResMut<ActiveCameras>,
|
||||||
|
query: &mut Query<Read<Camera>>,
|
||||||
|
) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
|
mod active_cameras;
|
||||||
mod camera;
|
mod camera;
|
||||||
mod projection;
|
mod projection;
|
||||||
mod visible_entities;
|
mod visible_entities;
|
||||||
|
|
||||||
|
pub use active_cameras::*;
|
||||||
pub use camera::*;
|
pub use camera::*;
|
||||||
pub use projection::*;
|
pub use projection::*;
|
||||||
pub use visible_entities::*;
|
pub use visible_entities::*;
|
||||||
|
@ -33,7 +33,7 @@ impl Default for PerspectiveCameraEntity {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
PerspectiveCameraEntity {
|
PerspectiveCameraEntity {
|
||||||
camera: Camera {
|
camera: Camera {
|
||||||
name: Some(base_render_graph::uniform::CAMERA.to_string()),
|
name: Some(base_render_graph::camera::CAMERA.to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
perspective_projection: Default::default(),
|
perspective_projection: Default::default(),
|
||||||
@ -81,7 +81,7 @@ impl Default for OrthographicCameraEntity {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
OrthographicCameraEntity {
|
OrthographicCameraEntity {
|
||||||
camera: Camera {
|
camera: Camera {
|
||||||
name: Some(base_render_graph::uniform::CAMERA2D.to_string()),
|
name: Some(base_render_graph::camera::CAMERA2D.to_string()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
orthographic_projection: Default::default(),
|
orthographic_projection: Default::default(),
|
||||||
|
@ -94,7 +94,12 @@ impl AppPlugin for RenderPlugin {
|
|||||||
.init_resource::<VertexBufferDescriptors>()
|
.init_resource::<VertexBufferDescriptors>()
|
||||||
.init_resource::<TextureResourceSystemState>()
|
.init_resource::<TextureResourceSystemState>()
|
||||||
.init_resource::<AssetRenderResourceBindings>()
|
.init_resource::<AssetRenderResourceBindings>()
|
||||||
|
.init_resource::<ActiveCameras>()
|
||||||
.add_system_to_stage(bevy_app::stage::PRE_UPDATE, clear_draw_system.system())
|
.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(
|
.add_system_to_stage(
|
||||||
bevy_app::stage::POST_UPDATE,
|
bevy_app::stage::POST_UPDATE,
|
||||||
camera::camera_system::<OrthographicProjection>(),
|
camera::camera_system::<OrthographicProjection>(),
|
||||||
@ -125,6 +130,14 @@ impl AppPlugin for RenderPlugin {
|
|||||||
let resources = app.resources();
|
let resources = app.resources();
|
||||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||||
render_graph.add_base_graph(config);
|
render_graph.add_base_graph(config);
|
||||||
|
let mut active_cameras = resources.get_mut::<ActiveCameras>().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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::{
|
|||||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||||
render_resource::{BufferInfo, BufferUsage, RenderResourceBinding, RenderResourceBindings},
|
render_resource::{BufferInfo, BufferUsage, RenderResourceBinding, RenderResourceBindings},
|
||||||
renderer::{RenderContext, RenderResourceContext},
|
renderer::{RenderContext, RenderResourceContext},
|
||||||
Camera,
|
ActiveCameras, Camera,
|
||||||
};
|
};
|
||||||
use bevy_core::bytes::AsBytes;
|
use bevy_core::bytes::AsBytes;
|
||||||
|
|
||||||
@ -12,17 +12,17 @@ use std::borrow::Cow;
|
|||||||
|
|
||||||
pub struct CameraNode {
|
pub struct CameraNode {
|
||||||
command_queue: CommandQueue,
|
command_queue: CommandQueue,
|
||||||
uniform_name: Cow<'static, str>,
|
camera_name: Cow<'static, str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CameraNode {
|
impl CameraNode {
|
||||||
pub fn new<T>(uniform_name: T) -> Self
|
pub fn new<T>(camera_name: T) -> Self
|
||||||
where
|
where
|
||||||
T: Into<Cow<'static, str>>,
|
T: Into<Cow<'static, str>>,
|
||||||
{
|
{
|
||||||
CameraNode {
|
CameraNode {
|
||||||
command_queue: Default::default(),
|
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<dyn Schedulable> {
|
fn get_system(&self) -> Box<dyn Schedulable> {
|
||||||
let mut camera_buffer = None;
|
let mut camera_buffer = None;
|
||||||
let mut command_queue = self.command_queue.clone();
|
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,
|
(move |world: &mut SubWorld,
|
||||||
|
active_cameras: Res<ActiveCameras>,
|
||||||
render_resource_context: Res<Box<dyn RenderResourceContext>>,
|
render_resource_context: Res<Box<dyn RenderResourceContext>>,
|
||||||
// PERF: this write on RenderResourceAssignments will prevent this system from running in parallel
|
// PERF: this write on RenderResourceAssignments will prevent this system from running in parallel
|
||||||
// with other systems that do the same
|
// with other systems that do the same
|
||||||
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
mut render_resource_bindings: ResMut<RenderResourceBindings>,
|
||||||
query: &mut Query<(Read<Camera>, Read<Transform>)>| {
|
_query: &mut Query<(Read<Camera>, Read<Transform>)>| {
|
||||||
let render_resource_context = &**render_resource_context;
|
let render_resource_context = &**render_resource_context;
|
||||||
if camera_buffer.is_none() {
|
if camera_buffer.is_none() {
|
||||||
let size = std::mem::size_of::<[[f32; 4]; 4]>();
|
let size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||||
@ -60,7 +61,7 @@ impl SystemNode for CameraNode {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
render_resource_bindings.set(
|
render_resource_bindings.set(
|
||||||
&uniform_name,
|
&camera_name,
|
||||||
RenderResourceBinding::Buffer {
|
RenderResourceBinding::Buffer {
|
||||||
buffer,
|
buffer,
|
||||||
range: 0..size as u64,
|
range: 0..size as u64,
|
||||||
@ -69,34 +70,38 @@ impl SystemNode for CameraNode {
|
|||||||
);
|
);
|
||||||
camera_buffer = Some(buffer);
|
camera_buffer = Some(buffer);
|
||||||
}
|
}
|
||||||
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
|
let (camera, transform) = if let Some(camera_entity) = active_cameras.get(&camera_name)
|
||||||
if let Some((camera, transform)) = query
|
|
||||||
.iter(world)
|
|
||||||
.find(|(camera, _)| camera.name.as_ref().map(|n| n.as_str()) == Some(&uniform_name))
|
|
||||||
{
|
{
|
||||||
let camera_matrix: [f32; 16] =
|
(
|
||||||
(camera.view_matrix * transform.value).to_cols_array();
|
world.get_component::<Camera>(camera_entity).unwrap(),
|
||||||
|
world.get_component::<Transform>(camera_entity).unwrap(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
let tmp_buffer = render_resource_context.create_buffer_mapped(
|
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
|
||||||
BufferInfo {
|
let camera_matrix: [f32; 16] = (camera.view_matrix * transform.value).to_cols_array();
|
||||||
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(
|
let tmp_buffer = render_resource_context.create_buffer_mapped(
|
||||||
tmp_buffer,
|
BufferInfo {
|
||||||
0,
|
size: matrix_size,
|
||||||
camera_buffer.unwrap(),
|
buffer_usage: BufferUsage::COPY_SRC,
|
||||||
0,
|
..Default::default()
|
||||||
matrix_size as u64,
|
},
|
||||||
);
|
&mut |data, _renderer| {
|
||||||
command_queue.free_buffer(tmp_buffer);
|
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()
|
.system()
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use bevy_render::{
|
|||||||
pipeline::{state_descriptors::*, PipelineDescriptor},
|
pipeline::{state_descriptors::*, PipelineDescriptor},
|
||||||
render_graph::{nodes::CameraNode, RenderGraph},
|
render_graph::{nodes::CameraNode, RenderGraph},
|
||||||
shader::{Shader, ShaderStage, ShaderStages},
|
shader::{Shader, ShaderStage, ShaderStages},
|
||||||
texture::TextureFormat,
|
texture::TextureFormat, ActiveCameras,
|
||||||
};
|
};
|
||||||
use legion::prelude::Resources;
|
use legion::prelude::Resources;
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ pub mod node {
|
|||||||
pub const UI_CAMERA: &'static str = "ui_camera";
|
pub const UI_CAMERA: &'static str = "ui_camera";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod uniform {
|
pub mod camera {
|
||||||
pub const UI_CAMERA: &'static str = "UiCamera";
|
pub const UI_CAMERA: &'static str = "UiCamera";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,12 +70,14 @@ pub trait UiRenderGraphBuilder {
|
|||||||
|
|
||||||
impl UiRenderGraphBuilder for RenderGraph {
|
impl UiRenderGraphBuilder for RenderGraph {
|
||||||
fn add_ui_graph(&mut self, resources: &Resources) -> &mut Self {
|
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)
|
self.add_node_edge(node::UI_CAMERA, base_render_graph::node::MAIN_PASS)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
|
let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
|
||||||
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
||||||
pipelines.set(UI_PIPELINE_HANDLE, build_ui_pipeline(&mut shaders));
|
pipelines.set(UI_PIPELINE_HANDLE, build_ui_pipeline(&mut shaders));
|
||||||
|
let mut active_cameras = resources.get_mut::<ActiveCameras>().unwrap();
|
||||||
|
active_cameras.add(camera::UI_CAMERA);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user