Path: blob/main/crates/bevy_post_process/src/motion_blur/node.rs
6596 views
use bevy_ecs::{query::QueryItem, world::World};1use bevy_render::{2diagnostic::RecordDiagnostics,3extract_component::ComponentUniforms,4globals::GlobalsBuffer,5render_graph::{NodeRunError, RenderGraphContext, ViewNode},6render_resource::{7BindGroupEntries, Operations, PipelineCache, RenderPassColorAttachment,8RenderPassDescriptor,9},10renderer::RenderContext,11view::{Msaa, ViewTarget},12};1314use bevy_core_pipeline::prepass::ViewPrepassTextures;1516use super::{17pipeline::{MotionBlurPipeline, MotionBlurPipelineId},18MotionBlurUniform,19};2021#[derive(Default)]22pub struct MotionBlurNode;2324impl ViewNode for MotionBlurNode {25type ViewQuery = (26&'static ViewTarget,27&'static MotionBlurPipelineId,28&'static ViewPrepassTextures,29&'static MotionBlurUniform,30&'static Msaa,31);32fn run(33&self,34_graph: &mut RenderGraphContext,35render_context: &mut RenderContext,36(view_target, pipeline_id, prepass_textures, motion_blur, msaa): QueryItem<Self::ViewQuery>,37world: &World,38) -> Result<(), NodeRunError> {39if motion_blur.samples == 0 || motion_blur.shutter_angle <= 0.0 {40return Ok(()); // We can skip running motion blur in these cases.41}4243let motion_blur_pipeline = world.resource::<MotionBlurPipeline>();44let pipeline_cache = world.resource::<PipelineCache>();45let settings_uniforms = world.resource::<ComponentUniforms<MotionBlurUniform>>();46let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline_id.0) else {47return Ok(());48};4950let Some(settings_binding) = settings_uniforms.uniforms().binding() else {51return Ok(());52};53let (Some(prepass_motion_vectors_texture), Some(prepass_depth_texture)) =54(&prepass_textures.motion_vectors, &prepass_textures.depth)55else {56return Ok(());57};58let Some(globals_uniforms) = world.resource::<GlobalsBuffer>().buffer.binding() else {59return Ok(());60};6162let diagnostics = render_context.diagnostic_recorder();6364let post_process = view_target.post_process_write();6566let layout = if msaa.samples() == 1 {67&motion_blur_pipeline.layout68} else {69&motion_blur_pipeline.layout_msaa70};7172let bind_group = render_context.render_device().create_bind_group(73Some("motion_blur_bind_group"),74layout,75&BindGroupEntries::sequential((76post_process.source,77&prepass_motion_vectors_texture.texture.default_view,78&prepass_depth_texture.texture.default_view,79&motion_blur_pipeline.sampler,80settings_binding.clone(),81globals_uniforms.clone(),82)),83);8485let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {86label: Some("motion_blur"),87color_attachments: &[Some(RenderPassColorAttachment {88view: post_process.destination,89depth_slice: None,90resolve_target: None,91ops: Operations::default(),92})],93depth_stencil_attachment: None,94timestamp_writes: None,95occlusion_query_set: None,96});97let pass_span = diagnostics.pass_span(&mut render_pass, "motion_blur");9899render_pass.set_render_pipeline(pipeline);100render_pass.set_bind_group(0, &bind_group, &[]);101render_pass.draw(0..3, 0..1);102103pass_span.end(&mut render_pass);104105Ok(())106}107}108109110