From 31b5943ad48e2735fc78832b7465f0e619b6f9df Mon Sep 17 00:00:00 2001 From: JMS55 <47158642+JMS55@users.noreply.github.com> Date: Sun, 7 Apr 2024 14:59:16 -0400 Subject: [PATCH] Add previous_view_uniforms.inverse_view (#12902) # Objective - Upload previous frame's inverse_view matrix to the GPU for use with https://github.com/bevyengine/bevy/pull/12898. --- ## Changelog - Added `prepass_bindings::previous_view_uniforms.inverse_view`. - Renamed `prepass_bindings::previous_view_proj` to `prepass_bindings::previous_view_uniforms.view_proj`. - Renamed `PreviousViewProjectionUniformOffset` to `PreviousViewUniformOffset`. - Renamed `PreviousViewProjection` to `PreviousViewData`. ## Migration Guide - Renamed `prepass_bindings::previous_view_proj` to `prepass_bindings::previous_view_uniforms.view_proj`. - Renamed `PreviousViewProjectionUniformOffset` to `PreviousViewUniformOffset`. - Renamed `PreviousViewProjection` to `PreviousViewData`. --- .../src/meshlet/material_draw_nodes.rs | 24 +++--- .../meshlet/visibility_buffer_resolve.wgsl | 8 +- crates/bevy_pbr/src/prepass/mod.rs | 84 ++++++++++--------- crates/bevy_pbr/src/prepass/prepass.wgsl | 4 +- .../src/prepass/prepass_bindings.wgsl | 7 +- .../src/render/pbr_prepass_functions.wgsl | 4 +- 6 files changed, 67 insertions(+), 64 deletions(-) diff --git a/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs b/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs index f87751ba4b..bbe1676bbe 100644 --- a/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs +++ b/crates/bevy_pbr/src/meshlet/material_draw_nodes.rs @@ -7,8 +7,8 @@ use super::{ MeshletGpuScene, }; use crate::{ - MeshViewBindGroup, PrepassViewBindGroup, PreviousViewProjectionUniformOffset, - ViewFogUniformOffset, ViewLightProbesUniformOffset, ViewLightsUniformOffset, + MeshViewBindGroup, PrepassViewBindGroup, PreviousViewUniformOffset, ViewFogUniformOffset, + ViewLightProbesUniformOffset, ViewLightsUniformOffset, }; use bevy_core_pipeline::prepass::ViewPrepassTextures; use bevy_ecs::{query::QueryItem, world::World}; @@ -135,7 +135,7 @@ impl ViewNode for MeshletPrepassNode { &'static ExtractedCamera, &'static ViewPrepassTextures, &'static ViewUniformOffset, - Option<&'static PreviousViewProjectionUniformOffset>, + Option<&'static PreviousViewUniformOffset>, &'static MeshletViewMaterialsPrepass, &'static MeshletViewBindGroups, &'static MeshletViewResources, @@ -149,7 +149,7 @@ impl ViewNode for MeshletPrepassNode { camera, view_prepass_textures, view_uniform_offset, - previous_view_projection_uniform_offset, + previous_view_uniform_offset, meshlet_view_materials, meshlet_view_bind_groups, meshlet_view_resources, @@ -209,15 +209,13 @@ impl ViewNode for MeshletPrepassNode { render_pass.set_camera_viewport(viewport); } - if let Some(previous_view_projection_uniform_offset) = - previous_view_projection_uniform_offset - { + if let Some(previous_view_uniform_offset) = previous_view_uniform_offset { render_pass.set_bind_group( 0, prepass_view_bind_group.motion_vectors.as_ref().unwrap(), &[ view_uniform_offset.offset, - previous_view_projection_uniform_offset.offset, + previous_view_uniform_offset.offset, ], ); } else { @@ -258,7 +256,7 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode { &'static ExtractedCamera, &'static ViewPrepassTextures, &'static ViewUniformOffset, - Option<&'static PreviousViewProjectionUniformOffset>, + Option<&'static PreviousViewUniformOffset>, &'static MeshletViewMaterialsDeferredGBufferPrepass, &'static MeshletViewBindGroups, &'static MeshletViewResources, @@ -272,7 +270,7 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode { camera, view_prepass_textures, view_uniform_offset, - previous_view_projection_uniform_offset, + previous_view_uniform_offset, meshlet_view_materials, meshlet_view_bind_groups, meshlet_view_resources, @@ -337,15 +335,13 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode { render_pass.set_camera_viewport(viewport); } - if let Some(previous_view_projection_uniform_offset) = - previous_view_projection_uniform_offset - { + if let Some(previous_view_uniform_offset) = previous_view_uniform_offset { render_pass.set_bind_group( 0, prepass_view_bind_group.motion_vectors.as_ref().unwrap(), &[ view_uniform_offset.offset, - previous_view_projection_uniform_offset.offset, + previous_view_uniform_offset.offset, ], ); } else { diff --git a/crates/bevy_pbr/src/meshlet/visibility_buffer_resolve.wgsl b/crates/bevy_pbr/src/meshlet/visibility_buffer_resolve.wgsl index 0325ba96b9..4ade7d709a 100644 --- a/crates/bevy_pbr/src/meshlet/visibility_buffer_resolve.wgsl +++ b/crates/bevy_pbr/src/meshlet/visibility_buffer_resolve.wgsl @@ -22,7 +22,7 @@ #ifdef PREPASS_FRAGMENT #ifdef MOTION_VECTOR_PREPASS #import bevy_pbr::{ - prepass_bindings::previous_view_proj, + prepass_bindings::previous_view_uniforms, pbr_prepass_functions::calculate_motion_vector, } #endif @@ -153,9 +153,9 @@ fn resolve_vertex_output(frag_coord: vec4) -> VertexOutput { let previous_world_position_1 = mesh_position_local_to_world(previous_model, vec4(vertex_1.position, 1.0)); let previous_world_position_2 = mesh_position_local_to_world(previous_model, vec4(vertex_2.position, 1.0)); let previous_world_position_3 = mesh_position_local_to_world(previous_model, vec4(vertex_3.position, 1.0)); - let previous_clip_position_1 = previous_view_proj * vec4(previous_world_position_1.xyz, 1.0); - let previous_clip_position_2 = previous_view_proj * vec4(previous_world_position_2.xyz, 1.0); - let previous_clip_position_3 = previous_view_proj * vec4(previous_world_position_3.xyz, 1.0); + let previous_clip_position_1 = previous_view_uniforms.view_proj * vec4(previous_world_position_1.xyz, 1.0); + let previous_clip_position_2 = previous_view_uniforms.view_proj * vec4(previous_world_position_2.xyz, 1.0); + let previous_clip_position_3 = previous_view_uniforms.view_proj * vec4(previous_world_position_3.xyz, 1.0); let previous_partial_derivatives = compute_partial_derivatives( array(previous_clip_position_1, previous_clip_position_2, previous_clip_position_3), frag_coord_ndc, diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index 0536434c25..e43ab46b05 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -143,7 +143,7 @@ where PreUpdate, ( update_mesh_previous_global_transforms, - update_previous_view_projections, + update_previous_view_data, ), ); } @@ -154,7 +154,7 @@ where if no_prepass_plugin_loaded { render_app - .add_systems(ExtractSchedule, extract_camera_previous_view_projection) + .add_systems(ExtractSchedule, extract_camera_previous_view_data) .add_systems( Render, ( @@ -163,7 +163,7 @@ where sort_binned_render_phase:: ).in_set(RenderSet::PhaseSort), ( - prepare_previous_view_projection_uniforms, + prepare_previous_view_uniforms, batch_and_prepare_binned_render_phase::, batch_and_prepare_binned_render_phase::, @@ -201,17 +201,20 @@ where struct AnyPrepassPluginLoaded; #[derive(Component, ShaderType, Clone)] -pub struct PreviousViewProjection { +pub struct PreviousViewData { + pub inverse_view: Mat4, pub view_proj: Mat4, } -pub fn update_previous_view_projections( +pub fn update_previous_view_data( mut commands: Commands, query: Query<(Entity, &Camera, &GlobalTransform), (With, With)>, ) { for (entity, camera, camera_transform) in &query { - commands.entity(entity).try_insert(PreviousViewProjection { - view_proj: camera.projection_matrix() * camera_transform.compute_matrix().inverse(), + let inverse_view = camera_transform.compute_matrix().inverse(); + commands.entity(entity).try_insert(PreviousViewData { + inverse_view, + view_proj: camera.projection_matrix() * inverse_view, }); } } @@ -263,8 +266,8 @@ impl FromWorld for PrepassPipeline { uniform_buffer::(true), // Globals uniform_buffer::(false), - // PreviousViewProjection - uniform_buffer::(true), + // PreviousViewUniforms + uniform_buffer::(true), ), ), ); @@ -603,16 +606,16 @@ where } // Extract the render phases for the prepass -pub fn extract_camera_previous_view_projection( +pub fn extract_camera_previous_view_data( mut commands: Commands, - cameras_3d: Extract), With>>, + cameras_3d: Extract), With>>, ) { - for (entity, camera, maybe_previous_view_proj) in cameras_3d.iter() { + for (entity, camera, maybe_previous_view_data) in cameras_3d.iter() { if camera.is_active { let mut entity = commands.get_or_spawn(entity); - if let Some(previous_view) = maybe_previous_view_proj { - entity.insert(previous_view.clone()); + if let Some(previous_view_data) = maybe_previous_view_data { + entity.insert(previous_view_data.clone()); } } } @@ -620,23 +623,20 @@ pub fn extract_camera_previous_view_projection( #[derive(Resource, Default)] pub struct PreviousViewProjectionUniforms { - pub uniforms: DynamicUniformBuffer, + pub uniforms: DynamicUniformBuffer, } #[derive(Component)] -pub struct PreviousViewProjectionUniformOffset { +pub struct PreviousViewUniformOffset { pub offset: u32, } -pub fn prepare_previous_view_projection_uniforms( +pub fn prepare_previous_view_uniforms( mut commands: Commands, render_device: Res, render_queue: Res, mut view_uniforms: ResMut, - views: Query< - (Entity, &ExtractedView, Option<&PreviousViewProjection>), - With, - >, + views: Query<(Entity, &ExtractedView, Option<&PreviousViewData>), With>, ) { let views_iter = views.iter(); let view_count = views_iter.len(); @@ -647,18 +647,22 @@ pub fn prepare_previous_view_projection_uniforms( else { return; }; - for (entity, camera, maybe_previous_view_proj) in views_iter { - let view_projection = match maybe_previous_view_proj { + + for (entity, camera, maybe_previous_view_uniforms) in views_iter { + let view_projection = match maybe_previous_view_uniforms { Some(previous_view) => previous_view.clone(), - None => PreviousViewProjection { - view_proj: camera.projection * camera.transform.compute_matrix().inverse(), - }, + None => { + let inverse_view = camera.transform.compute_matrix().inverse(); + PreviousViewData { + inverse_view, + view_proj: camera.projection * inverse_view, + } + } }; - commands - .entity(entity) - .insert(PreviousViewProjectionUniformOffset { - offset: writer.write(&view_projection), - }); + + commands.entity(entity).insert(PreviousViewUniformOffset { + offset: writer.write(&view_projection), + }); } } @@ -673,7 +677,7 @@ pub fn prepare_prepass_view_bind_group( prepass_pipeline: Res>, view_uniforms: Res, globals_buffer: Res, - previous_view_proj_uniforms: Res, + previous_view_uniforms: Res, mut prepass_view_bind_group: ResMut, ) { if let (Some(view_binding), Some(globals_binding)) = ( @@ -686,14 +690,14 @@ pub fn prepare_prepass_view_bind_group( &BindGroupEntries::sequential((view_binding.clone(), globals_binding.clone())), )); - if let Some(previous_view_proj_binding) = previous_view_proj_uniforms.uniforms.binding() { + if let Some(previous_view_uniforms_binding) = previous_view_uniforms.uniforms.binding() { prepass_view_bind_group.motion_vectors = Some(render_device.create_bind_group( "prepass_view_motion_vectors_bind_group", &prepass_pipeline.view_layout_motion_vectors, &BindGroupEntries::sequential(( view_binding, globals_binding, - previous_view_proj_binding, + previous_view_uniforms_binding, )), )); } @@ -918,16 +922,16 @@ impl RenderCommand

for SetPrepassViewBindGroup< type Param = SRes; type ViewQuery = ( Read, - Option>, + Option>, ); type ItemQuery = (); #[inline] fn render<'w>( _item: &P, - (view_uniform_offset, previous_view_projection_uniform_offset): ( + (view_uniform_offset, previous_view_uniform_offset): ( &'_ ViewUniformOffset, - Option<&'_ PreviousViewProjectionUniformOffset>, + Option<&'_ PreviousViewUniformOffset>, ), _entity: Option<()>, prepass_view_bind_group: SystemParamItem<'w, '_, Self::Param>, @@ -935,15 +939,13 @@ impl RenderCommand

for SetPrepassViewBindGroup< ) -> RenderCommandResult { let prepass_view_bind_group = prepass_view_bind_group.into_inner(); - if let Some(previous_view_projection_uniform_offset) = - previous_view_projection_uniform_offset - { + if let Some(previous_view_uniform_offset) = previous_view_uniform_offset { pass.set_bind_group( I, prepass_view_bind_group.motion_vectors.as_ref().unwrap(), &[ view_uniform_offset.offset, - previous_view_projection_uniform_offset.offset, + previous_view_uniform_offset.offset, ], ); } else { diff --git a/crates/bevy_pbr/src/prepass/prepass.wgsl b/crates/bevy_pbr/src/prepass/prepass.wgsl index 094364a631..89e98fb313 100644 --- a/crates/bevy_pbr/src/prepass/prepass.wgsl +++ b/crates/bevy_pbr/src/prepass/prepass.wgsl @@ -4,7 +4,7 @@ prepass_io::{Vertex, VertexOutput, FragmentOutput}, skinning, morph, - mesh_view_bindings::{view, previous_view_proj}, + mesh_view_bindings::view, } #ifdef DEFERRED_PREPASS @@ -127,7 +127,7 @@ fn fragment(in: VertexOutput) -> FragmentOutput { #ifdef MOTION_VECTOR_PREPASS let clip_position_t = view.unjittered_view_proj * in.world_position; let clip_position = clip_position_t.xy / clip_position_t.w; - let previous_clip_position_t = prepass_bindings::previous_view_proj * in.previous_world_position; + let previous_clip_position_t = prepass_bindings::previous_view_uniforms.view_proj * in.previous_world_position; let previous_clip_position = previous_clip_position_t.xy / previous_clip_position_t.w; // These motion vectors are used as offsets to UV positions and are stored // in the range -1,1 to allow offsetting from the one corner to the diff --git a/crates/bevy_pbr/src/prepass/prepass_bindings.wgsl b/crates/bevy_pbr/src/prepass/prepass_bindings.wgsl index b574ef3fa4..fdc38a4c49 100644 --- a/crates/bevy_pbr/src/prepass/prepass_bindings.wgsl +++ b/crates/bevy_pbr/src/prepass/prepass_bindings.wgsl @@ -1,7 +1,12 @@ #define_import_path bevy_pbr::prepass_bindings +struct PreviousViewUniforms { + inverse_view: mat4x4, + view_proj: mat4x4, +} + #ifdef MOTION_VECTOR_PREPASS -@group(0) @binding(2) var previous_view_proj: mat4x4; +@group(0) @binding(2) var previous_view_uniforms: PreviousViewUniforms; #endif // MOTION_VECTOR_PREPASS // Material bindings will be in @group(2) diff --git a/crates/bevy_pbr/src/render/pbr_prepass_functions.wgsl b/crates/bevy_pbr/src/render/pbr_prepass_functions.wgsl index edf08a5cb2..aab3a2abfb 100644 --- a/crates/bevy_pbr/src/render/pbr_prepass_functions.wgsl +++ b/crates/bevy_pbr/src/render/pbr_prepass_functions.wgsl @@ -2,7 +2,7 @@ #import bevy_pbr::{ prepass_io::VertexOutput, - prepass_bindings::previous_view_proj, + prepass_bindings::previous_view_uniforms, mesh_view_bindings::view, pbr_bindings, pbr_types, @@ -47,7 +47,7 @@ fn prepass_alpha_discard(in: VertexOutput) { fn calculate_motion_vector(world_position: vec4, previous_world_position: vec4) -> vec2 { let clip_position_t = view.unjittered_view_proj * world_position; let clip_position = clip_position_t.xy / clip_position_t.w; - let previous_clip_position_t = previous_view_proj * previous_world_position; + let previous_clip_position_t = previous_view_uniforms.view_proj * previous_world_position; let previous_clip_position = previous_clip_position_t.xy / previous_clip_position_t.w; // These motion vectors are used as offsets to UV positions and are stored // in the range -1,1 to allow offsetting from the one corner to the