mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 06:00:20 +00:00
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`.
This commit is contained in:
parent
452821dd52
commit
31b5943ad4
6 changed files with 67 additions and 64 deletions
|
@ -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 {
|
||||
|
|
|
@ -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<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,
|
||||
|
|
|
@ -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::<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>,
|
||||
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -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<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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -620,23 +623,20 @@ pub fn extract_camera_previous_view_projection(
|
|||
|
||||
#[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();
|
||||
|
@ -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<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)) = (
|
||||
|
@ -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,
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
@ -918,16 +922,16 @@ 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>,
|
||||
|
@ -935,15 +939,13 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> 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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<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
|
||||
|
|
Loading…
Reference in a new issue