Fix motion blur on skinned meshes (#18712)
## Objective Fix motion blur not working on skinned meshes. ## Solution `set_mesh_motion_vector_flags` can set `RenderMeshInstanceFlags::HAS_PREVIOUS_SKIN` after specialization has already cached the material. This can lead to `MeshPipelineKey::HAS_PREVIOUS_SKIN` never getting set, disabling motion blur. The fix is to make sure `set_mesh_motion_vector_flags` happens before specialization. Note that the bug is fixed in a different way by #18074, which includes other fixes but is a much larger change. ## Testing Open the `animated_mesh` example and add these components to the `Camera3d` entity: ```rust MotionBlur { shutter_angle: 5.0, samples: 2, #[cfg(all(feature = "webgl2", target_arch = "wasm32", not(feature = "webgpu")))] _webgl2_padding: Default::default(), }, #[cfg(all(feature = "webgl2", target_arch = "wasm32", not(feature = "webgpu")))] Msaa::Off, ``` Tested on `animated_mesh`, `many_foxes`, `custom_skinned_mesh`, Win10/Nvidia with Vulkan, WebGL/Chrome, WebGPU/Chrome. Note that testing `many_foxes` WebGL requires #18715.
This commit is contained in:
parent
78d5c50b50
commit
5da64ddbee
@ -327,7 +327,8 @@ where
|
|||||||
.in_set(RenderSet::PrepareMeshes)
|
.in_set(RenderSet::PrepareMeshes)
|
||||||
.after(prepare_assets::<PreparedMaterial<M>>)
|
.after(prepare_assets::<PreparedMaterial<M>>)
|
||||||
.after(prepare_assets::<RenderMesh>)
|
.after(prepare_assets::<RenderMesh>)
|
||||||
.after(collect_meshes_for_gpu_building),
|
.after(collect_meshes_for_gpu_building)
|
||||||
|
.after(set_mesh_motion_vector_flags),
|
||||||
queue_material_meshes::<M>
|
queue_material_meshes::<M>
|
||||||
.in_set(RenderSet::QueueMeshes)
|
.in_set(RenderSet::QueueMeshes)
|
||||||
.after(prepare_assets::<PreparedMaterial<M>>),
|
.after(prepare_assets::<PreparedMaterial<M>>),
|
||||||
|
@ -3,11 +3,11 @@ mod prepass_bindings;
|
|||||||
use crate::{
|
use crate::{
|
||||||
alpha_mode_pipeline_key, binding_arrays_are_usable, buffer_layout,
|
alpha_mode_pipeline_key, binding_arrays_are_usable, buffer_layout,
|
||||||
collect_meshes_for_gpu_building, material_bind_groups::MaterialBindGroupAllocator,
|
collect_meshes_for_gpu_building, material_bind_groups::MaterialBindGroupAllocator,
|
||||||
queue_material_meshes, setup_morph_and_skinning_defs, skin, DrawMesh,
|
queue_material_meshes, set_mesh_motion_vector_flags, setup_morph_and_skinning_defs, skin,
|
||||||
EntitySpecializationTicks, Material, MaterialPipeline, MaterialPipelineKey, MeshLayouts,
|
DrawMesh, EntitySpecializationTicks, Material, MaterialPipeline, MaterialPipelineKey,
|
||||||
MeshPipeline, MeshPipelineKey, OpaqueRendererMethod, PreparedMaterial, RenderLightmaps,
|
MeshLayouts, MeshPipeline, MeshPipelineKey, OpaqueRendererMethod, PreparedMaterial,
|
||||||
RenderMaterialInstances, RenderMeshInstanceFlags, RenderMeshInstances, RenderPhaseType,
|
RenderLightmaps, RenderMaterialInstances, RenderMeshInstanceFlags, RenderMeshInstances,
|
||||||
SetMaterialBindGroup, SetMeshBindGroup, ShadowView, StandardMaterial,
|
RenderPhaseType, SetMaterialBindGroup, SetMeshBindGroup, ShadowView, StandardMaterial,
|
||||||
};
|
};
|
||||||
use bevy_app::{App, Plugin, PreUpdate};
|
use bevy_app::{App, Plugin, PreUpdate};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
@ -219,7 +219,8 @@ where
|
|||||||
.in_set(RenderSet::PrepareMeshes)
|
.in_set(RenderSet::PrepareMeshes)
|
||||||
.after(prepare_assets::<PreparedMaterial<M>>)
|
.after(prepare_assets::<PreparedMaterial<M>>)
|
||||||
.after(prepare_assets::<RenderMesh>)
|
.after(prepare_assets::<RenderMesh>)
|
||||||
.after(collect_meshes_for_gpu_building),
|
.after(collect_meshes_for_gpu_building)
|
||||||
|
.after(set_mesh_motion_vector_flags),
|
||||||
queue_prepass_material_meshes::<M>
|
queue_prepass_material_meshes::<M>
|
||||||
.in_set(RenderSet::QueueMeshes)
|
.in_set(RenderSet::QueueMeshes)
|
||||||
.after(prepare_assets::<PreparedMaterial<M>>)
|
.after(prepare_assets::<PreparedMaterial<M>>)
|
||||||
|
@ -1648,7 +1648,7 @@ fn extract_mesh_for_gpu_building(
|
|||||||
/// [`crate::material::queue_material_meshes`] check the skin and morph target
|
/// [`crate::material::queue_material_meshes`] check the skin and morph target
|
||||||
/// tables for each mesh, but that would be too slow in the hot mesh queuing
|
/// tables for each mesh, but that would be too slow in the hot mesh queuing
|
||||||
/// loop.
|
/// loop.
|
||||||
fn set_mesh_motion_vector_flags(
|
pub(crate) fn set_mesh_motion_vector_flags(
|
||||||
mut render_mesh_instances: ResMut<RenderMeshInstances>,
|
mut render_mesh_instances: ResMut<RenderMeshInstances>,
|
||||||
skin_uniforms: Res<SkinUniforms>,
|
skin_uniforms: Res<SkinUniforms>,
|
||||||
morph_indices: Res<MorphIndices>,
|
morph_indices: Res<MorphIndices>,
|
||||||
|
Loading…
Reference in New Issue
Block a user