Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_post_process/src/motion_blur/pipeline.rs
6596 views
1
use bevy_asset::{load_embedded_asset, AssetServer, Handle};
2
use bevy_core_pipeline::FullscreenShader;
3
use bevy_ecs::{
4
component::Component,
5
entity::Entity,
6
query::With,
7
resource::Resource,
8
system::{Commands, Query, Res, ResMut},
9
};
10
use bevy_image::BevyDefault as _;
11
use bevy_render::{
12
globals::GlobalsUniform,
13
render_resource::{
14
binding_types::{
15
sampler, texture_2d, texture_2d_multisampled, texture_depth_2d,
16
texture_depth_2d_multisampled, uniform_buffer_sized,
17
},
18
BindGroupLayout, BindGroupLayoutEntries, CachedRenderPipelineId, ColorTargetState,
19
ColorWrites, FragmentState, PipelineCache, RenderPipelineDescriptor, Sampler,
20
SamplerBindingType, SamplerDescriptor, ShaderStages, ShaderType, SpecializedRenderPipeline,
21
SpecializedRenderPipelines, TextureFormat, TextureSampleType,
22
},
23
renderer::RenderDevice,
24
view::{ExtractedView, Msaa, ViewTarget},
25
};
26
use bevy_shader::{Shader, ShaderDefVal};
27
use bevy_utils::default;
28
29
use super::MotionBlurUniform;
30
31
#[derive(Resource)]
32
pub struct MotionBlurPipeline {
33
pub(crate) sampler: Sampler,
34
pub(crate) layout: BindGroupLayout,
35
pub(crate) layout_msaa: BindGroupLayout,
36
pub(crate) fullscreen_shader: FullscreenShader,
37
pub(crate) fragment_shader: Handle<Shader>,
38
}
39
40
impl MotionBlurPipeline {
41
pub(crate) fn new(
42
render_device: &RenderDevice,
43
fullscreen_shader: FullscreenShader,
44
fragment_shader: Handle<Shader>,
45
) -> Self {
46
let mb_layout = &BindGroupLayoutEntries::sequential(
47
ShaderStages::FRAGMENT,
48
(
49
// View target (read)
50
texture_2d(TextureSampleType::Float { filterable: true }),
51
// Motion Vectors
52
texture_2d(TextureSampleType::Float { filterable: true }),
53
// Depth
54
texture_depth_2d(),
55
// Linear Sampler
56
sampler(SamplerBindingType::Filtering),
57
// Motion blur settings uniform input
58
uniform_buffer_sized(false, Some(MotionBlurUniform::min_size())),
59
// Globals uniform input
60
uniform_buffer_sized(false, Some(GlobalsUniform::min_size())),
61
),
62
);
63
64
let mb_layout_msaa = &BindGroupLayoutEntries::sequential(
65
ShaderStages::FRAGMENT,
66
(
67
// View target (read)
68
texture_2d(TextureSampleType::Float { filterable: true }),
69
// Motion Vectors
70
texture_2d_multisampled(TextureSampleType::Float { filterable: false }),
71
// Depth
72
texture_depth_2d_multisampled(),
73
// Linear Sampler
74
sampler(SamplerBindingType::Filtering),
75
// Motion blur settings uniform input
76
uniform_buffer_sized(false, Some(MotionBlurUniform::min_size())),
77
// Globals uniform input
78
uniform_buffer_sized(false, Some(GlobalsUniform::min_size())),
79
),
80
);
81
82
let sampler = render_device.create_sampler(&SamplerDescriptor::default());
83
let layout = render_device.create_bind_group_layout("motion_blur_layout", mb_layout);
84
let layout_msaa =
85
render_device.create_bind_group_layout("motion_blur_layout_msaa", mb_layout_msaa);
86
87
Self {
88
sampler,
89
layout,
90
layout_msaa,
91
fullscreen_shader,
92
fragment_shader,
93
}
94
}
95
}
96
97
pub fn init_motion_blur_pipeline(
98
mut commands: Commands,
99
render_device: Res<RenderDevice>,
100
fullscreen_shader: Res<FullscreenShader>,
101
asset_server: Res<AssetServer>,
102
) {
103
let fullscreen_shader = fullscreen_shader.clone();
104
let fragment_shader = load_embedded_asset!(asset_server.as_ref(), "motion_blur.wgsl");
105
commands.insert_resource(MotionBlurPipeline::new(
106
&render_device,
107
fullscreen_shader,
108
fragment_shader,
109
));
110
}
111
112
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
113
pub struct MotionBlurPipelineKey {
114
hdr: bool,
115
samples: u32,
116
}
117
118
impl SpecializedRenderPipeline for MotionBlurPipeline {
119
type Key = MotionBlurPipelineKey;
120
121
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
122
let layout = match key.samples {
123
1 => vec![self.layout.clone()],
124
_ => vec![self.layout_msaa.clone()],
125
};
126
127
let mut shader_defs = vec![];
128
129
if key.samples > 1 {
130
shader_defs.push(ShaderDefVal::from("MULTISAMPLED"));
131
}
132
133
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
134
{
135
shader_defs.push("NO_DEPTH_TEXTURE_SUPPORT".into());
136
shader_defs.push("SIXTEEN_BYTE_ALIGNMENT".into());
137
}
138
139
RenderPipelineDescriptor {
140
label: Some("motion_blur_pipeline".into()),
141
layout,
142
vertex: self.fullscreen_shader.to_vertex_state(),
143
fragment: Some(FragmentState {
144
shader: self.fragment_shader.clone(),
145
shader_defs,
146
targets: vec![Some(ColorTargetState {
147
format: if key.hdr {
148
ViewTarget::TEXTURE_FORMAT_HDR
149
} else {
150
TextureFormat::bevy_default()
151
},
152
blend: None,
153
write_mask: ColorWrites::ALL,
154
})],
155
..default()
156
}),
157
..default()
158
}
159
}
160
}
161
162
#[derive(Component)]
163
pub struct MotionBlurPipelineId(pub CachedRenderPipelineId);
164
165
pub(crate) fn prepare_motion_blur_pipelines(
166
mut commands: Commands,
167
pipeline_cache: Res<PipelineCache>,
168
mut pipelines: ResMut<SpecializedRenderPipelines<MotionBlurPipeline>>,
169
pipeline: Res<MotionBlurPipeline>,
170
views: Query<(Entity, &ExtractedView, &Msaa), With<MotionBlurUniform>>,
171
) {
172
for (entity, view, msaa) in &views {
173
let pipeline_id = pipelines.specialize(
174
&pipeline_cache,
175
&pipeline,
176
MotionBlurPipelineKey {
177
hdr: view.hdr,
178
samples: msaa.samples(),
179
},
180
);
181
182
commands
183
.entity(entity)
184
.insert(MotionBlurPipelineId(pipeline_id));
185
}
186
}
187
188