From f24de4f95449a396d0ee71ac6b7e7492e38c3e6c Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:55:34 -0700 Subject: [PATCH 1/7] Make systems not crash when user removes entities --- crates/bevy_pbr/src/prepass/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 61afa1d0e459c..2e3a97d038a13 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -210,7 +210,7 @@ pub fn update_previous_view_projections( query: Query<(Entity, &Camera, &GlobalTransform), (With, With)>, ) { for (entity, camera, camera_transform) in &query { - commands.entity(entity).insert(PreviousViewProjection { + commands.entity(entity).try_insert(PreviousViewProjection { view_proj: camera.projection_matrix() * camera_transform.compute_matrix().inverse(), }); } @@ -230,7 +230,7 @@ pub fn update_mesh_previous_global_transforms( for (entity, transform) in &meshes { commands .entity(entity) - .insert(PreviousGlobalTransform(transform.affine())); + .try_insert(PreviousGlobalTransform(transform.affine())); } } } From 51cdcf8e34ae9a5bca6ec0fc5d9db6951ae96be2 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:55:44 -0700 Subject: [PATCH 2/7] Make more TAA stuff public --- crates/bevy_core_pipeline/src/lib.rs | 5 +- crates/bevy_core_pipeline/src/taa/mod.rs | 144 ++++++++++++----------- 2 files changed, 78 insertions(+), 71 deletions(-) diff --git a/crates/bevy_core_pipeline/src/lib.rs b/crates/bevy_core_pipeline/src/lib.rs index 3c64535d4fe68..ec119ad5ae551 100644 --- a/crates/bevy_core_pipeline/src/lib.rs +++ b/crates/bevy_core_pipeline/src/lib.rs @@ -21,7 +21,10 @@ pub use skybox::Skybox; /// Experimental features that are not yet finished. Please report any issues you encounter! pub mod experimental { pub mod taa { - pub use crate::taa::*; + pub use crate::taa::{ + TemporalAntiAliasBundle, TemporalAntiAliasNode, TemporalAntiAliasPlugin, + TemporalAntiAliasSettings, + }; } } diff --git a/crates/bevy_core_pipeline/src/taa/mod.rs b/crates/bevy_core_pipeline/src/taa/mod.rs index e61dccc5d4bf5..c2948f671c623 100644 --- a/crates/bevy_core_pipeline/src/taa/mod.rs +++ b/crates/bevy_core_pipeline/src/taa/mod.rs @@ -35,7 +35,7 @@ use bevy_render::{ ExtractSchedule, MainWorld, Render, RenderApp, RenderSet, }; -mod draw_3d_graph { +pub mod draw_3d_graph { pub mod node { /// Label for the TAA render node. pub const TAA: &str = "taa"; @@ -61,7 +61,7 @@ impl Plugin for TemporalAntiAliasPlugin { }; render_app - .init_resource::>() + .init_resource::>() .add_systems(ExtractSchedule, extract_taa_settings) .add_systems( Render, @@ -71,7 +71,10 @@ impl Plugin for TemporalAntiAliasPlugin { prepare_taa_history_textures.in_set(RenderSet::PrepareResources), ), ) - .add_render_graph_node::>(CORE_3D, draw_3d_graph::node::TAA) + .add_render_graph_node::>( + CORE_3D, + draw_3d_graph::node::TAA, + ) .add_render_graph_edges( CORE_3D, &[ @@ -88,7 +91,7 @@ impl Plugin for TemporalAntiAliasPlugin { return; }; - render_app.init_resource::(); + render_app.init_resource::(); } } @@ -110,14 +113,13 @@ pub struct TemporalAntiAliasBundle { /// # Tradeoffs /// /// Pros: +/// * Filters more types of aliasing than MSAA, such as textures and singular bright pixels (specular aliasing) /// * Cost scales with screen/view resolution, unlike MSAA which scales with number of triangles -/// * Filters more types of aliasing than MSAA, such as textures and singular bright pixels -/// * Greatly increases the quality of stochastic rendering techniques such as SSAO, shadow mapping, etc +/// * Greatly increases the quality of stochastic rendering techniques such as SSAO, certain shadow map sampling methods, etc /// /// Cons: /// * Chance of "ghosting" - ghostly trails left behind moving objects -/// * Thin geometry, lighting detail, or texture lines may flicker or disappear -/// * Slightly blurs the image, leading to a softer look (using an additional sharpening pass can reduce this) +/// * Thin geometry, lighting detail, or texture lines may flicker noisily or disappear /// /// Because TAA blends past frames with the current frame, when the frames differ too much /// (such as with fast moving objects or camera cuts), ghosting artifacts may occur. @@ -130,7 +132,7 @@ pub struct TemporalAntiAliasBundle { /// and add the [`DepthPrepass`], [`MotionVectorPrepass`], and [`TemporalJitter`] /// components to your camera. /// -/// Cannot be used with [`bevy_render::camera::OrthographicProjection`]. +/// [Currently](https://github.com/bevyengine/bevy/issues/8423) cannot be used with [`bevy_render::camera::OrthographicProjection`]. /// /// Currently does not support skinned meshes and morph targets. /// There will probably be ghosting artifacts if used with them. @@ -151,7 +153,7 @@ pub struct TemporalAntiAliasSettings { /// representative of the current frame, such as in sudden camera cuts. /// /// After setting this to true, it will automatically be toggled - /// back to false after one frame. + /// back to false at the end of the frame. pub reset: bool, } @@ -161,16 +163,17 @@ impl Default for TemporalAntiAliasSettings { } } +/// Render [bevy_render::render_graph::Node] used by temporal anti-aliasing. #[derive(Default)] -struct TAANode; +pub struct TemporalAntiAliasNode; -impl ViewNode for TAANode { +impl ViewNode for TemporalAntiAliasNode { type ViewQuery = ( &'static ExtractedCamera, &'static ViewTarget, - &'static TAAHistoryTextures, + &'static TemporalAntiAliasHistoryTextures, &'static ViewPrepassTextures, - &'static TAAPipelineId, + &'static TemporalAntiAliasPipelineId, ); fn run( @@ -183,59 +186,58 @@ impl ViewNode for TAANode { world: &World, ) -> Result<(), NodeRunError> { let (Some(pipelines), Some(pipeline_cache)) = ( - world.get_resource::(), + world.get_resource::(), world.get_resource::(), ) else { return Ok(()); }; - let (Some(taa_pipeline), Some(prepass_motion_vectors_texture), Some(prepass_depth_texture)) = ( + let ( + Some(taa_pipeline), + Some(prepass_motion_vectors_texture), + Some(prepass_depth_texture), + ) = ( pipeline_cache.get_render_pipeline(taa_pipeline_id.0), &prepass_textures.motion_vectors, &prepass_textures.depth, - ) else { + ) + else { return Ok(()); }; let view_target = view_target.post_process_write(); - let taa_bind_group = - render_context - .render_device() - .create_bind_group(&BindGroupDescriptor { - label: Some("taa_bind_group"), - layout: &pipelines.taa_bind_group_layout, - entries: &[ - BindGroupEntry { - binding: 0, - resource: BindingResource::TextureView(view_target.source), - }, - BindGroupEntry { - binding: 1, - resource: BindingResource::TextureView( - &taa_history_textures.read.default_view, - ), - }, - BindGroupEntry { - binding: 2, - resource: BindingResource::TextureView( - &prepass_motion_vectors_texture.default_view, - ), - }, - BindGroupEntry { - binding: 3, - resource: BindingResource::TextureView( - &prepass_depth_texture.default_view, - ), - }, - BindGroupEntry { - binding: 4, - resource: BindingResource::Sampler(&pipelines.nearest_sampler), - }, - BindGroupEntry { - binding: 5, - resource: BindingResource::Sampler(&pipelines.linear_sampler), - }, - ], - }); + let render_device = render_context.render_device(); + let taa_bind_group = render_device.create_bind_group(&BindGroupDescriptor { + label: Some("taa_bind_group"), + layout: &pipelines.taa_bind_group_layout, + entries: &[ + BindGroupEntry { + binding: 0, + resource: BindingResource::TextureView(view_target.source), + }, + BindGroupEntry { + binding: 1, + resource: BindingResource::TextureView(&taa_history_textures.read.default_view), + }, + BindGroupEntry { + binding: 2, + resource: BindingResource::TextureView( + &prepass_motion_vectors_texture.default_view, + ), + }, + BindGroupEntry { + binding: 3, + resource: BindingResource::TextureView(&prepass_depth_texture.default_view), + }, + BindGroupEntry { + binding: 4, + resource: BindingResource::Sampler(&pipelines.nearest_sampler), + }, + BindGroupEntry { + binding: 5, + resource: BindingResource::Sampler(&pipelines.linear_sampler), + }, + ], + }); { let mut taa_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor { @@ -267,13 +269,13 @@ impl ViewNode for TAANode { } #[derive(Resource)] -struct TAAPipeline { +struct TaaPipeline { taa_bind_group_layout: BindGroupLayout, nearest_sampler: Sampler, linear_sampler: Sampler, } -impl FromWorld for TAAPipeline { +impl FromWorld for TaaPipeline { fn from_world(world: &mut World) -> Self { let render_device = world.resource::(); @@ -355,7 +357,7 @@ impl FromWorld for TAAPipeline { ], }); - TAAPipeline { + TaaPipeline { taa_bind_group_layout, nearest_sampler, linear_sampler, @@ -364,13 +366,13 @@ impl FromWorld for TAAPipeline { } #[derive(PartialEq, Eq, Hash, Clone)] -struct TAAPipelineKey { +struct TaaPipelineKey { hdr: bool, reset: bool, } -impl SpecializedRenderPipeline for TAAPipeline { - type Key = TAAPipelineKey; +impl SpecializedRenderPipeline for TaaPipeline { + type Key = TaaPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { let mut shader_defs = vec![]; @@ -467,7 +469,7 @@ fn prepare_taa_jitter_and_mip_bias( } #[derive(Component)] -struct TAAHistoryTextures { +pub struct TemporalAntiAliasHistoryTextures { write: CachedTexture, read: CachedTexture, } @@ -507,12 +509,12 @@ fn prepare_taa_history_textures( let history_2_texture = texture_cache.get(&render_device, texture_descriptor); let textures = if frame_count.0 % 2 == 0 { - TAAHistoryTextures { + TemporalAntiAliasHistoryTextures { write: history_1_texture, read: history_2_texture, } } else { - TAAHistoryTextures { + TemporalAntiAliasHistoryTextures { write: history_2_texture, read: history_1_texture, } @@ -524,17 +526,17 @@ fn prepare_taa_history_textures( } #[derive(Component)] -struct TAAPipelineId(CachedRenderPipelineId); +pub struct TemporalAntiAliasPipelineId(CachedRenderPipelineId); fn prepare_taa_pipelines( mut commands: Commands, pipeline_cache: Res, - mut pipelines: ResMut>, - pipeline: Res, + mut pipelines: ResMut>, + pipeline: Res, views: Query<(Entity, &ExtractedView, &TemporalAntiAliasSettings)>, ) { for (entity, view, taa_settings) in &views { - let mut pipeline_key = TAAPipelineKey { + let mut pipeline_key = TaaPipelineKey { hdr: view.hdr, reset: taa_settings.reset, }; @@ -546,6 +548,8 @@ fn prepare_taa_pipelines( pipelines.specialize(&pipeline_cache, &pipeline, pipeline_key); } - commands.entity(entity).insert(TAAPipelineId(pipeline_id)); + commands + .entity(entity) + .insert(TemporalAntiAliasPipelineId(pipeline_id)); } } From fecb9ccdf12aad7966990ad2067bf72006a965cf Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 19 Oct 2023 21:56:20 -0700 Subject: [PATCH 3/7] Reject history when motion vectors point off screen --- crates/bevy_core_pipeline/src/taa/taa.wgsl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/bevy_core_pipeline/src/taa/taa.wgsl b/crates/bevy_core_pipeline/src/taa/taa.wgsl index 53be6b02f0ecf..f67f7fa032a3d 100644 --- a/crates/bevy_core_pipeline/src/taa/taa.wgsl +++ b/crates/bevy_core_pipeline/src/taa/taa.wgsl @@ -173,6 +173,9 @@ fn taa(@location(0) uv: vec2) -> Output { // Else reset history_confidence = 1.0; } + // Reject history when motion vectors point off screen + history_confidence *= f32(all(saturate(history_uv) == history_uv)); + history_confidence = min(1.0, history_confidence); // Blend current and past sample // Use more of the history if we're confident in it (reduces noise when there is no motion) From 1e0a4a490d0767604ba43d9be873a9bc89b13095 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:51:21 -0700 Subject: [PATCH 4/7] Reject history when off-screen correctly --- crates/bevy_core_pipeline/src/taa/taa.wgsl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/bevy_core_pipeline/src/taa/taa.wgsl b/crates/bevy_core_pipeline/src/taa/taa.wgsl index f67f7fa032a3d..09f0ddd50a1ba 100644 --- a/crates/bevy_core_pipeline/src/taa/taa.wgsl +++ b/crates/bevy_core_pipeline/src/taa/taa.wgsl @@ -173,14 +173,18 @@ fn taa(@location(0) uv: vec2) -> Output { // Else reset history_confidence = 1.0; } - // Reject history when motion vectors point off screen - history_confidence *= f32(all(saturate(history_uv) == history_uv)); - history_confidence = min(1.0, history_confidence); // Blend current and past sample // Use more of the history if we're confident in it (reduces noise when there is no motion) // https://hhoppe.com/supersample.pdf, section 4.1 - let current_color_factor = clamp(1.0 / history_confidence, MIN_HISTORY_BLEND_RATE, DEFAULT_HISTORY_BLEND_RATE); + var current_color_factor = clamp(1.0 / history_confidence, MIN_HISTORY_BLEND_RATE, DEFAULT_HISTORY_BLEND_RATE); + + // Reject history when motion vectors point off screen + if any(saturate(history_uv) != history_uv) { + current_color_factor = 1.0; + history_confidence = 1.0; + } + current_color = mix(history_color, current_color, current_color_factor); #endif // #ifndef RESET From 60ab328b86d58defc3313bdfa19c06a67a7e2945 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:55:21 -0700 Subject: [PATCH 5/7] Fmt --- crates/bevy_core_pipeline/src/taa/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_core_pipeline/src/taa/mod.rs b/crates/bevy_core_pipeline/src/taa/mod.rs index d748e6abbe9f5..a9f2429dabf3d 100644 --- a/crates/bevy_core_pipeline/src/taa/mod.rs +++ b/crates/bevy_core_pipeline/src/taa/mod.rs @@ -199,8 +199,7 @@ impl ViewNode for TemporalAntiAliasNode { pipeline_cache.get_render_pipeline(taa_pipeline_id.0), &prepass_textures.motion_vectors, &prepass_textures.depth, - ) - else { + ) else { return Ok(()); }; let view_target = view_target.post_process_write(); From 9ef3aeb4528eefb216ab7ad51e8c23bbb515f508 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Tue, 24 Oct 2023 17:32:21 -0700 Subject: [PATCH 6/7] Appease clippy --- crates/bevy_core_pipeline/src/taa/mod.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/bevy_core_pipeline/src/taa/mod.rs b/crates/bevy_core_pipeline/src/taa/mod.rs index a9f2429dabf3d..01efe2ebfd96f 100644 --- a/crates/bevy_core_pipeline/src/taa/mod.rs +++ b/crates/bevy_core_pipeline/src/taa/mod.rs @@ -191,11 +191,7 @@ impl ViewNode for TemporalAntiAliasNode { ) else { return Ok(()); }; - let ( - Some(taa_pipeline), - Some(prepass_motion_vectors_texture), - Some(prepass_depth_texture), - ) = ( + let (Some(taa_pipeline), Some(prepass_motion_vectors_texture), Some(prepass_depth_texture)) = ( pipeline_cache.get_render_pipeline(taa_pipeline_id.0), &prepass_textures.motion_vectors, &prepass_textures.depth, From 7decb02874a1410d9b98cdcef2264c1a481f7ec1 Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Thu, 26 Oct 2023 22:56:23 -0700 Subject: [PATCH 7/7] Fix doc comment --- crates/bevy_core_pipeline/src/taa/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_core_pipeline/src/taa/mod.rs b/crates/bevy_core_pipeline/src/taa/mod.rs index 01efe2ebfd96f..de4069c9abe7d 100644 --- a/crates/bevy_core_pipeline/src/taa/mod.rs +++ b/crates/bevy_core_pipeline/src/taa/mod.rs @@ -163,7 +163,7 @@ impl Default for TemporalAntiAliasSettings { } } -/// Render [bevy_render::render_graph::Node] used by temporal anti-aliasing. +/// Render [`bevy_render::render_graph::Node`] used by temporal anti-aliasing. #[derive(Default)] pub struct TemporalAntiAliasNode;