Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_post_process/src/motion_blur/node.rs
6596 views
1
use bevy_ecs::{query::QueryItem, world::World};
2
use bevy_render::{
3
diagnostic::RecordDiagnostics,
4
extract_component::ComponentUniforms,
5
globals::GlobalsBuffer,
6
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
7
render_resource::{
8
BindGroupEntries, Operations, PipelineCache, RenderPassColorAttachment,
9
RenderPassDescriptor,
10
},
11
renderer::RenderContext,
12
view::{Msaa, ViewTarget},
13
};
14
15
use bevy_core_pipeline::prepass::ViewPrepassTextures;
16
17
use super::{
18
pipeline::{MotionBlurPipeline, MotionBlurPipelineId},
19
MotionBlurUniform,
20
};
21
22
#[derive(Default)]
23
pub struct MotionBlurNode;
24
25
impl ViewNode for MotionBlurNode {
26
type ViewQuery = (
27
&'static ViewTarget,
28
&'static MotionBlurPipelineId,
29
&'static ViewPrepassTextures,
30
&'static MotionBlurUniform,
31
&'static Msaa,
32
);
33
fn run(
34
&self,
35
_graph: &mut RenderGraphContext,
36
render_context: &mut RenderContext,
37
(view_target, pipeline_id, prepass_textures, motion_blur, msaa): QueryItem<Self::ViewQuery>,
38
world: &World,
39
) -> Result<(), NodeRunError> {
40
if motion_blur.samples == 0 || motion_blur.shutter_angle <= 0.0 {
41
return Ok(()); // We can skip running motion blur in these cases.
42
}
43
44
let motion_blur_pipeline = world.resource::<MotionBlurPipeline>();
45
let pipeline_cache = world.resource::<PipelineCache>();
46
let settings_uniforms = world.resource::<ComponentUniforms<MotionBlurUniform>>();
47
let Some(pipeline) = pipeline_cache.get_render_pipeline(pipeline_id.0) else {
48
return Ok(());
49
};
50
51
let Some(settings_binding) = settings_uniforms.uniforms().binding() else {
52
return Ok(());
53
};
54
let (Some(prepass_motion_vectors_texture), Some(prepass_depth_texture)) =
55
(&prepass_textures.motion_vectors, &prepass_textures.depth)
56
else {
57
return Ok(());
58
};
59
let Some(globals_uniforms) = world.resource::<GlobalsBuffer>().buffer.binding() else {
60
return Ok(());
61
};
62
63
let diagnostics = render_context.diagnostic_recorder();
64
65
let post_process = view_target.post_process_write();
66
67
let layout = if msaa.samples() == 1 {
68
&motion_blur_pipeline.layout
69
} else {
70
&motion_blur_pipeline.layout_msaa
71
};
72
73
let bind_group = render_context.render_device().create_bind_group(
74
Some("motion_blur_bind_group"),
75
layout,
76
&BindGroupEntries::sequential((
77
post_process.source,
78
&prepass_motion_vectors_texture.texture.default_view,
79
&prepass_depth_texture.texture.default_view,
80
&motion_blur_pipeline.sampler,
81
settings_binding.clone(),
82
globals_uniforms.clone(),
83
)),
84
);
85
86
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
87
label: Some("motion_blur"),
88
color_attachments: &[Some(RenderPassColorAttachment {
89
view: post_process.destination,
90
depth_slice: None,
91
resolve_target: None,
92
ops: Operations::default(),
93
})],
94
depth_stencil_attachment: None,
95
timestamp_writes: None,
96
occlusion_query_set: None,
97
});
98
let pass_span = diagnostics.pass_span(&mut render_pass, "motion_blur");
99
100
render_pass.set_render_pipeline(pipeline);
101
render_pass.set_bind_group(0, &bind_group, &[]);
102
render_pass.draw(0..3, 0..1);
103
104
pass_span.end(&mut render_pass);
105
106
Ok(())
107
}
108
}
109
110