mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
render: ActiveCameras resource and system
This commit is contained in:
parent
b6dbbf04db
commit
ca8625c407
7 changed files with 106 additions and 40 deletions
|
@ -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());
|
||||
|
|
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 projection;
|
||||
mod visible_entities;
|
||||
|
||||
pub use active_cameras::*;
|
||||
pub use camera::*;
|
||||
pub use projection::*;
|
||||
pub use visible_entities::*;
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -94,7 +94,12 @@ impl AppPlugin for RenderPlugin {
|
|||
.init_resource::<VertexBufferDescriptors>()
|
||||
.init_resource::<TextureResourceSystemState>()
|
||||
.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::POST_UPDATE,
|
||||
camera::active_cameras_system.system(),
|
||||
)
|
||||
.add_system_to_stage(
|
||||
bevy_app::stage::POST_UPDATE,
|
||||
camera::camera_system::<OrthographicProjection>(),
|
||||
|
@ -125,6 +130,14 @@ impl AppPlugin for RenderPlugin {
|
|||
let resources = app.resources();
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
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_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<T>(uniform_name: T) -> Self
|
||||
pub fn new<T>(camera_name: T) -> Self
|
||||
where
|
||||
T: Into<Cow<'static, str>>,
|
||||
{
|
||||
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<dyn Schedulable> {
|
||||
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<ActiveCameras>,
|
||||
render_resource_context: Res<Box<dyn RenderResourceContext>>,
|
||||
// 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<RenderResourceBindings>,
|
||||
query: &mut Query<(Read<Camera>, Read<Transform>)>| {
|
||||
_query: &mut Query<(Read<Camera>, Read<Transform>)>| {
|
||||
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>(camera_entity).unwrap(),
|
||||
world.get_component::<Transform>(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()
|
||||
}
|
||||
|
|
|
@ -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::<Assets<PipelineDescriptor>>().unwrap();
|
||||
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue