From 69925f081716728dddee90d3f01735b91a6abf5e Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Thu, 25 Jun 2020 23:04:08 -0700 Subject: [PATCH] render: multi-window cameras ready to go! passes now bind camera buffers and cameras can now be assigned non-primary windows --- crates/bevy_pbr/src/entity.rs | 4 +- .../src/pipelines/forward/forward.frag | 8 +- .../src/pipelines/forward/forward.vert | 2 +- .../bevy_render/src/base_render_graph/mod.rs | 10 +-- crates/bevy_render/src/camera/camera.rs | 67 +++++++++++---- crates/bevy_render/src/entity.rs | 2 +- crates/bevy_render/src/lib.rs | 2 +- crates/bevy_render/src/pipeline/binding.rs | 2 +- .../src/pipeline/pipeline_layout.rs | 39 ++++----- .../src/render_graph/nodes/pass_node.rs | 86 ++++++++++++++++--- .../render_resource_bindings.rs | 15 +--- .../bevy_render/src/shader/shader_reflect.rs | 47 ++++------ crates/bevy_sprite/src/render/sprite.vert | 2 +- .../bevy_sprite/src/render/sprite_sheet.vert | 9 +- crates/bevy_text/src/draw.rs | 18 ++-- crates/bevy_ui/src/render/ui.vert | 2 +- crates/bevy_window/src/window.rs | 8 ++ examples/window/multiple_windows.rs | 76 +++++++++------- 18 files changed, 239 insertions(+), 160 deletions(-) diff --git a/crates/bevy_pbr/src/entity.rs b/crates/bevy_pbr/src/entity.rs index dc0d70f677..01609a5813 100644 --- a/crates/bevy_pbr/src/entity.rs +++ b/crates/bevy_pbr/src/entity.rs @@ -29,12 +29,12 @@ impl Default for MeshComponents { dynamic_bindings: vec![ // Transform DynamicBinding { - bind_group: 1, + bind_group: 2, binding: 0, }, // StandardMaterial_albedo DynamicBinding { - bind_group: 2, + bind_group: 3, binding: 0, }, ], diff --git a/crates/bevy_pbr/src/pipelines/forward/forward.frag b/crates/bevy_pbr/src/pipelines/forward/forward.frag index b1e948145c..9c869f29e7 100644 --- a/crates/bevy_pbr/src/pipelines/forward/forward.frag +++ b/crates/bevy_pbr/src/pipelines/forward/forward.frag @@ -18,18 +18,18 @@ layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; }; -layout(set = 0, binding = 1) uniform Lights { +layout(set = 1, binding = 0) uniform Lights { uvec4 NumLights; Light SceneLights[MAX_LIGHTS]; }; -layout(set = 2, binding = 0) uniform StandardMaterial_albedo { +layout(set = 3, binding = 0) uniform StandardMaterial_albedo { vec4 Albedo; }; # ifdef STANDARDMATERIAL_ALBEDO_TEXTURE -layout(set = 3, binding = 0) uniform texture2D StandardMaterial_albedo_texture; -layout(set = 3, binding = 1) uniform sampler StandardMaterial_albedo_texture_sampler; +layout(set = 3, binding = 1) uniform texture2D StandardMaterial_albedo_texture; +layout(set = 3, binding = 2) uniform sampler StandardMaterial_albedo_texture_sampler; # endif void main() { diff --git a/crates/bevy_pbr/src/pipelines/forward/forward.vert b/crates/bevy_pbr/src/pipelines/forward/forward.vert index bb109832df..00cd153602 100644 --- a/crates/bevy_pbr/src/pipelines/forward/forward.vert +++ b/crates/bevy_pbr/src/pipelines/forward/forward.vert @@ -12,7 +12,7 @@ layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; }; -layout(set = 1, binding = 0) uniform Transform { +layout(set = 2, binding = 0) uniform Transform { mat4 Model; }; diff --git a/crates/bevy_render/src/base_render_graph/mod.rs b/crates/bevy_render/src/base_render_graph/mod.rs index 3a0d0a6f7f..cb98ac1f07 100644 --- a/crates/bevy_render/src/base_render_graph/mod.rs +++ b/crates/bevy_render/src/base_render_graph/mod.rs @@ -26,7 +26,7 @@ pub struct BaseRenderGraphConfig { pub mod node { pub const PRIMARY_SWAP_CHAIN: &str = "swapchain"; - pub const CAMERA: &str = "camera"; + pub const CAMERA3D: &str = "camera3d"; pub const CAMERA2D: &str = "camera2d"; pub const TEXTURE_COPY: &str = "texture_copy"; pub const MAIN_DEPTH_TEXTURE: &str = "main_pass_depth_texture"; @@ -35,7 +35,7 @@ pub mod node { } pub mod camera { - pub const CAMERA: &str = "Camera"; + pub const CAMERA3D: &str = "Camera3d"; pub const CAMERA2D: &str = "Camera2d"; } @@ -62,7 +62,7 @@ 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(camera::CAMERA)); + self.add_system_node(node::CAMERA3D, CameraNode::new(camera::CAMERA3D)); } if config.add_2d_camera { @@ -117,7 +117,7 @@ impl BaseRenderGraphBuilder for RenderGraph { main_pass_node.use_default_clear_color(0); if config.add_3d_camera { - main_pass_node.add_camera(camera::CAMERA); + main_pass_node.add_camera(camera::CAMERA3D); } if config.add_2d_camera { @@ -135,7 +135,7 @@ impl BaseRenderGraphBuilder for RenderGraph { .unwrap(); if config.add_3d_camera { - self.add_node_edge(node::CAMERA, node::MAIN_PASS).unwrap(); + self.add_node_edge(node::CAMERA3D, node::MAIN_PASS).unwrap(); } if config.add_2d_camera { diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index a6ee21c565..7fdc1cc9f3 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -1,7 +1,7 @@ use crate::CameraProjection; use bevy_app::{EventReader, Events}; use bevy_property::Properties; -use bevy_window::{WindowCreated, WindowResized, Windows}; +use bevy_window::{WindowCreated, WindowReference, WindowResized, Windows}; use glam::Mat4; use legion::{prelude::*, storage::Component}; @@ -9,6 +9,8 @@ use legion::{prelude::*, storage::Component}; pub struct Camera { pub projection_matrix: Mat4, pub name: Option, + #[property(ignore)] + pub window: WindowReference, } pub fn camera_system() -> Box { @@ -19,27 +21,58 @@ pub fn camera_system() -> Box window_created_events: Res>, windows: Res, query: &mut Query<(Write, Write)>| { - let primary_window_resized_event = window_resized_event_reader - .find_latest(&window_resized_events, |event| event.is_primary); - - for event in window_created_event_reader.iter(&window_created_events) { - if !event.is_primary { + let mut changed_window_ids = Vec::new(); + let mut changed_primary_window_id = None; + // handle resize events. latest events are handled first because we only want to resize each window once + for event in window_resized_event_reader + .iter(&window_resized_events) + .rev() + { + if changed_window_ids.contains(&event.id) { continue; } - if let Some(window) = windows.get(event.id) { - for (mut camera, mut camera_projection) in query.iter_mut(world) { - camera_projection.update(window.width as usize, window.height as usize); - camera.projection_matrix = camera_projection.get_projection_matrix(); - } + + if event.is_primary { + changed_primary_window_id = Some(event.id); + } else { + changed_window_ids.push(event.id); } } - if let Some(primary_window_resized_event) = primary_window_resized_event { - for (mut camera, mut camera_projection) in query.iter_mut(world) { - camera_projection.update( - primary_window_resized_event.width, - primary_window_resized_event.height, - ); + // handle resize events. latest events are handled first because we only want to resize each window once + for event in window_created_event_reader + .iter(&window_created_events) + .rev() + { + if changed_window_ids.contains(&event.id) { + continue; + } + + if event.is_primary { + changed_primary_window_id = Some(event.id); + } else { + changed_window_ids.push(event.id); + } + } + + for (mut camera, mut camera_projection) in query.iter_mut(world) { + if let Some(window) = match camera.window { + WindowReference::Id(id) => { + if changed_window_ids.contains(&id) { + windows.get(id) + } else { + None + } + } + WindowReference::Primary => { + if let Some(id) = changed_primary_window_id { + windows.get(id) + } else { + None + } + } + } { + camera_projection.update(window.width as usize, window.height as usize); camera.projection_matrix = camera_projection.get_projection_matrix(); } } diff --git a/crates/bevy_render/src/entity.rs b/crates/bevy_render/src/entity.rs index 59de3ce8b7..0bbebaa9ed 100644 --- a/crates/bevy_render/src/entity.rs +++ b/crates/bevy_render/src/entity.rs @@ -33,7 +33,7 @@ impl Default for PerspectiveCameraComponents { fn default() -> Self { PerspectiveCameraComponents { camera: Camera { - name: Some(base_render_graph::camera::CAMERA.to_string()), + name: Some(base_render_graph::camera::CAMERA3D.to_string()), ..Default::default() }, perspective_projection: Default::default(), diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index e8b687b94a..1896ead14a 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -132,7 +132,7 @@ impl AppPlugin for RenderPlugin { 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); + active_cameras.add(base_render_graph::camera::CAMERA3D); } if config.add_2d_camera { diff --git a/crates/bevy_render/src/pipeline/binding.rs b/crates/bevy_render/src/pipeline/binding.rs index 8318bd8008..05a69053ca 100644 --- a/crates/bevy_render/src/pipeline/binding.rs +++ b/crates/bevy_render/src/pipeline/binding.rs @@ -40,7 +40,7 @@ impl BindType { match self { BindType::Uniform { properties, .. } => { Some(properties.iter().fold(0, |total, property| { - total + property.property_type.get_size() + total + property.get_size() })) } _ => None, diff --git a/crates/bevy_render/src/pipeline/pipeline_layout.rs b/crates/bevy_render/src/pipeline/pipeline_layout.rs index a80b2f8983..d372787fe9 100644 --- a/crates/bevy_render/src/pipeline/pipeline_layout.rs +++ b/crates/bevy_render/src/pipeline/pipeline_layout.rs @@ -85,14 +85,7 @@ impl PipelineLayout { } #[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -pub struct UniformProperty { - pub name: String, - pub property_type: UniformPropertyType, -} - -#[derive(Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] -pub enum UniformPropertyType { - // TODO: Use VertexFormat here +pub enum UniformProperty { UInt, Int, IVec2, @@ -104,27 +97,27 @@ pub enum UniformPropertyType { Mat3, Mat4, Struct(Vec), - Array(Box, usize), + Array(Box, usize), } -impl UniformPropertyType { +impl UniformProperty { pub fn get_size(&self) -> u64 { match self { - UniformPropertyType::UInt => 4, - UniformPropertyType::Int => 4, - UniformPropertyType::IVec2 => 4 * 2, - UniformPropertyType::Float => 4, - UniformPropertyType::UVec4 => 4 * 4, - UniformPropertyType::Vec2 => 4 * 2, - UniformPropertyType::Vec3 => 4 * 3, - UniformPropertyType::Vec4 => 4 * 4, - UniformPropertyType::Mat3 => 4 * 4 * 3, - UniformPropertyType::Mat4 => 4 * 4 * 4, - UniformPropertyType::Struct(properties) => properties + UniformProperty::UInt => 4, + UniformProperty::Int => 4, + UniformProperty::IVec2 => 4 * 2, + UniformProperty::Float => 4, + UniformProperty::UVec4 => 4 * 4, + UniformProperty::Vec2 => 4 * 2, + UniformProperty::Vec3 => 4 * 3, + UniformProperty::Vec4 => 4 * 4, + UniformProperty::Mat3 => 4 * 4 * 3, + UniformProperty::Mat4 => 4 * 4 * 4, + UniformProperty::Struct(properties) => properties .iter() - .map(|p| p.property_type.get_size()) + .map(|p| p.get_size()) .fold(0, |total, size| total + size), - UniformPropertyType::Array(property, length) => property.get_size() * *length as u64, + UniformProperty::Array(property, length) => property.get_size() * *length as u64, } } } diff --git a/crates/bevy_render/src/render_graph/nodes/pass_node.rs b/crates/bevy_render/src/render_graph/nodes/pass_node.rs index 5cd7b3e2d8..763a38249a 100644 --- a/crates/bevy_render/src/render_graph/nodes/pass_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/pass_node.rs @@ -1,21 +1,32 @@ use crate::{ draw::{Draw, RenderCommand}, - pass::{PassDescriptor, TextureAttachment, ClearColor}, - pipeline::PipelineDescriptor, + pass::{ClearColor, PassDescriptor, TextureAttachment}, + pipeline::{ + BindGroupDescriptor, BindType, BindingDescriptor, PipelineDescriptor, UniformProperty, + }, render_graph::{Node, ResourceSlotInfo, ResourceSlots}, - render_resource::{BindGroupId, BufferId, RenderResourceBindings, RenderResourceType}, - renderer::RenderContext, ActiveCameras, VisibleEntities, + render_resource::{ + BindGroup, BindGroupId, BufferId, RenderResourceBindings, RenderResourceType, + }, + renderer::RenderContext, + ActiveCameras, VisibleEntities, }; use bevy_asset::{Assets, Handle}; use legion::prelude::*; +struct CameraInfo { + name: String, + bind_group_id: Option, +} + pub struct PassNode { descriptor: PassDescriptor, inputs: Vec, - cameras: Vec, + cameras: Vec, color_attachment_input_indices: Vec>, depth_stencil_attachment_input_index: Option, default_clear_color_inputs: Vec, + camera_bind_group_descriptor: BindGroupDescriptor, } impl PassNode { @@ -45,6 +56,18 @@ impl PassNode { } } + let camera_bind_group_descriptor = BindGroupDescriptor::new( + 0, + vec![BindingDescriptor { + name: "Camera".to_string(), + index: 0, + bind_type: BindType::Uniform { + dynamic: false, + properties: vec![UniformProperty::Struct(vec![UniformProperty::Mat4])], + }, + }], + ); + PassNode { descriptor, inputs, @@ -52,11 +75,15 @@ impl PassNode { color_attachment_input_indices, depth_stencil_attachment_input_index, default_clear_color_inputs: Vec::new(), + camera_bind_group_descriptor, } } pub fn add_camera(&mut self, camera_name: &str) { - self.cameras.push(camera_name.to_string()); + self.cameras.push(CameraInfo { + name: camera_name.to_string(), + bind_group_id: None, + }); } pub fn use_default_clear_color(&mut self, color_attachment_index: usize) { @@ -79,12 +106,12 @@ impl Node for PassNode { ) { let render_resource_bindings = resources.get::().unwrap(); let pipelines = resources.get::>().unwrap(); - let active_cameras= resources.get::().unwrap(); + let active_cameras = resources.get::().unwrap(); for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() { if self.default_clear_color_inputs.contains(&i) { if let Some(default_clear_color) = resources.get::() { - color_attachment.clear_color = default_clear_color.color; + color_attachment.clear_color = default_clear_color.color; } } if let Some(input_index) = self.color_attachment_input_indices[i] { @@ -101,18 +128,40 @@ impl Node for PassNode { .attachment = TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap()); } + for camera_info in self.cameras.iter_mut() { + let camera_binding = + if let Some(camera_binding) = render_resource_bindings.get(&camera_info.name) { + camera_binding.clone() + } else { + continue; + }; + + let camera_bind_group = BindGroup::build().add_binding(0, camera_binding).finish(); + render_context + .resources() + .create_bind_group(self.camera_bind_group_descriptor.id, &camera_bind_group); + camera_info.bind_group_id = Some(camera_bind_group.id); + } render_context.begin_pass( &self.descriptor, &render_resource_bindings, &mut |render_pass| { - for camera_name in self.cameras.iter() { - let visible_entities = if let Some(camera_entity) = active_cameras.get(camera_name) { + for camera_info in self.cameras.iter() { + let camera_bind_group_id= if let Some(bind_group_id) = camera_info.bind_group_id { + bind_group_id + } else { + continue; + }; + + // get an ordered list of entities visible to the camera + let visible_entities = if let Some(camera_entity) = active_cameras.get(&camera_info.name) { world.get_component::(camera_entity).unwrap() } else { continue; }; + // attempt to draw each visible entity let mut draw_state = DrawState::default(); for visible_entity in visible_entities.iter() { let draw = if let Some(draw) = world.get_component::(visible_entity.entity) { @@ -124,7 +173,8 @@ impl Node for PassNode { if !draw.is_visible { continue; } - + + // each Draw component contains an ordered list of render commands. we turn those into actual render commands here for render_command in draw.render_commands.iter() { match render_command { RenderCommand::SetPipeline { pipeline } => { @@ -132,6 +182,20 @@ impl Node for PassNode { render_pass.set_pipeline(*pipeline); let descriptor = pipelines.get(pipeline).unwrap(); draw_state.set_pipeline(*pipeline, descriptor); + + // try to set current camera bind group + let layout = descriptor.get_layout().unwrap(); + if let Some(descriptor) = layout.get_bind_group(0) { + if *descriptor == self.camera_bind_group_descriptor { + draw_state.set_bind_group(0, camera_bind_group_id); + render_pass.set_bind_group( + 0, + descriptor.id, + camera_bind_group_id, + None + ); + } + } } RenderCommand::DrawIndexed { base_vertex, diff --git a/crates/bevy_render/src/render_resource/render_resource_bindings.rs b/crates/bevy_render/src/render_resource/render_resource_bindings.rs index 9104c9c7f3..a910c797f4 100644 --- a/crates/bevy_render/src/render_resource/render_resource_bindings.rs +++ b/crates/bevy_render/src/render_resource/render_resource_bindings.rs @@ -261,7 +261,7 @@ impl Default for RenderResourceBindingsId { #[cfg(test)] mod tests { use super::*; - use crate::pipeline::{BindType, BindingDescriptor, UniformProperty, UniformPropertyType}; + use crate::pipeline::{BindType, BindingDescriptor, UniformProperty}; #[test] fn test_bind_groups() { @@ -273,13 +273,7 @@ mod tests { name: "a".to_string(), bind_type: BindType::Uniform { dynamic: false, - properties: vec![UniformProperty { - name: "A".to_string(), - property_type: UniformPropertyType::Struct(vec![UniformProperty { - name: "".to_string(), - property_type: UniformPropertyType::Mat4, - }]), - }], + properties: vec![UniformProperty::Struct(vec![UniformProperty::Mat4])], }, }, BindingDescriptor { @@ -287,10 +281,7 @@ mod tests { name: "b".to_string(), bind_type: BindType::Uniform { dynamic: false, - properties: vec![UniformProperty { - name: "B".to_string(), - property_type: UniformPropertyType::Float, - }], + properties: vec![UniformProperty::Float], }, }, ], diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index 1834c61dc7..1e415174c9 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -1,7 +1,7 @@ use crate::{ pipeline::{ BindGroupDescriptor, BindType, BindingDescriptor, InputStepMode, UniformProperty, - UniformPropertyType, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, + VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, }, texture::{TextureComponentType, TextureViewDimension}, }; @@ -214,31 +214,26 @@ enum NumberType { } fn reflect_uniform(type_description: &ReflectTypeDescription) -> UniformProperty { - let uniform_property_type = if type_description + if type_description .type_flags .contains(ReflectTypeFlags::STRUCT) { reflect_uniform_struct(type_description) } else { reflect_uniform_numeric(type_description) - }; - - UniformProperty { - name: type_description.type_name.to_string(), - property_type: uniform_property_type, } } -fn reflect_uniform_struct(type_description: &ReflectTypeDescription) -> UniformPropertyType { +fn reflect_uniform_struct(type_description: &ReflectTypeDescription) -> UniformProperty { let mut properties = Vec::new(); for member in type_description.members.iter() { properties.push(reflect_uniform(member)); } - UniformPropertyType::Struct(properties) + UniformProperty::Struct(properties) } -fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> UniformPropertyType { +fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> UniformProperty { let traits = &type_description.traits; let number_type = if type_description.type_flags.contains(ReflectTypeFlags::INT) { match traits.numeric.scalar.signedness { @@ -266,8 +261,8 @@ fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> Uniform traits.numeric.matrix.column_count, traits.numeric.matrix.row_count, ) { - (NumberType::Float, 3, 3) => UniformPropertyType::Mat3, - (NumberType::Float, 4, 4) => UniformPropertyType::Mat4, + (NumberType::Float, 3, 3) => UniformProperty::Mat3, + (NumberType::Float, 4, 4) => UniformProperty::Mat4, (number_type, column_count, row_count) => panic!( "unexpected uniform property matrix format {:?} {}x{}", number_type, column_count, row_count @@ -275,14 +270,14 @@ fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> Uniform } } else { match (number_type, traits.numeric.vector.component_count) { - (NumberType::UInt, 0) => UniformPropertyType::UInt, - (NumberType::Int, 0) => UniformPropertyType::Int, - (NumberType::Int, 2) => UniformPropertyType::IVec2, - (NumberType::Float, 0) => UniformPropertyType::Float, - (NumberType::Float, 2) => UniformPropertyType::Vec2, - (NumberType::Float, 3) => UniformPropertyType::Vec3, - (NumberType::Float, 4) => UniformPropertyType::Vec4, - (NumberType::UInt, 4) => UniformPropertyType::UVec4, + (NumberType::UInt, 0) => UniformProperty::UInt, + (NumberType::Int, 0) => UniformProperty::Int, + (NumberType::Int, 2) => UniformProperty::IVec2, + (NumberType::Float, 0) => UniformProperty::Float, + (NumberType::Float, 2) => UniformProperty::Vec2, + (NumberType::Float, 3) => UniformProperty::Vec3, + (NumberType::Float, 4) => UniformProperty::Vec4, + (NumberType::UInt, 4) => UniformProperty::UVec4, (number_type, component_count) => panic!( "unexpected uniform property format {:?} {}", number_type, component_count @@ -414,15 +409,9 @@ mod tests { name: "Camera".into(), bind_type: BindType::Uniform { dynamic: false, - properties: vec![UniformProperty { - name: "Camera".into(), - property_type: UniformPropertyType::Struct(vec![ - UniformProperty { - name: "".into(), - property_type: UniformPropertyType::Mat4, - } - ]), - }], + properties: vec![UniformProperty::Struct(vec![ + UniformProperty::Mat4 + ])], }, }] ), diff --git a/crates/bevy_sprite/src/render/sprite.vert b/crates/bevy_sprite/src/render/sprite.vert index 3cab495b10..c4ecaed96e 100644 --- a/crates/bevy_sprite/src/render/sprite.vert +++ b/crates/bevy_sprite/src/render/sprite.vert @@ -6,7 +6,7 @@ layout(location = 2) in vec2 Vertex_Uv; layout(location = 0) out vec2 v_Uv; -layout(set = 0, binding = 0) uniform Camera2d { +layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; }; diff --git a/crates/bevy_sprite/src/render/sprite_sheet.vert b/crates/bevy_sprite/src/render/sprite_sheet.vert index 909367c433..3e3c21588f 100644 --- a/crates/bevy_sprite/src/render/sprite_sheet.vert +++ b/crates/bevy_sprite/src/render/sprite_sheet.vert @@ -7,16 +7,9 @@ layout(location = 2) in vec2 Vertex_Uv; layout(location = 0) out vec2 v_Uv; layout(location = 1) out vec4 v_Color; -// TODO: remove UI shader def and replace with generic "Camera" when its easier to manually bind global RenderResourceBindings -#ifdef UI_CAMERA -layout(set = 0, binding = 0) uniform UiCamera { +layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; }; -# else -layout(set = 0, binding = 0) uniform Camera2d { - mat4 ViewProj; -}; -#endif // TODO: merge dimensions into "sprites" buffer when that is supported in the Uniforms derive abstraction layout(set = 1, binding = 0) uniform TextureAtlas_size { diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 06015a816e..fc12d187eb 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -4,7 +4,7 @@ use bevy_asset::Assets; use bevy_render::{ draw::{Draw, DrawContext, DrawError, Drawable}, mesh, - pipeline::{PipelineSpecialization, ShaderSpecialization}, + pipeline::PipelineSpecialization, render_resource::{ AssetRenderResourceBindings, BindGroup, BufferUsage, RenderResourceBindings, RenderResourceId, @@ -13,7 +13,6 @@ use bevy_render::{ }; use bevy_sprite::{TextureAtlas, TextureAtlasSprite}; use glam::{Mat4, Vec3}; -use std::collections::HashSet; pub struct TextStyle { pub font_size: f32, @@ -57,16 +56,11 @@ impl<'a> DrawableText<'a> { impl<'a> Drawable for DrawableText<'a> { fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError> { - let mut shader_defs = HashSet::new(); - shader_defs.insert("UI_CAMERA".to_string()); context.set_pipeline( draw, bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE, // TODO: remove this shader def specialization when its easier to manually bind global render resources to specific bind groups - &PipelineSpecialization { - shader_specialization: ShaderSpecialization { shader_defs }, - ..Default::default() - }, + &PipelineSpecialization::default(), )?; let render_resource_context = &**context.render_resource_context; @@ -151,10 +145,10 @@ impl<'a> Drawable for DrawableText<'a> { .shared_buffers .get_buffer(&sprite, BufferUsage::UNIFORM) .unwrap(); - let sprite_bind_group = - BindGroup::build() - .add_binding(0, transform_buffer) - .add_binding(1, sprite_buffer).finish(); + let sprite_bind_group = BindGroup::build() + .add_binding(0, transform_buffer) + .add_binding(1, sprite_buffer) + .finish(); context.create_bind_group_resource(2, &sprite_bind_group)?; draw.set_bind_group(2, &sprite_bind_group); draw.draw_indexed(indices.clone(), 0, 0..1); diff --git a/crates/bevy_ui/src/render/ui.vert b/crates/bevy_ui/src/render/ui.vert index f719ca810d..2268af642b 100644 --- a/crates/bevy_ui/src/render/ui.vert +++ b/crates/bevy_ui/src/render/ui.vert @@ -6,7 +6,7 @@ layout(location = 2) in vec2 Vertex_Uv; layout(location = 0) out vec2 v_Uv; -layout(set = 0, binding = 0) uniform UiCamera { +layout(set = 0, binding = 0) uniform Camera { mat4 ViewProj; }; diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index 5ee1d624e2..8017284ff7 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -1,10 +1,18 @@ use uuid::Uuid; +#[derive(Debug)] pub enum WindowReference { Primary, Id(WindowId), } +impl Default for WindowReference { + fn default() -> Self { + WindowReference::Primary + } + +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct WindowId(Uuid); diff --git a/examples/window/multiple_windows.rs b/examples/window/multiple_windows.rs index 3ca25ba10c..ec98b9ec86 100644 --- a/examples/window/multiple_windows.rs +++ b/examples/window/multiple_windows.rs @@ -1,18 +1,30 @@ -use bevy::{prelude::*, window::CreateWindow}; -use bevy_render::{pass::{StoreOp, LoadOp, TextureAttachment, RenderPassColorAttachmentDescriptor, PassDescriptor, RenderPassDepthStencilAttachmentDescriptor}, texture::{TextureDescriptor, TextureFormat, TextureUsage}}; -use bevy_window::{WindowId, WindowReference}; +use bevy::{ + prelude::*, + render::{ + pass::{ + LoadOp, PassDescriptor, RenderPassColorAttachmentDescriptor, + RenderPassDepthStencilAttachmentDescriptor, StoreOp, TextureAttachment, + }, + texture::{TextureDescriptor, TextureFormat, TextureUsage}, + ActiveCameras, + }, + window::{CreateWindow, WindowId, WindowReference}, +}; fn main() { App::build() .add_default_plugins() - .add_startup_system(create_second_window_system.system()) - .add_startup_system(setup_scene.system()) + .add_startup_system(setup.system()) .run(); } -fn create_second_window_system( +fn setup( + command_buffer: &mut CommandBuffer, mut create_window_events: ResMut>, + mut active_cameras: ResMut, mut render_graph: ResMut, + mut materials: ResMut>, + asset_server: Res, ) { let window_id = WindowId::new(); @@ -48,6 +60,10 @@ fn create_second_window_system( ), ); + // add a new depth texture node for our new window + render_graph.add_system_node("secondary_camera", CameraNode::new("Secondary")); + + // add a new render pass for our new camera let mut second_window_pass = PassNode::new(PassDescriptor { color_attachments: vec![RenderPassColorAttachmentDescriptor { attachment: TextureAttachment::Input("color".to_string()), @@ -70,13 +86,10 @@ fn create_second_window_system( sample_count: 1, }); - // TODO: use different camera here - second_window_pass.add_camera(bevy::render::base_render_graph::camera::CAMERA); + second_window_pass.add_camera("Secondary"); + active_cameras.add("Secondary"); - render_graph.add_node( - "second_window_pass", - second_window_pass, - ); + render_graph.add_node("second_window_pass", second_window_pass); render_graph .add_slot_edge( @@ -95,13 +108,13 @@ fn create_second_window_system( "depth", ) .unwrap(); -} -fn setup_scene( - command_buffer: &mut CommandBuffer, - asset_server: Res, - mut materials: ResMut>, -) { + render_graph + .add_node_edge("secondary_camera", "second_window_pass") + .unwrap(); + + // SETUP SCENE + // load the mesh let mesh_handle = asset_server .load("assets/models/monkey/Monkey.gltf") @@ -135,18 +148,19 @@ fn setup_scene( Vec3::new(0.0, 1.0, 0.0), )), ..Default::default() + }) + // second window camera + .entity_with(PerspectiveCameraComponents { + camera: Camera { + name: Some("Secondary".to_string()), + window: WindowReference::Id(window_id), + ..Default::default() + }, + transform: Transform::new_sync_disabled(Mat4::face_toward( + Vec3::new(6.0, 0.0, 0.0), + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, 1.0, 0.0), + )), + ..Default::default() }); - // // second window camera - // .entity_with(PerspectiveCameraComponents { - // camera: Camera { - // name: Some("Secondary".to_string()), - // ..Default::default() - // }, - // transform: Transform::new_sync_disabled(Mat4::face_toward( - // Vec3::new(0.0, 0.0, 6.0), - // Vec3::new(0.0, 0.0, 0.0), - // Vec3::new(0.0, 1.0, 0.0), - // )), - // ..Default::default() - // }); }