From ca4726ea7d0584551c2aeb5e84135de33c2c8acc Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Thu, 25 Jun 2020 16:02:21 -0700 Subject: [PATCH] render to second window in multiple_windows example --- .../src/texture/texture_descriptor.rs | 19 +++ crates/bevy_window/src/event.rs | 1 + crates/bevy_window/src/lib.rs | 1 + crates/bevy_window/src/window.rs | 8 +- crates/bevy_winit/src/lib.rs | 2 +- examples/window/multiple_windows.rs | 138 +++++++++++++++++- 6 files changed, 163 insertions(+), 6 deletions(-) diff --git a/crates/bevy_render/src/texture/texture_descriptor.rs b/crates/bevy_render/src/texture/texture_descriptor.rs index d19d28ecfc..08b6e6a2a4 100644 --- a/crates/bevy_render/src/texture/texture_descriptor.rs +++ b/crates/bevy_render/src/texture/texture_descriptor.rs @@ -26,3 +26,22 @@ impl From<&Texture> for TextureDescriptor { } } } + + +impl Default for TextureDescriptor { + fn default() -> Self { + TextureDescriptor { + size: Extent3d { + width: 1, + height: 1, + depth: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: TextureDimension::D2, + format: TextureFormat::Rgba8UnormSrgb, + usage: TextureUsage::SAMPLED | TextureUsage::COPY_DST, + } + } + +} \ No newline at end of file diff --git a/crates/bevy_window/src/event.rs b/crates/bevy_window/src/event.rs index 4d74711187..e4479f7427 100644 --- a/crates/bevy_window/src/event.rs +++ b/crates/bevy_window/src/event.rs @@ -13,6 +13,7 @@ pub struct WindowResized { /// An event that indicates that a new window should be created. #[derive(Debug, Clone)] pub struct CreateWindow { + pub id: WindowId, pub descriptor: WindowDescriptor, } diff --git a/crates/bevy_window/src/lib.rs b/crates/bevy_window/src/lib.rs index 58f0cc35c3..21819bcb99 100644 --- a/crates/bevy_window/src/lib.rs +++ b/crates/bevy_window/src/lib.rs @@ -38,6 +38,7 @@ impl AppPlugin for WindowPlugin { let mut create_window_event = app.resources().get_mut::>().unwrap(); create_window_event.send(CreateWindow { + id: WindowId::new(), descriptor: primary_window_descriptor.clone(), }); } diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index ed403186bc..5ee1d624e2 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -9,6 +9,10 @@ pub enum WindowReference { pub struct WindowId(Uuid); impl WindowId { + pub fn new() -> Self { + WindowId(Uuid::new_v4()) + } + pub fn to_string(&self) -> String { self.0.to_simple().to_string() } @@ -24,9 +28,9 @@ pub struct Window { } impl Window { - pub fn new(window_descriptor: &WindowDescriptor) -> Self { + pub fn new(id: WindowId, window_descriptor: &WindowDescriptor) -> Self { Window { - id: WindowId(Uuid::new_v4()), + id, height: window_descriptor.height, width: window_descriptor.width, title: window_descriptor.title.clone(), diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index 6e964a8e29..39ad9ec67b 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -155,7 +155,7 @@ fn handle_create_window_events( let create_window_events = resources.get::>().unwrap(); let mut window_created_events = resources.get_mut::>().unwrap(); for create_window_event in create_window_event_reader.iter(&create_window_events) { - let window = Window::new(&create_window_event.descriptor); + let window = Window::new(create_window_event.id, &create_window_event.descriptor); winit_windows.create_window(event_loop, &window); let window_id = window.id; windows.add(window); diff --git a/examples/window/multiple_windows.rs b/examples/window/multiple_windows.rs index 8319b98240..3ca25ba10c 100644 --- a/examples/window/multiple_windows.rs +++ b/examples/window/multiple_windows.rs @@ -1,20 +1,152 @@ use bevy::{prelude::*, window::CreateWindow}; +use bevy_render::{pass::{StoreOp, LoadOp, TextureAttachment, RenderPassColorAttachmentDescriptor, PassDescriptor, RenderPassDepthStencilAttachmentDescriptor}, texture::{TextureDescriptor, TextureFormat, TextureUsage}}; +use bevy_window::{WindowId, WindowReference}; fn main() { App::build() .add_default_plugins() - .add_startup_system(setup.system()) + .add_startup_system(create_second_window_system.system()) + .add_startup_system(setup_scene.system()) .run(); } -fn setup(mut create_window_events: ResMut>) { +fn create_second_window_system( + mut create_window_events: ResMut>, + mut render_graph: ResMut, +) { + let window_id = WindowId::new(); + // sends out a "CreateWindow" event, which will be received by the windowing backend create_window_events.send(CreateWindow { + id: window_id, descriptor: WindowDescriptor { width: 800, height: 600, vsync: false, - title: "another window".to_string(), + title: "second window".to_string(), }, }); + + // here we setup our render graph to draw our second camera to the new window's swap chain + + // add a swapchain node for our new window + render_graph.add_node( + "second_window_swap_chain", + WindowSwapChainNode::new(WindowReference::Id(window_id)), + ); + + // add a new depth texture node for our new window + render_graph.add_node( + "second_window_depth_texture", + WindowTextureNode::new( + WindowReference::Id(window_id), + TextureDescriptor { + format: TextureFormat::Depth32Float, + usage: TextureUsage::OUTPUT_ATTACHMENT, + ..Default::default() + }, + ), + ); + + let mut second_window_pass = PassNode::new(PassDescriptor { + color_attachments: vec![RenderPassColorAttachmentDescriptor { + attachment: TextureAttachment::Input("color".to_string()), + resolve_target: None, + load_op: LoadOp::Clear, + store_op: StoreOp::Store, + clear_color: Color::rgb(0.1, 0.1, 0.1), + }], + depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor { + attachment: TextureAttachment::Input("depth".to_string()), + depth_load_op: LoadOp::Clear, + depth_store_op: StoreOp::Store, + stencil_load_op: LoadOp::Clear, + stencil_store_op: StoreOp::Store, + stencil_read_only: false, + depth_read_only: false, + clear_depth: 1.0, + clear_stencil: 0, + }), + sample_count: 1, + }); + + // TODO: use different camera here + second_window_pass.add_camera(bevy::render::base_render_graph::camera::CAMERA); + + render_graph.add_node( + "second_window_pass", + second_window_pass, + ); + + render_graph + .add_slot_edge( + "second_window_swap_chain", + WindowSwapChainNode::OUT_TEXTURE, + "second_window_pass", + "color", + ) + .unwrap(); + + render_graph + .add_slot_edge( + "second_window_depth_texture", + WindowTextureNode::OUT_TEXTURE, + "second_window_pass", + "depth", + ) + .unwrap(); +} + +fn setup_scene( + command_buffer: &mut CommandBuffer, + asset_server: Res, + mut materials: ResMut>, +) { + // load the mesh + let mesh_handle = asset_server + .load("assets/models/monkey/Monkey.gltf") + .unwrap(); + + // create a material for the mesh + let material_handle = materials.add(StandardMaterial { + albedo: Color::rgb(0.5, 0.4, 0.3), + ..Default::default() + }); + + // add entities to the world + command_buffer + .build() + // mesh + .entity_with(MeshComponents { + mesh: mesh_handle, + material: material_handle, + ..Default::default() + }) + // light + .entity_with(LightComponents { + translation: Translation::new(4.0, 5.0, 4.0), + ..Default::default() + }) + // main camera + .entity_with(PerspectiveCameraComponents { + 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() + }); + // // 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() + // }); }