Skip to content

Commit

Permalink
Add previous_view_uniforms.inverse_view (bevyengine#12902)
Browse files Browse the repository at this point in the history
# Objective
- Upload previous frame's inverse_view matrix to the GPU for use with
bevyengine#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`.
  • Loading branch information
JMS55 authored Apr 7, 2024
1 parent 452821d commit 31b5943
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 64 deletions.
24 changes: 10 additions & 14 deletions crates/bevy_pbr/src/meshlet/material_draw_nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_pbr/src/meshlet/visibility_buffer_resolve.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -153,9 +153,9 @@ fn resolve_vertex_output(frag_coord: vec4<f32>) -> 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,
Expand Down
84 changes: 43 additions & 41 deletions crates/bevy_pbr/src/prepass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ where
PreUpdate,
(
update_mesh_previous_global_transforms,
update_previous_view_projections,
update_previous_view_data,
),
);
}
Expand All @@ -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,
(
Expand All @@ -163,7 +163,7 @@ where
sort_binned_render_phase::<AlphaMask3dPrepass>
).in_set(RenderSet::PhaseSort),
(
prepare_previous_view_projection_uniforms,
prepare_previous_view_uniforms,
batch_and_prepare_binned_render_phase::<Opaque3dPrepass, MeshPipeline>,
batch_and_prepare_binned_render_phase::<AlphaMask3dPrepass,
MeshPipeline>,
Expand Down Expand Up @@ -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<Camera3d>, With<MotionVectorPrepass>)>,
) {
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,
});
}
}
Expand Down Expand Up @@ -263,8 +266,8 @@ impl<M: Material> FromWorld for PrepassPipeline<M> {
uniform_buffer::<ViewUniform>(true),
// Globals
uniform_buffer::<GlobalsUniform>(false),
// PreviousViewProjection
uniform_buffer::<PreviousViewProjection>(true),
// PreviousViewUniforms
uniform_buffer::<PreviousViewData>(true),
),
),
);
Expand Down Expand Up @@ -603,40 +606,37 @@ 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<Query<(Entity, &Camera, Option<&PreviousViewProjection>), With<Camera3d>>>,
cameras_3d: Extract<Query<(Entity, &Camera, Option<&PreviousViewData>), With<Camera3d>>>,
) {
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());
}
}
}
}

#[derive(Resource, Default)]
pub struct PreviousViewProjectionUniforms {
pub uniforms: DynamicUniformBuffer<PreviousViewProjection>,
pub uniforms: DynamicUniformBuffer<PreviousViewData>,
}

#[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<RenderDevice>,
render_queue: Res<RenderQueue>,
mut view_uniforms: ResMut<PreviousViewProjectionUniforms>,
views: Query<
(Entity, &ExtractedView, Option<&PreviousViewProjection>),
With<MotionVectorPrepass>,
>,
views: Query<(Entity, &ExtractedView, Option<&PreviousViewData>), With<MotionVectorPrepass>>,
) {
let views_iter = views.iter();
let view_count = views_iter.len();
Expand All @@ -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),
});
}
}

Expand All @@ -673,7 +677,7 @@ pub fn prepare_prepass_view_bind_group<M: Material>(
prepass_pipeline: Res<PrepassPipeline<M>>,
view_uniforms: Res<ViewUniforms>,
globals_buffer: Res<GlobalsBuffer>,
previous_view_proj_uniforms: Res<PreviousViewProjectionUniforms>,
previous_view_uniforms: Res<PreviousViewProjectionUniforms>,
mut prepass_view_bind_group: ResMut<PrepassViewBindGroup>,
) {
if let (Some(view_binding), Some(globals_binding)) = (
Expand All @@ -686,14 +690,14 @@ pub fn prepare_prepass_view_bind_group<M: Material>(
&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,
)),
));
}
Expand Down Expand Up @@ -918,32 +922,30 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetPrepassViewBindGroup<
type Param = SRes<PrepassViewBindGroup>;
type ViewQuery = (
Read<ViewUniformOffset>,
Option<Read<PreviousViewProjectionUniformOffset>>,
Option<Read<PreviousViewUniformOffset>>,
);
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>,
pass: &mut TrackedRenderPass<'w>,
) -> 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 {
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/prepass/prepass.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion crates/bevy_pbr/src/prepass/prepass_bindings.wgsl
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#define_import_path bevy_pbr::prepass_bindings

struct PreviousViewUniforms {
inverse_view: mat4x4<f32>,
view_proj: mat4x4<f32>,
}

#ifdef MOTION_VECTOR_PREPASS
@group(0) @binding(2) var<uniform> previous_view_proj: mat4x4<f32>;
@group(0) @binding(2) var<uniform> previous_view_uniforms: PreviousViewUniforms;
#endif // MOTION_VECTOR_PREPASS

// Material bindings will be in @group(2)
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/render/pbr_prepass_functions.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -47,7 +47,7 @@ fn prepass_alpha_discard(in: VertexOutput) {
fn calculate_motion_vector(world_position: vec4<f32>, previous_world_position: vec4<f32>) -> vec2<f32> {
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
Expand Down

0 comments on commit 31b5943

Please sign in to comment.