181 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			181 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use bevy::{
 | |
|     prelude::*,
 | |
|     render::{
 | |
|         camera::{ActiveCameras, Camera},
 | |
|         pass::*,
 | |
|         render_graph::{
 | |
|             base::MainPass, CameraNode, PassNode, RenderGraph, WindowSwapChainNode,
 | |
|             WindowTextureNode,
 | |
|         },
 | |
|         texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
 | |
|     },
 | |
|     window::{CreateWindow, WindowDescriptor, WindowId},
 | |
| };
 | |
| 
 | |
| /// This example creates a second window and draws a mesh from two different cameras.
 | |
| fn main() {
 | |
|     App::build()
 | |
|         .add_resource(Msaa { samples: 4 })
 | |
|         .add_plugins(DefaultPlugins)
 | |
|         .add_startup_system(setup.system())
 | |
|         .run();
 | |
| }
 | |
| 
 | |
| fn setup(
 | |
|     commands: &mut Commands,
 | |
|     mut create_window_events: ResMut<Events<CreateWindow>>,
 | |
|     mut active_cameras: ResMut<ActiveCameras>,
 | |
|     mut render_graph: ResMut<RenderGraph>,
 | |
|     asset_server: Res<AssetServer>,
 | |
|     msaa: Res<Msaa>,
 | |
| ) {
 | |
|     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: "second window".to_string(),
 | |
|             ..Default::default()
 | |
|         },
 | |
|     });
 | |
| 
 | |
|     // 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(window_id),
 | |
|     );
 | |
| 
 | |
|     // add a new depth texture node for our new window
 | |
|     render_graph.add_node(
 | |
|         "second_window_depth_texture",
 | |
|         WindowTextureNode::new(
 | |
|             window_id,
 | |
|             TextureDescriptor {
 | |
|                 format: TextureFormat::Depth32Float,
 | |
|                 usage: TextureUsage::OUTPUT_ATTACHMENT,
 | |
|                 sample_count: msaa.samples,
 | |
|                 ..Default::default()
 | |
|             },
 | |
|         ),
 | |
|     );
 | |
| 
 | |
|     // add a new camera node for our new window
 | |
|     render_graph.add_system_node("secondary_camera", CameraNode::new("Secondary"));
 | |
| 
 | |
|     // add a new render pass for our new window / camera
 | |
|     let mut second_window_pass = PassNode::<&MainPass>::new(PassDescriptor {
 | |
|         color_attachments: vec![msaa.color_attachment_descriptor(
 | |
|             TextureAttachment::Input("color_attachment".to_string()),
 | |
|             TextureAttachment::Input("color_resolve_target".to_string()),
 | |
|             Operations {
 | |
|                 load: LoadOp::Clear(Color::rgb(0.5, 0.5, 0.8)),
 | |
|                 store: true,
 | |
|             },
 | |
|         )],
 | |
|         depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
 | |
|             attachment: TextureAttachment::Input("depth".to_string()),
 | |
|             depth_ops: Some(Operations {
 | |
|                 load: LoadOp::Clear(1.0),
 | |
|                 store: true,
 | |
|             }),
 | |
|             stencil_ops: None,
 | |
|         }),
 | |
|         sample_count: msaa.samples,
 | |
|     });
 | |
| 
 | |
|     second_window_pass.add_camera("Secondary");
 | |
|     active_cameras.add("Secondary");
 | |
| 
 | |
|     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",
 | |
|             if msaa.samples > 1 {
 | |
|                 "color_resolve_target"
 | |
|             } else {
 | |
|                 "color_attachment"
 | |
|             },
 | |
|         )
 | |
|         .unwrap();
 | |
| 
 | |
|     render_graph
 | |
|         .add_slot_edge(
 | |
|             "second_window_depth_texture",
 | |
|             WindowTextureNode::OUT_TEXTURE,
 | |
|             "second_window_pass",
 | |
|             "depth",
 | |
|         )
 | |
|         .unwrap();
 | |
| 
 | |
|     render_graph
 | |
|         .add_node_edge("secondary_camera", "second_window_pass")
 | |
|         .unwrap();
 | |
| 
 | |
|     if msaa.samples > 1 {
 | |
|         render_graph.add_node(
 | |
|             "second_multi_sampled_color_attachment",
 | |
|             WindowTextureNode::new(
 | |
|                 window_id,
 | |
|                 TextureDescriptor {
 | |
|                     size: Extent3d {
 | |
|                         depth: 1,
 | |
|                         width: 1,
 | |
|                         height: 1,
 | |
|                     },
 | |
|                     mip_level_count: 1,
 | |
|                     sample_count: msaa.samples,
 | |
|                     dimension: TextureDimension::D2,
 | |
|                     format: TextureFormat::default(),
 | |
|                     usage: TextureUsage::OUTPUT_ATTACHMENT,
 | |
|                 },
 | |
|             ),
 | |
|         );
 | |
| 
 | |
|         render_graph
 | |
|             .add_slot_edge(
 | |
|                 "second_multi_sampled_color_attachment",
 | |
|                 WindowSwapChainNode::OUT_TEXTURE,
 | |
|                 "second_window_pass",
 | |
|                 "color_attachment",
 | |
|             )
 | |
|             .unwrap();
 | |
|     }
 | |
| 
 | |
|     // SETUP SCENE
 | |
| 
 | |
|     // add entities to the world
 | |
|     commands
 | |
|         .spawn_scene(asset_server.load("models/monkey/Monkey.gltf"))
 | |
|         // light
 | |
|         .spawn(LightBundle {
 | |
|             transform: Transform::from_translation(Vec3::new(4.0, 5.0, 4.0)),
 | |
|             ..Default::default()
 | |
|         })
 | |
|         // main camera
 | |
|         .spawn(Camera3dBundle {
 | |
|             transform: Transform::from_translation(Vec3::new(0.0, 0.0, 6.0))
 | |
|                 .looking_at(Vec3::default(), Vec3::unit_y()),
 | |
|             ..Default::default()
 | |
|         })
 | |
|         // second window camera
 | |
|         .spawn(Camera3dBundle {
 | |
|             camera: Camera {
 | |
|                 name: Some("Secondary".to_string()),
 | |
|                 window: window_id,
 | |
|                 ..Default::default()
 | |
|             },
 | |
|             transform: Transform::from_translation(Vec3::new(6.0, 0.0, 0.0))
 | |
|                 .looking_at(Vec3::default(), Vec3::unit_y()),
 | |
|             ..Default::default()
 | |
|         });
 | |
| }
 | 
