camera: remove active camera components in favor of camera names

This commit is contained in:
Carter Anderson 2020-05-29 22:07:55 -07:00
parent fec9034644
commit 51d41b2302
20 changed files with 149 additions and 222 deletions

View File

@ -89,6 +89,7 @@ where
}
// impl_property!(SEQUENCE, VecDeque<T> where T: Clone + Send + Sync + Serialize + 'static);
impl_property!(Option<T> where T: Clone + Send + Sync + Serialize + for<'de> Deserialize<'de> + 'static);
impl_property!(HashSet<T> where T: Clone + Eq + Send + Sync + Hash + Serialize + for<'de> Deserialize<'de> + 'static);
impl_property!(HashMap<K, V> where
K: Clone + Eq + Send + Sync + Hash + Serialize + for<'de> Deserialize<'de> + 'static,

View File

@ -5,7 +5,7 @@ use crate::{
},
render_graph::{
nodes::{
Camera2dNode, CameraNode, PassNode, TextureCopyNode, WindowSwapChainNode,
CameraNode, PassNode, TextureCopyNode, WindowSwapChainNode,
WindowTextureNode,
},
RenderGraph,
@ -13,7 +13,7 @@ use crate::{
texture::{
Extent3d, Texture, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage,
},
Color,
Color, render_resource::resource_name,
};
use bevy_app::GetEventReader;
use bevy_asset::AssetEvent;
@ -72,11 +72,11 @@ impl BaseRenderGraphBuilder for RenderGraph {
TextureCopyNode::new(resources.get_event_reader::<AssetEvent<Texture>>()),
);
if config.add_3d_camera {
self.add_system_node(node::CAMERA, CameraNode::default());
self.add_system_node(node::CAMERA, CameraNode::new(resource_name::uniform::CAMERA));
}
if config.add_2d_camera {
self.add_system_node(node::CAMERA2D, Camera2dNode::default());
self.add_system_node(node::CAMERA2D, CameraNode::new(resource_name::uniform::CAMERA2D));
}
if config.add_main_depth_texture {

View File

@ -4,12 +4,6 @@ use bevy_window::WindowResized;
use glam::Mat4;
use legion::{prelude::*, storage::Component};
#[derive(Default, Properties)]
pub struct ActiveCamera;
#[derive(Default, Properties)]
pub struct ActiveCamera2d;
#[derive(Debug, Clone, Properties)]
pub struct OrthographicCamera {
pub left: f32,
@ -88,6 +82,7 @@ impl Default for PerspectiveCamera {
#[derive(Default, Debug, Properties)]
pub struct Camera {
pub view_matrix: Mat4,
pub name: Option<String>,
}
pub fn camera_system<T: CameraProjection + Component>(resources: &mut Resources) -> Box<dyn Schedulable> {

View File

@ -1,4 +1,4 @@
use crate::{mesh::Mesh, ActiveCamera, ActiveCamera2d, Camera, Renderable, OrthographicCamera, PerspectiveCamera};
use crate::{mesh::Mesh, Camera, Renderable, OrthographicCamera, PerspectiveCamera, render_resource::resource_name};
use bevy_asset::Handle;
use bevy_derive::EntityArchetype;
use bevy_transform::components::{LocalToWorld, Rotation, Scale, Translation};
@ -14,17 +14,58 @@ pub struct MeshMaterialEntity<T: Default + Send + Sync + 'static> {
pub scale: Scale,
}
#[derive(EntityArchetype, Default)]
pub struct CameraEntity {
#[derive(EntityArchetype)]
pub struct PerspectiveCameraEntity {
pub camera: Camera,
pub perspective_camera: PerspectiveCamera,
pub active_camera: ActiveCamera,
pub local_to_world: LocalToWorld,
}
#[derive(EntityArchetype, Default)]
impl Default for PerspectiveCameraEntity {
fn default() -> Self {
PerspectiveCameraEntity {
camera: Camera {
name: Some(resource_name::uniform::CAMERA.to_string()),
..Default::default()
},
perspective_camera: Default::default(),
local_to_world: Default::default(),
}
}
}
#[derive(EntityArchetype)]
pub struct OrthographicCameraEntity {
pub camera: Camera,
pub orthographic_camera: OrthographicCamera,
pub active_camera_2d: ActiveCamera2d,
pub local_to_world: LocalToWorld,
}
impl OrthographicCameraEntity {
pub fn ui() -> Self {
OrthographicCameraEntity {
camera: Camera {
// TODO: ui should have its own uniform
name: Some(resource_name::uniform::CAMERA2D.to_string()),
..Default::default()
},
orthographic_camera: Default::default(),
local_to_world: Default::default(),
}
}
}
impl Default for OrthographicCameraEntity {
fn default() -> Self {
OrthographicCameraEntity {
camera: Camera {
name: Some(resource_name::uniform::CAMERA2D.to_string()),
..Default::default()
},
orthographic_camera: Default::default(),
local_to_world: Default::default(),
}
}
}

View File

@ -79,8 +79,6 @@ impl AppPlugin for RenderPlugin {
.register_component::<OrthographicCamera>()
.register_component::<PerspectiveCamera>()
.register_component::<Renderable>()
.register_component::<ActiveCamera>()
.register_component::<ActiveCamera2d>()
.register_property_type::<Color>()
.register_property_type::<Range<f32>>()
.init_resource::<RenderGraph>()

View File

@ -1,4 +1,3 @@
mod camera2d_node;
mod camera_node;
mod pass_node;
mod uniform_node;
@ -6,7 +5,6 @@ mod window_swapchain_node;
mod window_texture_node;
mod texture_copy_node;
pub use camera2d_node::*;
pub use camera_node::*;
pub use pass_node::*;
pub use uniform_node::*;

View File

@ -1,111 +0,0 @@
use bevy_app::Events;
use bevy_window::WindowResized;
use crate::{
camera::{ActiveCamera2d, Camera},
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
render_resource::{
resource_name, BufferInfo, BufferUsage, RenderResourceAssignment, RenderResourceAssignments,
},
renderer::{RenderContext, RenderResources},
};
use legion::prelude::*;
use zerocopy::AsBytes;
#[derive(Default)]
pub struct Camera2dNode {
command_queue: CommandQueue,
}
impl Node for Camera2dNode {
fn update(
&mut self,
_world: &World,
_resources: &Resources,
render_context: &mut dyn RenderContext,
_input: &ResourceSlots,
_output: &mut ResourceSlots,
) {
self.command_queue.execute(render_context);
}
}
impl SystemNode for Camera2dNode {
fn get_system(&self) -> Box<dyn Schedulable> {
let mut camera_buffer = None;
let mut window_resized_event_reader = None;
let mut command_queue = self.command_queue.clone();
SystemBuilder::new("camera_2d_resource_provider")
.read_resource::<RenderResources>()
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
.write_resource::<RenderResourceAssignments>()
.read_resource::<Events<WindowResized>>()
.with_query(<(Read<Camera>, Read<ActiveCamera2d>)>::query())
.build(
move |_,
world,
(
render_resource_context,
ref mut render_resource_assignments,
window_resized_events,
),
query| {
let render_resources = &render_resource_context.context;
if camera_buffer.is_none() {
let size = std::mem::size_of::<[[f32; 4]; 4]>();
let buffer = render_resources.create_buffer(BufferInfo {
size,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
render_resource_assignments.set(
resource_name::uniform::CAMERA2D,
RenderResourceAssignment::Buffer {
resource: buffer,
range: 0..size as u64,
dynamic_index: None,
},
);
camera_buffer = Some(buffer);
}
if window_resized_event_reader.is_none() {
window_resized_event_reader = Some(window_resized_events.get_reader());
}
let primary_window_resized_event = window_resized_event_reader
.as_mut()
.unwrap()
.find_latest(&window_resized_events, |event| event.is_primary);
if let Some(_) = primary_window_resized_event {
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
for (camera, _) in query.iter(world) {
let camera_matrix: [[f32; 4]; 4] =
camera.view_matrix.to_cols_array_2d();
let tmp_buffer = render_resources.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);
}
}
},
)
}
}

View File

@ -1,21 +1,34 @@
use crate::{
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
render_resource::{
resource_name, BufferInfo, BufferUsage, RenderResourceAssignment, RenderResourceAssignments,
BufferInfo, BufferUsage, RenderResourceAssignment, RenderResourceAssignments,
},
renderer::{RenderContext, RenderResources},
ActiveCamera, Camera,
Camera,
};
use bevy_app::Events;
use bevy_transform::prelude::*;
use bevy_window::WindowResized;
use legion::prelude::*;
use std::borrow::Cow;
use zerocopy::AsBytes;
#[derive(Default)]
pub struct CameraNode {
command_queue: CommandQueue,
uniform_name: Cow<'static, str>,
}
impl CameraNode {
pub fn new<T>(uniform_name: T) -> Self
where
T: Into<Cow<'static, str>>,
{
CameraNode {
command_queue: Default::default(),
uniform_name: uniform_name.into(),
}
}
}
impl Node for CameraNode {
@ -36,75 +49,70 @@ impl SystemNode for CameraNode {
let mut camera_buffer = None;
let mut window_resized_event_reader = None;
let mut command_queue = self.command_queue.clone();
let uniform_name = self.uniform_name.clone();
(move |world: &mut SubWorld,
render_resources: Res<RenderResources>,
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel
// with other systems that do the same
mut render_resource_assignments: ResMut<RenderResourceAssignments>,
window_resized_events: Res<Events<WindowResized>>,
query: &mut Query<(Read<Camera>, Read<LocalToWorld>)>| {
let render_resources = &render_resources.context;
if camera_buffer.is_none() {
let size = std::mem::size_of::<[[f32; 4]; 4]>();
let buffer = render_resources.create_buffer(BufferInfo {
size,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
render_resource_assignments.set(
&uniform_name,
RenderResourceAssignment::Buffer {
resource: buffer,
range: 0..size as u64,
dynamic_index: None,
},
);
camera_buffer = Some(buffer);
}
if window_resized_event_reader.is_none() {
window_resized_event_reader = Some(window_resized_events.get_reader());
}
let primary_window_resized_event = window_resized_event_reader
.as_mut()
.unwrap()
.find_latest(&window_resized_events, |event| event.is_primary);
if let Some(_) = primary_window_resized_event {
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
if let Some((camera, local_to_world)) = query
.iter(world)
.find(|(camera, _)| camera.name.as_ref().map(|n| n.as_str()) == Some(&uniform_name))
{
let camera_matrix: [[f32; 4]; 4] =
(camera.view_matrix * local_to_world.0).to_cols_array_2d();
SystemBuilder::new("camera_resource_provider")
.read_resource::<RenderResources>()
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
.write_resource::<RenderResourceAssignments>()
.read_resource::<Events<WindowResized>>()
.with_query(<(Read<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query())
.build(
move |_,
world,
(
render_resource_context,
ref mut render_resource_assignments,
window_resized_events,
),
query| {
let render_resources = &render_resource_context.context;
if camera_buffer.is_none() {
let size = std::mem::size_of::<[[f32; 4]; 4]>();
let buffer = render_resources.create_buffer(BufferInfo {
size,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
let tmp_buffer = render_resources.create_buffer_mapped(
BufferInfo {
size: matrix_size,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
});
render_resource_assignments.set(
resource_name::uniform::CAMERA,
RenderResourceAssignment::Buffer {
resource: buffer,
range: 0..size as u64,
dynamic_index: None,
},
);
camera_buffer = Some(buffer);
}
if window_resized_event_reader.is_none() {
window_resized_event_reader = Some(window_resized_events.get_reader());
}
let primary_window_resized_event = window_resized_event_reader
.as_mut()
.unwrap()
.find_latest(&window_resized_events, |event| event.is_primary);
if let Some(_) = primary_window_resized_event {
let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>();
for (camera, local_to_world, _) in query.iter(world) {
let camera_matrix: [[f32; 4]; 4] =
(camera.view_matrix * local_to_world.0).to_cols_array_2d();
},
&mut |data, _renderer| {
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
},
);
let tmp_buffer = render_resources.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);
}
}
},
)
command_queue.copy_buffer_to_buffer(
tmp_buffer,
0,
camera_buffer.unwrap(),
0,
matrix_size as u64,
);
command_queue.free_buffer(tmp_buffer);
}
}
})
.system()
}
}

View File

@ -49,7 +49,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -38,7 +38,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(2.0, -6.0, 2.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -52,7 +52,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(5.0, 10.0, 10.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -62,7 +62,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -66,7 +66,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, -8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -34,7 +34,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -69,7 +69,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(0.0, -10.0, 3.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -11,20 +11,17 @@ fn main() {
fn setup(
command_buffer: &mut CommandBuffer,
mut asset_server: ResMut<AssetServer>,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Load an asset folder:
asset_server.load_asset_folder("assets").unwrap();
// Load our mesh:
let mesh_handle = asset_server
.load("assets/models/monkey/Monkey.gltf")
.unwrap();
// Tell the asset server to watch for asset changes on disk:
asset_server.watch_for_changes().unwrap();
// Get a handle for our mesh:
let mesh_handle = asset_server
.get_handle("assets/models/monkey/Monkey.gltf")
.unwrap();
// Any changes to the mesh will be reloaded automatically! Try making a change to Monkey.gltf.
// You should see the changes immediately show up in your app.
@ -49,7 +46,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(2.0, -6.0, 2.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -86,7 +86,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -84,7 +84,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -111,7 +111,7 @@ fn setup(
..Default::default()
})
// camera
.add_entity(CameraEntity {
.add_entity(PerspectiveCameraEntity {
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),

View File

@ -22,7 +22,7 @@ pub use crate::render::{
pipeline::PipelineDescriptor,
render_graph::{
nodes::{
AssetUniformNode, Camera2dNode, CameraNode, PassNode, UniformNode, WindowSwapChainNode,
AssetUniformNode, CameraNode, PassNode, UniformNode, WindowSwapChainNode,
WindowTextureNode,
},
RenderGraph,
@ -30,7 +30,7 @@ pub use crate::render::{
render_resource::resource_name,
shader::{Shader, ShaderDefSuffixProvider, ShaderStage, ShaderStages},
texture::{Texture, TextureType},
ActiveCamera, ActiveCamera2d, Camera, OrthographicCamera, PerspectiveCamera, Color, ColorSource, Renderable,
Camera, OrthographicCamera, PerspectiveCamera, Color, ColorSource, Renderable,
};
#[cfg(feature = "scene")]
pub use crate::scene::{Scene, SceneSpawner};