bevy_render/camera/
camera_driver_node.rs1use crate::{
2 camera::{ExtractedCamera, NormalizedRenderTarget, SortedCameras},
3 render_graph::{Node, NodeRunError, RenderGraphContext},
4 renderer::RenderContext,
5 view::ExtractedWindows,
6};
7use bevy_ecs::{prelude::QueryState, world::World};
8use bevy_utils::HashSet;
9use wgpu::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDescriptor, StoreOp};
10
11pub struct CameraDriverNode {
12 cameras: QueryState<&'static ExtractedCamera>,
13}
14
15impl CameraDriverNode {
16 pub fn new(world: &mut World) -> Self {
17 Self {
18 cameras: world.query(),
19 }
20 }
21}
22
23impl Node for CameraDriverNode {
24 fn update(&mut self, world: &mut World) {
25 self.cameras.update_archetypes(world);
26 }
27 fn run(
28 &self,
29 graph: &mut RenderGraphContext,
30 render_context: &mut RenderContext,
31 world: &World,
32 ) -> Result<(), NodeRunError> {
33 let sorted_cameras = world.resource::<SortedCameras>();
34 let windows = world.resource::<ExtractedWindows>();
35 let mut camera_windows = HashSet::new();
36 for sorted_camera in &sorted_cameras.0 {
37 let Ok(camera) = self.cameras.get_manual(world, sorted_camera.entity) else {
38 continue;
39 };
40
41 let mut run_graph = true;
42 if let Some(NormalizedRenderTarget::Window(window_ref)) = camera.target {
43 let window_entity = window_ref.entity();
44 if windows.windows.get(&window_entity).is_some() {
45 camera_windows.insert(window_entity);
46 } else {
47 run_graph = false;
49 }
50 }
51 if run_graph {
52 graph.run_sub_graph(camera.render_graph, vec![], Some(sorted_camera.entity))?;
53 }
54 }
55
56 for (id, window) in world.resource::<ExtractedWindows>().iter() {
59 if camera_windows.contains(id) {
60 continue;
61 }
62
63 let Some(swap_chain_texture) = &window.swap_chain_texture_view else {
64 continue;
65 };
66
67 #[cfg(feature = "trace")]
68 let _span = bevy_utils::tracing::info_span!("no_camera_clear_pass").entered();
69 let pass_descriptor = RenderPassDescriptor {
70 label: Some("no_camera_clear_pass"),
71 color_attachments: &[Some(RenderPassColorAttachment {
72 view: swap_chain_texture,
73 resolve_target: None,
74 ops: Operations {
75 load: LoadOp::Clear(wgpu::Color::BLACK),
76 store: StoreOp::Store,
77 },
78 })],
79 depth_stencil_attachment: None,
80 timestamp_writes: None,
81 occlusion_query_set: None,
82 };
83
84 render_context
85 .command_encoder()
86 .begin_render_pass(&pass_descriptor);
87 }
88
89 Ok(())
90 }
91}