Skip to content

Commit a796d53

Browse files
authored
Meshlet prep (#11442)
# Objective - Prep for #10164 - Make deferred_lighting_pass_id a ColorAttachment - Correctly extract shadow view frusta so that the view uniforms get populated - Make some needed things public - Misc formatting
1 parent 2165793 commit a796d53

File tree

14 files changed

+75
-45
lines changed

14 files changed

+75
-45
lines changed

crates/bevy_core_pipeline/src/core_3d/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ pub fn prepare_prepass_textures(
805805
.clone()
806806
});
807807

808-
let deferred_lighting_pass_id_texture = deferred_prepass.then(|| {
808+
let cached_deferred_lighting_pass_id_texture = deferred_prepass.then(|| {
809809
deferred_lighting_id_textures
810810
.entry(camera.target.clone())
811811
.or_insert_with(|| {
@@ -836,7 +836,8 @@ pub fn prepare_prepass_textures(
836836
motion_vectors: cached_motion_vectors_texture
837837
.map(|t| ColorAttachment::new(t, None, Color::BLACK)),
838838
deferred: cached_deferred_texture.map(|t| ColorAttachment::new(t, None, Color::BLACK)),
839-
deferred_lighting_pass_id: deferred_lighting_pass_id_texture,
839+
deferred_lighting_pass_id: cached_deferred_lighting_pass_id_texture
840+
.map(|t| ColorAttachment::new(t, None, Color::BLACK)),
840841
size,
841842
});
842843
}

crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ impl ViewNode for CopyDeferredLightingIdNode {
9494
let bind_group = render_context.render_device().create_bind_group(
9595
"copy_deferred_lighting_id_bind_group",
9696
&copy_deferred_lighting_id_pipeline.layout,
97-
&BindGroupEntries::single(&deferred_lighting_pass_id_texture.default_view),
97+
&BindGroupEntries::single(&deferred_lighting_pass_id_texture.texture.default_view),
9898
);
9999

100100
let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {

crates/bevy_core_pipeline/src/deferred/node.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ use bevy_render::render_graph::ViewNode;
55
use bevy_render::render_resource::StoreOp;
66
use bevy_render::{
77
camera::ExtractedCamera,
8-
prelude::Color,
98
render_graph::{NodeRunError, RenderGraphContext},
109
render_phase::RenderPhase,
11-
render_resource::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDescriptor},
10+
render_resource::RenderPassDescriptor,
1211
renderer::RenderContext,
1312
view::ViewDepthTexture,
1413
};
@@ -83,11 +82,11 @@ impl ViewNode for DeferredGBufferPrepassNode {
8382
.map(|deferred_texture| {
8483
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
8584
{
86-
RenderPassColorAttachment {
85+
bevy_render::render_resource::RenderPassColorAttachment {
8786
view: &deferred_texture.texture.default_view,
8887
resolve_target: None,
89-
ops: Operations {
90-
load: LoadOp::Load,
88+
ops: bevy_render::render_resource::Operations {
89+
load: bevy_render::render_resource::LoadOp::Load,
9190
store: StoreOp::Store,
9291
},
9392
}
@@ -101,14 +100,7 @@ impl ViewNode for DeferredGBufferPrepassNode {
101100
view_prepass_textures
102101
.deferred_lighting_pass_id
103102
.as_ref()
104-
.map(|deferred_lighting_pass_id| RenderPassColorAttachment {
105-
view: &deferred_lighting_pass_id.default_view,
106-
resolve_target: None,
107-
ops: Operations {
108-
load: LoadOp::Clear(Color::BLACK.into()),
109-
store: StoreOp::Store,
110-
},
111-
}),
103+
.map(|deferred_lighting_pass_id| deferred_lighting_pass_id.get_attachment()),
112104
);
113105

114106
if color_attachments.iter().all(Option::is_none) {

crates/bevy_core_pipeline/src/prepass/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use bevy_reflect::Reflect;
3434
use bevy_render::{
3535
render_phase::{CachedRenderPipelinePhaseItem, DrawFunctionId, PhaseItem},
3636
render_resource::{CachedRenderPipelineId, Extent3d, TextureFormat, TextureView},
37-
texture::{CachedTexture, ColorAttachment},
37+
texture::ColorAttachment,
3838
};
3939
use bevy_utils::{nonmax::NonMaxU32, FloatOrd};
4040

@@ -78,7 +78,7 @@ pub struct ViewPrepassTextures {
7878
pub deferred: Option<ColorAttachment>,
7979
/// A texture that specifies the deferred lighting pass id for a material.
8080
/// Exists only if [`DeferredPrepass`] is added to the `ViewTarget`
81-
pub deferred_lighting_pass_id: Option<CachedTexture>,
81+
pub deferred_lighting_pass_id: Option<ColorAttachment>,
8282
/// The size of the textures.
8383
pub size: Extent3d,
8484
}

crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
// Creates the deferred gbuffer from a PbrInput.
1919
fn deferred_gbuffer_from_pbr_input(in: PbrInput) -> vec4<u32> {
2020
// Only monochrome occlusion supported. May not be worth including at all.
21-
// Some models have baked occlusion, GLTF only supports monochrome.
21+
// Some models have baked occlusion, GLTF only supports monochrome.
2222
// Real time occlusion is applied in the deferred lighting pass.
2323
// Deriving luminance via Rec. 709. coefficients
2424
// https://en.wikipedia.org/wiki/Rec._709
@@ -27,7 +27,7 @@ fn deferred_gbuffer_from_pbr_input(in: PbrInput) -> vec4<u32> {
2727
var props = deferred_types::pack_unorm3x4_plus_unorm_20_(vec4(
2828
in.material.reflectance,
2929
in.material.metallic,
30-
diffuse_occlusion,
30+
diffuse_occlusion,
3131
in.frag_coord.z));
3232
#else
3333
var props = deferred_types::pack_unorm4x8_(vec4(
@@ -79,7 +79,7 @@ fn pbr_input_from_deferred_gbuffer(frag_coord: vec4<f32>, gbuffer: vec4<u32>) ->
7979
#ifdef WEBGL2 // More crunched for webgl so we can also fit depth.
8080
let props = deferred_types::unpack_unorm3x4_plus_unorm_20_(gbuffer.b);
8181
// Bias to 0.5 since that's the value for almost all materials.
82-
pbr.material.reflectance = saturate(props.r - 0.03333333333);
82+
pbr.material.reflectance = saturate(props.r - 0.03333333333);
8383
#else
8484
let props = deferred_types::unpack_unorm4x8_(gbuffer.b);
8585
pbr.material.reflectance = props.r;
@@ -92,9 +92,9 @@ fn pbr_input_from_deferred_gbuffer(frag_coord: vec4<f32>, gbuffer: vec4<u32>) ->
9292
let world_position = vec4(position_ndc_to_world(frag_coord_to_ndc(frag_coord)), 1.0);
9393
let is_orthographic = view.projection[3].w == 1.0;
9494
let V = pbr_functions::calculate_view(world_position, is_orthographic);
95-
95+
9696
pbr.frag_coord = frag_coord;
97-
pbr.world_normal = N;
97+
pbr.world_normal = N;
9898
pbr.world_position = world_position;
9999
pbr.N = N;
100100
pbr.V = V;

crates/bevy_pbr/src/prepass/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -639,8 +639,8 @@ pub fn prepare_previous_view_projection_uniforms(
639639

640640
#[derive(Default, Resource)]
641641
pub struct PrepassViewBindGroup {
642-
motion_vectors: Option<BindGroup>,
643-
no_motion_vectors: Option<BindGroup>,
642+
pub motion_vectors: Option<BindGroup>,
643+
pub no_motion_vectors: Option<BindGroup>,
644644
}
645645

646646
pub fn prepare_prepass_view_bind_group<M: Material>(

crates/bevy_pbr/src/prepass/prepass.wgsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ fn fragment(in: VertexOutput) -> FragmentOutput {
149149
#ifdef DEFERRED_PREPASS
150150
// There isn't any material info available for this default prepass shader so we are just writing 
151151
// emissive magenta out to the deferred gbuffer to be rendered by the first deferred lighting pass layer.
152-
// The is here so if the default prepass fragment is used for deferred magenta will be rendered, and also
152+
// This is here so if the default prepass fragment is used for deferred magenta will be rendered, and also
153153
// as an example to show that a user could write to the deferred gbuffer if they were to start from this shader.
154154
out.deferred = vec4(0u, bevy_pbr::rgb9e5::vec3_to_rgb9e5_(vec3(1.0, 0.0, 1.0)), 0u, 0u);
155155
out.deferred_lighting_pass_id = 1u;

crates/bevy_pbr/src/render/light.rs

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use bevy_render::{
55
camera::Camera,
66
color::Color,
77
mesh::Mesh,
8+
primitives::{CascadesFrusta, CubemapFrusta, Frustum},
89
render_asset::RenderAssets,
910
render_graph::{Node, NodeRunError, RenderGraphContext},
1011
render_phase::*,
@@ -48,6 +49,7 @@ pub struct ExtractedDirectionalLight {
4849
shadow_normal_bias: f32,
4950
cascade_shadow_config: CascadeShadowConfig,
5051
cascades: EntityHashMap<Entity, Vec<Cascade>>,
52+
frusta: EntityHashMap<Entity, Vec<Frustum>>,
5153
render_layers: RenderLayers,
5254
}
5355

@@ -296,6 +298,7 @@ pub fn extract_lights(
296298
&CubemapVisibleEntities,
297299
&GlobalTransform,
298300
&ViewVisibility,
301+
&CubemapFrusta,
299302
)>,
300303
>,
301304
spot_lights: Extract<
@@ -304,6 +307,7 @@ pub fn extract_lights(
304307
&VisibleEntities,
305308
&GlobalTransform,
306309
&ViewVisibility,
310+
&Frustum,
307311
)>,
308312
>,
309313
directional_lights: Extract<
@@ -314,6 +318,7 @@ pub fn extract_lights(
314318
&CascadesVisibleEntities,
315319
&Cascades,
316320
&CascadeShadowConfig,
321+
&CascadesFrusta,
317322
&GlobalTransform,
318323
&ViewVisibility,
319324
Option<&RenderLayers>,
@@ -343,7 +348,7 @@ pub fn extract_lights(
343348

344349
let mut point_lights_values = Vec::with_capacity(*previous_point_lights_len);
345350
for entity in global_point_lights.iter().copied() {
346-
let Ok((point_light, cubemap_visible_entities, transform, view_visibility)) =
351+
let Ok((point_light, cubemap_visible_entities, transform, view_visibility, frusta)) =
347352
point_lights.get(entity)
348353
else {
349354
continue;
@@ -373,15 +378,19 @@ pub fn extract_lights(
373378
};
374379
point_lights_values.push((
375380
entity,
376-
(extracted_point_light, render_cubemap_visible_entities),
381+
(
382+
extracted_point_light,
383+
render_cubemap_visible_entities,
384+
(*frusta).clone(),
385+
),
377386
));
378387
}
379388
*previous_point_lights_len = point_lights_values.len();
380389
commands.insert_or_spawn_batch(point_lights_values);
381390

382391
let mut spot_lights_values = Vec::with_capacity(*previous_spot_lights_len);
383392
for entity in global_point_lights.iter().copied() {
384-
if let Ok((spot_light, visible_entities, transform, view_visibility)) =
393+
if let Ok((spot_light, visible_entities, transform, view_visibility, frustum)) =
385394
spot_lights.get(entity)
386395
{
387396
if !view_visibility.get() {
@@ -417,6 +426,7 @@ pub fn extract_lights(
417426
spot_light_angles: Some((spot_light.inner_angle, spot_light.outer_angle)),
418427
},
419428
render_visible_entities,
429+
*frustum,
420430
),
421431
));
422432
}
@@ -430,6 +440,7 @@ pub fn extract_lights(
430440
visible_entities,
431441
cascades,
432442
cascade_config,
443+
frusta,
433444
transform,
434445
view_visibility,
435446
maybe_layers,
@@ -452,6 +463,7 @@ pub fn extract_lights(
452463
shadow_normal_bias: directional_light.shadow_normal_bias * std::f32::consts::SQRT_2,
453464
cascade_shadow_config: cascade_config.clone(),
454465
cascades: cascades.cascades.clone(),
466+
frusta: frusta.frusta.clone(),
455467
render_layers: maybe_layers.copied().unwrap_or_default(),
456468
},
457469
render_visible_entities,
@@ -656,7 +668,11 @@ pub fn prepare_lights(
656668
directional_light_shadow_map: Res<DirectionalLightShadowMap>,
657669
mut max_directional_lights_warning_emitted: Local<bool>,
658670
mut max_cascades_per_light_warning_emitted: Local<bool>,
659-
point_lights: Query<(Entity, &ExtractedPointLight)>,
671+
point_lights: Query<(
672+
Entity,
673+
&ExtractedPointLight,
674+
AnyOf<(&CubemapFrusta, &Frustum)>,
675+
)>,
660676
directional_lights: Query<(Entity, &ExtractedDirectionalLight)>,
661677
) {
662678
let views_iter = views.iter();
@@ -733,7 +749,7 @@ pub fn prepare_lights(
733749

734750
let spot_light_shadow_maps_count = point_lights
735751
.iter()
736-
.filter(|(_, light)| light.shadows_enabled && light.spot_light_angles.is_some())
752+
.filter(|(_, light, _)| light.shadows_enabled && light.spot_light_angles.is_some())
737753
.count()
738754
.min(max_texture_array_layers - directional_shadow_enabled_count * MAX_CASCADES_PER_LIGHT);
739755

@@ -742,7 +758,7 @@ pub fn prepare_lights(
742758
// - then those with shadows enabled first, so that the index can be used to render at most `point_light_shadow_maps_count`
743759
// point light shadows and `spot_light_shadow_maps_count` spot light shadow maps,
744760
// - then by entity as a stable key to ensure that a consistent set of lights are chosen if the light count limit is exceeded.
745-
point_lights.sort_by(|(entity_1, light_1), (entity_2, light_2)| {
761+
point_lights.sort_by(|(entity_1, light_1, _), (entity_2, light_2, _)| {
746762
point_light_order(
747763
(
748764
entity_1,
@@ -775,7 +791,7 @@ pub fn prepare_lights(
775791
}
776792

777793
let mut gpu_point_lights = Vec::new();
778-
for (index, &(entity, light)) in point_lights.iter().enumerate() {
794+
for (index, &(entity, light, _)) in point_lights.iter().enumerate() {
779795
let mut flags = PointLightFlags::NONE;
780796

781797
// Lights are sorted, shadow enabled lights are first
@@ -952,11 +968,11 @@ pub fn prepare_lights(
952968
};
953969

954970
// TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query
955-
for &(light_entity, light) in point_lights
971+
for &(light_entity, light, (point_light_frusta, _)) in point_lights
956972
.iter()
957973
// Lights are sorted, shadow enabled lights are first
958974
.take(point_light_shadow_maps_count)
959-
.filter(|(_, light)| light.shadows_enabled)
975+
.filter(|(_, light, _)| light.shadows_enabled)
960976
{
961977
let light_index = *global_light_meta
962978
.entity_to_index
@@ -967,7 +983,11 @@ pub fn prepare_lights(
967983
// and ignore rotation because we want the shadow map projections to align with the axes
968984
let view_translation = GlobalTransform::from_translation(light.transform.translation());
969985

970-
for (face_index, view_rotation) in cube_face_rotations.iter().enumerate() {
986+
for (face_index, (view_rotation, frustum)) in cube_face_rotations
987+
.iter()
988+
.zip(&point_light_frusta.unwrap().frusta)
989+
.enumerate()
990+
{
971991
let depth_texture_view =
972992
point_light_depth_texture
973993
.texture
@@ -1005,6 +1025,7 @@ pub fn prepare_lights(
10051025
hdr: false,
10061026
color_grading: Default::default(),
10071027
},
1028+
*frustum,
10081029
RenderPhase::<Shadow>::default(),
10091030
LightEntity::Point {
10101031
light_entity,
@@ -1017,7 +1038,7 @@ pub fn prepare_lights(
10171038
}
10181039

10191040
// spot lights
1020-
for (light_index, &(light_entity, light)) in point_lights
1041+
for (light_index, &(light_entity, light, (_, spot_light_frustum))) in point_lights
10211042
.iter()
10221043
.skip(point_light_count)
10231044
.take(spot_light_shadow_maps_count)
@@ -1063,6 +1084,7 @@ pub fn prepare_lights(
10631084
hdr: false,
10641085
color_grading: Default::default(),
10651086
},
1087+
*spot_light_frustum.unwrap(),
10661088
RenderPhase::<Shadow>::default(),
10671089
LightEntity::Spot { light_entity },
10681090
))
@@ -1078,12 +1100,20 @@ pub fn prepare_lights(
10781100
.enumerate()
10791101
.take(directional_shadow_enabled_count)
10801102
{
1081-
for (cascade_index, (cascade, bound)) in light
1103+
let cascades = light
10821104
.cascades
10831105
.get(&entity)
10841106
.unwrap()
10851107
.iter()
1086-
.take(MAX_CASCADES_PER_LIGHT)
1108+
.take(MAX_CASCADES_PER_LIGHT);
1109+
let frusta = light
1110+
.frusta
1111+
.get(&entity)
1112+
.unwrap()
1113+
.iter()
1114+
.take(MAX_CASCADES_PER_LIGHT);
1115+
for (cascade_index, ((cascade, frusta), bound)) in cascades
1116+
.zip(frusta)
10871117
.zip(&light.cascade_shadow_config.bounds)
10881118
.enumerate()
10891119
{
@@ -1129,6 +1159,7 @@ pub fn prepare_lights(
11291159
hdr: false,
11301160
color_grading: Default::default(),
11311161
},
1162+
*frusta,
11321163
RenderPhase::<Shadow>::default(),
11331164
LightEntity::Directional {
11341165
light_entity,

crates/bevy_render/src/mesh/mesh/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,13 @@ pub struct InnerMeshVertexBufferLayout {
678678
}
679679

680680
impl InnerMeshVertexBufferLayout {
681+
pub fn new(attribute_ids: Vec<MeshVertexAttributeId>, layout: VertexBufferLayout) -> Self {
682+
Self {
683+
attribute_ids,
684+
layout,
685+
}
686+
}
687+
681688
#[inline]
682689
pub fn contains(&self, attribute_id: impl Into<MeshVertexAttributeId>) -> bool {
683690
self.attribute_ids.contains(&attribute_id.into())

crates/bevy_render/src/primitives/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ impl Frustum {
303303
}
304304
}
305305

306-
#[derive(Component, Debug, Default, Reflect)]
306+
#[derive(Component, Clone, Debug, Default, Reflect)]
307307
#[reflect(Component)]
308308
pub struct CubemapFrusta {
309309
#[reflect(ignore)]

0 commit comments

Comments
 (0)