Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add previous_view_uniforms.inverse_view #12902

Merged
merged 4 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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