Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_pbr/src/meshlet/material_shade_nodes.rs
6600 views
1
use super::{
2
material_pipeline_prepare::{
3
MeshletViewMaterialsDeferredGBufferPrepass, MeshletViewMaterialsMainOpaquePass,
4
MeshletViewMaterialsPrepass,
5
},
6
resource_manager::{MeshletViewBindGroups, MeshletViewResources},
7
InstanceManager,
8
};
9
use crate::{
10
MeshViewBindGroup, PrepassViewBindGroup, ViewEnvironmentMapUniformOffset, ViewFogUniformOffset,
11
ViewLightProbesUniformOffset, ViewLightsUniformOffset, ViewScreenSpaceReflectionsUniformOffset,
12
};
13
use bevy_camera::MainPassResolutionOverride;
14
use bevy_camera::Viewport;
15
use bevy_core_pipeline::prepass::{
16
MotionVectorPrepass, PreviousViewUniformOffset, ViewPrepassTextures,
17
};
18
use bevy_ecs::{
19
query::{Has, QueryItem},
20
world::World,
21
};
22
use bevy_render::{
23
camera::ExtractedCamera,
24
diagnostic::RecordDiagnostics,
25
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
26
render_resource::{
27
LoadOp, Operations, PipelineCache, RenderPassDepthStencilAttachment, RenderPassDescriptor,
28
StoreOp,
29
},
30
renderer::RenderContext,
31
view::{ViewTarget, ViewUniformOffset},
32
};
33
34
/// Fullscreen shading pass based on the visibility buffer generated from rasterizing meshlets.
35
#[derive(Default)]
36
pub struct MeshletMainOpaquePass3dNode;
37
impl ViewNode for MeshletMainOpaquePass3dNode {
38
type ViewQuery = (
39
&'static ExtractedCamera,
40
&'static ViewTarget,
41
&'static MeshViewBindGroup,
42
&'static ViewUniformOffset,
43
&'static ViewLightsUniformOffset,
44
&'static ViewFogUniformOffset,
45
&'static ViewLightProbesUniformOffset,
46
&'static ViewScreenSpaceReflectionsUniformOffset,
47
&'static ViewEnvironmentMapUniformOffset,
48
Option<&'static MainPassResolutionOverride>,
49
&'static MeshletViewMaterialsMainOpaquePass,
50
&'static MeshletViewBindGroups,
51
&'static MeshletViewResources,
52
);
53
54
fn run(
55
&self,
56
_graph: &mut RenderGraphContext,
57
render_context: &mut RenderContext,
58
(
59
camera,
60
target,
61
mesh_view_bind_group,
62
view_uniform_offset,
63
view_lights_offset,
64
view_fog_offset,
65
view_light_probes_offset,
66
view_ssr_offset,
67
view_environment_map_offset,
68
resolution_override,
69
meshlet_view_materials,
70
meshlet_view_bind_groups,
71
meshlet_view_resources,
72
): QueryItem<Self::ViewQuery>,
73
world: &World,
74
) -> Result<(), NodeRunError> {
75
if meshlet_view_materials.is_empty() {
76
return Ok(());
77
}
78
79
let (
80
Some(instance_manager),
81
Some(pipeline_cache),
82
Some(meshlet_material_depth),
83
Some(meshlet_material_shade_bind_group),
84
) = (
85
world.get_resource::<InstanceManager>(),
86
world.get_resource::<PipelineCache>(),
87
meshlet_view_resources.material_depth.as_ref(),
88
meshlet_view_bind_groups.material_shade.as_ref(),
89
)
90
else {
91
return Ok(());
92
};
93
94
let diagnostics = render_context.diagnostic_recorder();
95
96
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
97
label: Some("meshlet_material_opaque_3d_pass"),
98
color_attachments: &[Some(target.get_color_attachment())],
99
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
100
view: &meshlet_material_depth.default_view,
101
depth_ops: Some(Operations {
102
load: LoadOp::Load,
103
store: StoreOp::Store,
104
}),
105
stencil_ops: None,
106
}),
107
timestamp_writes: None,
108
occlusion_query_set: None,
109
});
110
let pass_span = diagnostics.pass_span(&mut render_pass, "meshlet_material_opaque_3d_pass");
111
if let Some(viewport) =
112
Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
113
{
114
render_pass.set_camera_viewport(&viewport);
115
}
116
117
render_pass.set_bind_group(
118
0,
119
&mesh_view_bind_group.main,
120
&[
121
view_uniform_offset.offset,
122
view_lights_offset.offset,
123
view_fog_offset.offset,
124
**view_light_probes_offset,
125
**view_ssr_offset,
126
**view_environment_map_offset,
127
],
128
);
129
render_pass.set_bind_group(1, &mesh_view_bind_group.binding_array, &[]);
130
render_pass.set_bind_group(2, meshlet_material_shade_bind_group, &[]);
131
132
// 1 fullscreen triangle draw per material
133
for (material_id, material_pipeline_id, material_bind_group) in
134
meshlet_view_materials.iter()
135
{
136
if instance_manager.material_present_in_scene(material_id)
137
&& let Some(material_pipeline) =
138
pipeline_cache.get_render_pipeline(*material_pipeline_id)
139
{
140
let x = *material_id * 3;
141
render_pass.set_render_pipeline(material_pipeline);
142
render_pass.set_bind_group(3, material_bind_group, &[]);
143
render_pass.draw(x..(x + 3), 0..1);
144
}
145
}
146
147
pass_span.end(&mut render_pass);
148
149
Ok(())
150
}
151
}
152
153
/// Fullscreen pass to generate prepass textures based on the visibility buffer generated from rasterizing meshlets.
154
#[derive(Default)]
155
pub struct MeshletPrepassNode;
156
impl ViewNode for MeshletPrepassNode {
157
type ViewQuery = (
158
&'static ExtractedCamera,
159
&'static ViewPrepassTextures,
160
&'static ViewUniformOffset,
161
&'static PreviousViewUniformOffset,
162
Option<&'static MainPassResolutionOverride>,
163
Has<MotionVectorPrepass>,
164
&'static MeshletViewMaterialsPrepass,
165
&'static MeshletViewBindGroups,
166
&'static MeshletViewResources,
167
);
168
169
fn run(
170
&self,
171
_graph: &mut RenderGraphContext,
172
render_context: &mut RenderContext,
173
(
174
camera,
175
view_prepass_textures,
176
view_uniform_offset,
177
previous_view_uniform_offset,
178
resolution_override,
179
view_has_motion_vector_prepass,
180
meshlet_view_materials,
181
meshlet_view_bind_groups,
182
meshlet_view_resources,
183
): QueryItem<Self::ViewQuery>,
184
world: &World,
185
) -> Result<(), NodeRunError> {
186
if meshlet_view_materials.is_empty() {
187
return Ok(());
188
}
189
190
let (
191
Some(prepass_view_bind_group),
192
Some(instance_manager),
193
Some(pipeline_cache),
194
Some(meshlet_material_depth),
195
Some(meshlet_material_shade_bind_group),
196
) = (
197
world.get_resource::<PrepassViewBindGroup>(),
198
world.get_resource::<InstanceManager>(),
199
world.get_resource::<PipelineCache>(),
200
meshlet_view_resources.material_depth.as_ref(),
201
meshlet_view_bind_groups.material_shade.as_ref(),
202
)
203
else {
204
return Ok(());
205
};
206
207
let diagnostics = render_context.diagnostic_recorder();
208
209
let color_attachments = vec![
210
view_prepass_textures
211
.normal
212
.as_ref()
213
.map(|normals_texture| normals_texture.get_attachment()),
214
view_prepass_textures
215
.motion_vectors
216
.as_ref()
217
.map(|motion_vectors_texture| motion_vectors_texture.get_attachment()),
218
// Use None in place of Deferred attachments
219
None,
220
None,
221
];
222
223
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
224
label: Some("meshlet_material_prepass"),
225
color_attachments: &color_attachments,
226
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
227
view: &meshlet_material_depth.default_view,
228
depth_ops: Some(Operations {
229
load: LoadOp::Load,
230
store: StoreOp::Store,
231
}),
232
stencil_ops: None,
233
}),
234
timestamp_writes: None,
235
occlusion_query_set: None,
236
});
237
let pass_span = diagnostics.pass_span(&mut render_pass, "meshlet_material_prepass");
238
if let Some(viewport) =
239
Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
240
{
241
render_pass.set_camera_viewport(&viewport);
242
}
243
244
if view_has_motion_vector_prepass {
245
render_pass.set_bind_group(
246
0,
247
prepass_view_bind_group.motion_vectors.as_ref().unwrap(),
248
&[
249
view_uniform_offset.offset,
250
previous_view_uniform_offset.offset,
251
],
252
);
253
} else {
254
render_pass.set_bind_group(
255
0,
256
prepass_view_bind_group.no_motion_vectors.as_ref().unwrap(),
257
&[view_uniform_offset.offset],
258
);
259
}
260
261
render_pass.set_bind_group(1, &prepass_view_bind_group.empty_bind_group, &[]);
262
render_pass.set_bind_group(2, meshlet_material_shade_bind_group, &[]);
263
264
// 1 fullscreen triangle draw per material
265
for (material_id, material_pipeline_id, material_bind_group) in
266
meshlet_view_materials.iter()
267
{
268
if instance_manager.material_present_in_scene(material_id)
269
&& let Some(material_pipeline) =
270
pipeline_cache.get_render_pipeline(*material_pipeline_id)
271
{
272
let x = *material_id * 3;
273
render_pass.set_render_pipeline(material_pipeline);
274
render_pass.set_bind_group(2, material_bind_group, &[]);
275
render_pass.draw(x..(x + 3), 0..1);
276
}
277
}
278
279
pass_span.end(&mut render_pass);
280
281
Ok(())
282
}
283
}
284
285
/// Fullscreen pass to generate a gbuffer based on the visibility buffer generated from rasterizing meshlets.
286
#[derive(Default)]
287
pub struct MeshletDeferredGBufferPrepassNode;
288
impl ViewNode for MeshletDeferredGBufferPrepassNode {
289
type ViewQuery = (
290
&'static ExtractedCamera,
291
&'static ViewPrepassTextures,
292
&'static ViewUniformOffset,
293
&'static PreviousViewUniformOffset,
294
Option<&'static MainPassResolutionOverride>,
295
Has<MotionVectorPrepass>,
296
&'static MeshletViewMaterialsDeferredGBufferPrepass,
297
&'static MeshletViewBindGroups,
298
&'static MeshletViewResources,
299
);
300
301
fn run(
302
&self,
303
_graph: &mut RenderGraphContext,
304
render_context: &mut RenderContext,
305
(
306
camera,
307
view_prepass_textures,
308
view_uniform_offset,
309
previous_view_uniform_offset,
310
resolution_override,
311
view_has_motion_vector_prepass,
312
meshlet_view_materials,
313
meshlet_view_bind_groups,
314
meshlet_view_resources,
315
): QueryItem<Self::ViewQuery>,
316
world: &World,
317
) -> Result<(), NodeRunError> {
318
if meshlet_view_materials.is_empty() {
319
return Ok(());
320
}
321
322
let (
323
Some(prepass_view_bind_group),
324
Some(instance_manager),
325
Some(pipeline_cache),
326
Some(meshlet_material_depth),
327
Some(meshlet_material_shade_bind_group),
328
) = (
329
world.get_resource::<PrepassViewBindGroup>(),
330
world.get_resource::<InstanceManager>(),
331
world.get_resource::<PipelineCache>(),
332
meshlet_view_resources.material_depth.as_ref(),
333
meshlet_view_bind_groups.material_shade.as_ref(),
334
)
335
else {
336
return Ok(());
337
};
338
339
let color_attachments = vec![
340
view_prepass_textures
341
.normal
342
.as_ref()
343
.map(|normals_texture| normals_texture.get_attachment()),
344
view_prepass_textures
345
.motion_vectors
346
.as_ref()
347
.map(|motion_vectors_texture| motion_vectors_texture.get_attachment()),
348
view_prepass_textures
349
.deferred
350
.as_ref()
351
.map(|deferred_texture| deferred_texture.get_attachment()),
352
view_prepass_textures
353
.deferred_lighting_pass_id
354
.as_ref()
355
.map(|deferred_lighting_pass_id| deferred_lighting_pass_id.get_attachment()),
356
];
357
358
let diagnostics = render_context.diagnostic_recorder();
359
360
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
361
label: Some("meshlet_material_deferred_prepass"),
362
color_attachments: &color_attachments,
363
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
364
view: &meshlet_material_depth.default_view,
365
depth_ops: Some(Operations {
366
load: LoadOp::Load,
367
store: StoreOp::Store,
368
}),
369
stencil_ops: None,
370
}),
371
timestamp_writes: None,
372
occlusion_query_set: None,
373
});
374
let pass_span =
375
diagnostics.pass_span(&mut render_pass, "meshlet_material_deferred_prepass");
376
if let Some(viewport) =
377
Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)
378
{
379
render_pass.set_camera_viewport(&viewport);
380
}
381
382
if view_has_motion_vector_prepass {
383
render_pass.set_bind_group(
384
0,
385
prepass_view_bind_group.motion_vectors.as_ref().unwrap(),
386
&[
387
view_uniform_offset.offset,
388
previous_view_uniform_offset.offset,
389
],
390
);
391
} else {
392
render_pass.set_bind_group(
393
0,
394
prepass_view_bind_group.no_motion_vectors.as_ref().unwrap(),
395
&[view_uniform_offset.offset],
396
);
397
}
398
399
render_pass.set_bind_group(1, &prepass_view_bind_group.empty_bind_group, &[]);
400
render_pass.set_bind_group(2, meshlet_material_shade_bind_group, &[]);
401
402
// 1 fullscreen triangle draw per material
403
for (material_id, material_pipeline_id, material_bind_group) in
404
meshlet_view_materials.iter()
405
{
406
if instance_manager.material_present_in_scene(material_id)
407
&& let Some(material_pipeline) =
408
pipeline_cache.get_render_pipeline(*material_pipeline_id)
409
{
410
let x = *material_id * 3;
411
render_pass.set_render_pipeline(material_pipeline);
412
render_pass.set_bind_group(2, material_bind_group, &[]);
413
render_pass.draw(x..(x + 3), 0..1);
414
}
415
}
416
417
pass_span.end(&mut render_pass);
418
419
Ok(())
420
}
421
}
422
423