bevy_core_pipeline/oit/resolve/
node.rs

1use bevy_ecs::{prelude::*, query::QueryItem};
2use bevy_render::{
3    camera::ExtractedCamera,
4    render_graph::{NodeRunError, RenderGraphContext, RenderLabel, ViewNode},
5    render_resource::{BindGroupEntries, PipelineCache, RenderPassDescriptor},
6    renderer::RenderContext,
7    view::{ViewDepthTexture, ViewTarget, ViewUniformOffset},
8};
9
10use super::{OitResolveBindGroup, OitResolvePipeline, OitResolvePipelineId};
11
12/// Render label for the OIT resolve pass.
13#[derive(RenderLabel, Debug, Clone, Hash, PartialEq, Eq)]
14pub struct OitResolvePass;
15
16/// The node that executes the OIT resolve pass.
17#[derive(Default)]
18pub struct OitResolveNode;
19impl ViewNode for OitResolveNode {
20    type ViewQuery = (
21        &'static ExtractedCamera,
22        &'static ViewTarget,
23        &'static ViewUniformOffset,
24        &'static OitResolvePipelineId,
25        &'static ViewDepthTexture,
26    );
27
28    fn run(
29        &self,
30        _graph: &mut RenderGraphContext,
31        render_context: &mut RenderContext,
32        (camera, view_target, view_uniform, oit_resolve_pipeline_id, depth): QueryItem<
33            Self::ViewQuery,
34        >,
35        world: &World,
36    ) -> Result<(), NodeRunError> {
37        let Some(resolve_pipeline) = world.get_resource::<OitResolvePipeline>() else {
38            return Ok(());
39        };
40
41        // resolve oit
42        // sorts the layers and renders the final blended color to the screen
43        {
44            let pipeline_cache = world.resource::<PipelineCache>();
45            let bind_group = world.resource::<OitResolveBindGroup>();
46            let Some(pipeline) = pipeline_cache.get_render_pipeline(oit_resolve_pipeline_id.0)
47            else {
48                return Ok(());
49            };
50
51            let depth_bind_group = render_context.render_device().create_bind_group(
52                "oit_resolve_depth_bind_group",
53                &resolve_pipeline.oit_depth_bind_group_layout,
54                &BindGroupEntries::single(depth.view()),
55            );
56
57            let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
58                label: Some("oit_resolve_pass"),
59                color_attachments: &[Some(view_target.get_color_attachment())],
60                depth_stencil_attachment: None,
61                timestamp_writes: None,
62                occlusion_query_set: None,
63            });
64
65            if let Some(viewport) = camera.viewport.as_ref() {
66                render_pass.set_camera_viewport(viewport);
67            }
68
69            render_pass.set_render_pipeline(pipeline);
70            render_pass.set_bind_group(0, bind_group, &[view_uniform.offset]);
71            render_pass.set_bind_group(1, &depth_bind_group, &[]);
72
73            render_pass.draw(0..3, 0..1);
74        }
75
76        Ok(())
77    }
78}