From fe90db9544cc1307b479e413cbd86e7226e866ca Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 20 Jan 2024 12:25:25 -0800 Subject: [PATCH 1/2] Meshlet prep --- crates/bevy_core_pipeline/src/core_3d/mod.rs | 5 +- .../src/deferred/copy_lighting_id.rs | 2 +- .../bevy_core_pipeline/src/deferred/node.rs | 18 ++---- crates/bevy_core_pipeline/src/prepass/mod.rs | 4 +- .../src/deferred/pbr_deferred_functions.wgsl | 10 ++-- crates/bevy_pbr/src/prepass/mod.rs | 4 +- crates/bevy_pbr/src/prepass/prepass.wgsl | 2 +- crates/bevy_pbr/src/render/light.rs | 57 ++++++++++++++----- crates/bevy_render/src/mesh/mesh/mod.rs | 7 +++ crates/bevy_render/src/primitives/mod.rs | 2 +- crates/bevy_render/src/render_resource/mod.rs | 2 +- crates/bevy_render/src/view/mod.rs | 2 +- 12 files changed, 73 insertions(+), 42 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 5d6e72e88953e..5d8f067bf3c0e 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -805,7 +805,7 @@ pub fn prepare_prepass_textures( .clone() }); - let deferred_lighting_pass_id_texture = deferred_prepass.then(|| { + let cached_deferred_lighting_pass_id_texture = deferred_prepass.then(|| { deferred_lighting_id_textures .entry(camera.target.clone()) .or_insert_with(|| { @@ -836,7 +836,8 @@ pub fn prepare_prepass_textures( motion_vectors: cached_motion_vectors_texture .map(|t| ColorAttachment::new(t, None, Color::BLACK)), deferred: cached_deferred_texture.map(|t| ColorAttachment::new(t, None, Color::BLACK)), - deferred_lighting_pass_id: deferred_lighting_pass_id_texture, + deferred_lighting_pass_id: cached_deferred_lighting_pass_id_texture + .map(|t| ColorAttachment::new(t, None, Color::BLACK)), size, }); } diff --git a/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs b/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs index 71670b40b3cbd..aaf8d079dbec0 100644 --- a/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs +++ b/crates/bevy_core_pipeline/src/deferred/copy_lighting_id.rs @@ -94,7 +94,7 @@ impl ViewNode for CopyDeferredLightingIdNode { let bind_group = render_context.render_device().create_bind_group( "copy_deferred_lighting_id_bind_group", ©_deferred_lighting_id_pipeline.layout, - &BindGroupEntries::single(&deferred_lighting_pass_id_texture.default_view), + &BindGroupEntries::single(&deferred_lighting_pass_id_texture.texture.default_view), ); let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index 8fac4d77fb32f..0df8875e0a3bb 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -5,10 +5,9 @@ use bevy_render::render_graph::ViewNode; use bevy_render::render_resource::StoreOp; use bevy_render::{ camera::ExtractedCamera, - prelude::Color, render_graph::{NodeRunError, RenderGraphContext}, render_phase::RenderPhase, - render_resource::{LoadOp, Operations, RenderPassColorAttachment, RenderPassDescriptor}, + render_resource::RenderPassDescriptor, renderer::RenderContext, view::ViewDepthTexture, }; @@ -83,11 +82,11 @@ impl ViewNode for DeferredGBufferPrepassNode { .map(|deferred_texture| { #[cfg(all(feature = "webgl", target_arch = "wasm32"))] { - RenderPassColorAttachment { + bevy_render::render_resource::RenderPassColorAttachment { view: &deferred_texture.texture.default_view, resolve_target: None, - ops: Operations { - load: LoadOp::Load, + ops: bevy_render::render_resource::Operations { + load: bevy_render::render_resource::LoadOp::Load, store: StoreOp::Store, }, } @@ -101,14 +100,7 @@ impl ViewNode for DeferredGBufferPrepassNode { view_prepass_textures .deferred_lighting_pass_id .as_ref() - .map(|deferred_lighting_pass_id| RenderPassColorAttachment { - view: &deferred_lighting_pass_id.default_view, - resolve_target: None, - ops: Operations { - load: LoadOp::Clear(Color::BLACK.into()), - store: StoreOp::Store, - }, - }), + .map(|deferred_lighting_pass_id| deferred_lighting_pass_id.get_attachment()), ); if color_attachments.iter().all(Option::is_none) { diff --git a/crates/bevy_core_pipeline/src/prepass/mod.rs b/crates/bevy_core_pipeline/src/prepass/mod.rs index 5006c2a3055c9..c8d38db50f9fd 100644 --- a/crates/bevy_core_pipeline/src/prepass/mod.rs +++ b/crates/bevy_core_pipeline/src/prepass/mod.rs @@ -34,7 +34,7 @@ use bevy_reflect::Reflect; use bevy_render::{ render_phase::{CachedRenderPipelinePhaseItem, DrawFunctionId, PhaseItem}, render_resource::{CachedRenderPipelineId, Extent3d, TextureFormat, TextureView}, - texture::{CachedTexture, ColorAttachment}, + texture::ColorAttachment, }; use bevy_utils::{nonmax::NonMaxU32, FloatOrd}; @@ -78,7 +78,7 @@ pub struct ViewPrepassTextures { pub deferred: Option, /// A texture that specifies the deferred lighting pass id for a material. /// Exists only if [`DeferredPrepass`] is added to the `ViewTarget` - pub deferred_lighting_pass_id: Option, + pub deferred_lighting_pass_id: Option, /// The size of the textures. pub size: Extent3d, } diff --git a/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl b/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl index 7c2696f6c48dc..495ee6b7340d6 100644 --- a/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl +++ b/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl @@ -18,7 +18,7 @@ // Creates the deferred gbuffer from a PbrInput. fn deferred_gbuffer_from_pbr_input(in: PbrInput) -> vec4 { // Only monochrome occlusion supported. May not be worth including at all. - // Some models have baked occlusion, GLTF only supports monochrome. + // Some models have baked occlusion, GLTF only supports monochrome. // Real time occlusion is applied in the deferred lighting pass. // Deriving luminance via Rec. 709. coefficients // https://en.wikipedia.org/wiki/Rec._709 @@ -27,7 +27,7 @@ fn deferred_gbuffer_from_pbr_input(in: PbrInput) -> vec4 { var props = deferred_types::pack_unorm3x4_plus_unorm_20_(vec4( in.material.reflectance, in.material.metallic, - diffuse_occlusion, + diffuse_occlusion, in.frag_coord.z)); #else var props = deferred_types::pack_unorm4x8_(vec4( @@ -79,7 +79,7 @@ fn pbr_input_from_deferred_gbuffer(frag_coord: vec4, gbuffer: vec4) -> #ifdef WEBGL2 // More crunched for webgl so we can also fit depth. let props = deferred_types::unpack_unorm3x4_plus_unorm_20_(gbuffer.b); // Bias to 0.5 since that's the value for almost all materials. - pbr.material.reflectance = saturate(props.r - 0.03333333333); + pbr.material.reflectance = saturate(props.r - 0.03333333333); #else let props = deferred_types::unpack_unorm4x8_(gbuffer.b); pbr.material.reflectance = props.r; @@ -92,9 +92,9 @@ fn pbr_input_from_deferred_gbuffer(frag_coord: vec4, gbuffer: vec4) -> let world_position = vec4(position_ndc_to_world(frag_coord_to_ndc(frag_coord)), 1.0); let is_orthographic = view.projection[3].w == 1.0; let V = pbr_functions::calculate_view(world_position, is_orthographic); - + pbr.frag_coord = frag_coord; - pbr.world_normal = N; + pbr.world_normal = N; pbr.world_position = world_position; pbr.N = N; pbr.V = V; diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 6b05982f8942e..e2c9b553861f6 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -639,8 +639,8 @@ pub fn prepare_previous_view_projection_uniforms( #[derive(Default, Resource)] pub struct PrepassViewBindGroup { - motion_vectors: Option, - no_motion_vectors: Option, + pub motion_vectors: Option, + pub no_motion_vectors: Option, } pub fn prepare_prepass_view_bind_group( diff --git a/crates/bevy_pbr/src/prepass/prepass.wgsl b/crates/bevy_pbr/src/prepass/prepass.wgsl index 98795db5ac630..df0ff24f2c3d9 100644 --- a/crates/bevy_pbr/src/prepass/prepass.wgsl +++ b/crates/bevy_pbr/src/prepass/prepass.wgsl @@ -149,7 +149,7 @@ fn fragment(in: VertexOutput) -> FragmentOutput { #ifdef DEFERRED_PREPASS // There isn't any material info available for this default prepass shader so we are just writing  // emissive magenta out to the deferred gbuffer to be rendered by the first deferred lighting pass layer. - // The is here so if the default prepass fragment is used for deferred magenta will be rendered, and also + // This is here so if the default prepass fragment is used for deferred magenta will be rendered, and also // as an example to show that a user could write to the deferred gbuffer if they were to start from this shader. out.deferred = vec4(0u, bevy_pbr::rgb9e5::vec3_to_rgb9e5_(vec3(1.0, 0.0, 1.0)), 0u, 0u); out.deferred_lighting_pass_id = 1u; diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 3be78ffd452e3..0fdbb8066531a 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -5,6 +5,7 @@ use bevy_render::{ camera::Camera, color::Color, mesh::Mesh, + primitives::{CascadesFrusta, CubemapFrusta, Frustum}, render_asset::RenderAssets, render_graph::{Node, NodeRunError, RenderGraphContext}, render_phase::*, @@ -48,6 +49,7 @@ pub struct ExtractedDirectionalLight { shadow_normal_bias: f32, cascade_shadow_config: CascadeShadowConfig, cascades: EntityHashMap>, + frusta: EntityHashMap>, render_layers: RenderLayers, } @@ -296,6 +298,7 @@ pub fn extract_lights( &CubemapVisibleEntities, &GlobalTransform, &ViewVisibility, + &CubemapFrusta, )>, >, spot_lights: Extract< @@ -304,6 +307,7 @@ pub fn extract_lights( &VisibleEntities, &GlobalTransform, &ViewVisibility, + &Frustum, )>, >, directional_lights: Extract< @@ -314,6 +318,7 @@ pub fn extract_lights( &CascadesVisibleEntities, &Cascades, &CascadeShadowConfig, + &CascadesFrusta, &GlobalTransform, &ViewVisibility, Option<&RenderLayers>, @@ -343,7 +348,7 @@ pub fn extract_lights( let mut point_lights_values = Vec::with_capacity(*previous_point_lights_len); for entity in global_point_lights.iter().copied() { - let Ok((point_light, cubemap_visible_entities, transform, view_visibility)) = + let Ok((point_light, cubemap_visible_entities, transform, view_visibility, frusta)) = point_lights.get(entity) else { continue; @@ -373,7 +378,11 @@ pub fn extract_lights( }; point_lights_values.push(( entity, - (extracted_point_light, render_cubemap_visible_entities), + ( + extracted_point_light, + render_cubemap_visible_entities, + (*frusta).clone(), + ), )); } *previous_point_lights_len = point_lights_values.len(); @@ -381,7 +390,7 @@ pub fn extract_lights( let mut spot_lights_values = Vec::with_capacity(*previous_spot_lights_len); for entity in global_point_lights.iter().copied() { - if let Ok((spot_light, visible_entities, transform, view_visibility)) = + if let Ok((spot_light, visible_entities, transform, view_visibility, frustum)) = spot_lights.get(entity) { if !view_visibility.get() { @@ -417,6 +426,7 @@ pub fn extract_lights( spot_light_angles: Some((spot_light.inner_angle, spot_light.outer_angle)), }, render_visible_entities, + *frustum, ), )); } @@ -430,6 +440,7 @@ pub fn extract_lights( visible_entities, cascades, cascade_config, + frusta, transform, view_visibility, maybe_layers, @@ -452,6 +463,7 @@ pub fn extract_lights( shadow_normal_bias: directional_light.shadow_normal_bias * std::f32::consts::SQRT_2, cascade_shadow_config: cascade_config.clone(), cascades: cascades.cascades.clone(), + frusta: frusta.frusta.clone(), render_layers: maybe_layers.copied().unwrap_or_default(), }, render_visible_entities, @@ -656,7 +668,11 @@ pub fn prepare_lights( directional_light_shadow_map: Res, mut max_directional_lights_warning_emitted: Local, mut max_cascades_per_light_warning_emitted: Local, - point_lights: Query<(Entity, &ExtractedPointLight)>, + point_lights: Query<( + Entity, + &ExtractedPointLight, + AnyOf<(&CubemapFrusta, &Frustum)>, + )>, directional_lights: Query<(Entity, &ExtractedDirectionalLight)>, ) { let views_iter = views.iter(); @@ -733,7 +749,7 @@ pub fn prepare_lights( let spot_light_shadow_maps_count = point_lights .iter() - .filter(|(_, light)| light.shadows_enabled && light.spot_light_angles.is_some()) + .filter(|(_, light, _)| light.shadows_enabled && light.spot_light_angles.is_some()) .count() .min(max_texture_array_layers - directional_shadow_enabled_count * MAX_CASCADES_PER_LIGHT); @@ -742,7 +758,7 @@ pub fn prepare_lights( // - then those with shadows enabled first, so that the index can be used to render at most `point_light_shadow_maps_count` // point light shadows and `spot_light_shadow_maps_count` spot light shadow maps, // - then by entity as a stable key to ensure that a consistent set of lights are chosen if the light count limit is exceeded. - point_lights.sort_by(|(entity_1, light_1), (entity_2, light_2)| { + point_lights.sort_by(|(entity_1, light_1, _), (entity_2, light_2, _)| { point_light_order( ( entity_1, @@ -775,7 +791,7 @@ pub fn prepare_lights( } let mut gpu_point_lights = Vec::new(); - for (index, &(entity, light)) in point_lights.iter().enumerate() { + for (index, &(entity, light, _)) in point_lights.iter().enumerate() { let mut flags = PointLightFlags::NONE; // Lights are sorted, shadow enabled lights are first @@ -952,11 +968,11 @@ pub fn prepare_lights( }; // TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query - for &(light_entity, light) in point_lights + for &(light_entity, light, (point_light_frusta, _)) in point_lights .iter() // Lights are sorted, shadow enabled lights are first .take(point_light_shadow_maps_count) - .filter(|(_, light)| light.shadows_enabled) + .filter(|(_, light, _)| light.shadows_enabled) { let light_index = *global_light_meta .entity_to_index @@ -967,7 +983,11 @@ pub fn prepare_lights( // and ignore rotation because we want the shadow map projections to align with the axes let view_translation = GlobalTransform::from_translation(light.transform.translation()); - for (face_index, view_rotation) in cube_face_rotations.iter().enumerate() { + for (face_index, (view_rotation, frustum)) in cube_face_rotations + .iter() + .zip(&point_light_frusta.unwrap().frusta) + .enumerate() + { let depth_texture_view = point_light_depth_texture .texture @@ -1005,6 +1025,7 @@ pub fn prepare_lights( hdr: false, color_grading: Default::default(), }, + *frustum, RenderPhase::::default(), LightEntity::Point { light_entity, @@ -1017,7 +1038,7 @@ pub fn prepare_lights( } // spot lights - for (light_index, &(light_entity, light)) in point_lights + for (light_index, &(light_entity, light, (_, spot_light_frustum))) in point_lights .iter() .skip(point_light_count) .take(spot_light_shadow_maps_count) @@ -1063,6 +1084,7 @@ pub fn prepare_lights( hdr: false, color_grading: Default::default(), }, + *spot_light_frustum.unwrap(), RenderPhase::::default(), LightEntity::Spot { light_entity }, )) @@ -1078,12 +1100,20 @@ pub fn prepare_lights( .enumerate() .take(directional_shadow_enabled_count) { - for (cascade_index, (cascade, bound)) in light + let cascades = light .cascades .get(&entity) .unwrap() .iter() - .take(MAX_CASCADES_PER_LIGHT) + .take(MAX_CASCADES_PER_LIGHT); + let frusta = light + .frusta + .get(&entity) + .unwrap() + .iter() + .take(MAX_CASCADES_PER_LIGHT); + for (cascade_index, ((cascade, frusta), bound)) in cascades + .zip(frusta) .zip(&light.cascade_shadow_config.bounds) .enumerate() { @@ -1129,6 +1159,7 @@ pub fn prepare_lights( hdr: false, color_grading: Default::default(), }, + *frusta, RenderPhase::::default(), LightEntity::Directional { light_entity, diff --git a/crates/bevy_render/src/mesh/mesh/mod.rs b/crates/bevy_render/src/mesh/mesh/mod.rs index 270fd86cb1705..d7fa777a9f604 100644 --- a/crates/bevy_render/src/mesh/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mesh/mod.rs @@ -678,6 +678,13 @@ pub struct InnerMeshVertexBufferLayout { } impl InnerMeshVertexBufferLayout { + pub fn new(attribute_ids: Vec, layout: VertexBufferLayout) -> Self { + Self { + attribute_ids, + layout, + } + } + #[inline] pub fn contains(&self, attribute_id: impl Into) -> bool { self.attribute_ids.contains(&attribute_id.into()) diff --git a/crates/bevy_render/src/primitives/mod.rs b/crates/bevy_render/src/primitives/mod.rs index 0e4dfd7dd961b..b06511a9ba138 100644 --- a/crates/bevy_render/src/primitives/mod.rs +++ b/crates/bevy_render/src/primitives/mod.rs @@ -303,7 +303,7 @@ impl Frustum { } } -#[derive(Component, Debug, Default, Reflect)] +#[derive(Component, Clone, Debug, Default, Reflect)] #[reflect(Component)] pub struct CubemapFrusta { #[reflect(ignore)] diff --git a/crates/bevy_render/src/render_resource/mod.rs b/crates/bevy_render/src/render_resource/mod.rs index eaeacf5b23608..18558dcef867f 100644 --- a/crates/bevy_render/src/render_resource/mod.rs +++ b/crates/bevy_render/src/render_resource/mod.rs @@ -32,7 +32,7 @@ pub use uniform_buffer::*; // TODO: decide where re-exports should go pub use wgpu::{ - util::{BufferInitDescriptor, DrawIndexedIndirect}, + util::{BufferInitDescriptor, DrawIndexedIndirect, DrawIndirect}, AdapterInfo as WgpuAdapterInfo, AddressMode, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress, BufferAsyncError, BufferBinding, diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index acaa1818b27d0..729d21e4a4305 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -457,7 +457,7 @@ struct MainTargetTextures { } #[allow(clippy::too_many_arguments)] -fn prepare_view_targets( +pub fn prepare_view_targets( mut commands: Commands, windows: Res, images: Res>, From dd056c7b688fa595a2c8d24b279ec48dc9627313 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sat, 20 Jan 2024 23:56:43 -0800 Subject: [PATCH 2/2] Fix example imports --- examples/3d/spotlight.rs | 1 - examples/3d/update_gltf_scene.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/3d/spotlight.rs b/examples/3d/spotlight.rs index 862068977915e..533dc9dd2b817 100644 --- a/examples/3d/spotlight.rs +++ b/examples/3d/spotlight.rs @@ -17,7 +17,6 @@ fn main() { DefaultPlugins, FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin::default(), - bevy_internal::core_pipeline::experimental::taa::TemporalAntiAliasPlugin, )) .add_systems(Startup, setup) .add_systems(Update, (light_sway, movement)) diff --git a/examples/3d/update_gltf_scene.rs b/examples/3d/update_gltf_scene.rs index 84578cbefa4af..d885126f630a4 100644 --- a/examples/3d/update_gltf_scene.rs +++ b/examples/3d/update_gltf_scene.rs @@ -1,11 +1,11 @@ //! Update a scene from a glTF file, either by spawning the scene as a child of another entity, //! or by accessing the entities of the scene. -use bevy::prelude::*; +use bevy::{pbr::DirectionalLightShadowMap, prelude::*}; fn main() { App::new() - .insert_resource(bevy_internal::pbr::DirectionalLightShadowMap { size: 4096 }) + .insert_resource(DirectionalLightShadowMap { size: 4096 }) .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .add_systems(Update, move_scene_entities)