Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion crates/bevy_pbr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,10 @@ pub mod prelude {
}

use crate::gpu::GpuClusteringPlugin;
use crate::{deferred::DeferredPbrLightingPlugin, gpu::extract_clusters_for_gpu_clustering};
use crate::{
deferred::DeferredPbrLightingPlugin, gpu::extract_clusters_for_gpu_clustering,
skin::cache::SkinCachePlugin,
};
use bevy_app::prelude::*;
use bevy_asset::{AssetApp, AssetPath, Assets, Handle, RenderAssetUsages};
use bevy_core_pipeline::mip_generation::experimental::depth::early_downsample_depth;
Expand Down Expand Up @@ -238,6 +241,7 @@ impl Plugin for PbrPlugin {
))
.add_plugins((
decal::ForwardDecalPlugin,
SkinCachePlugin,
SyncComponentPlugin::<DirectionalLight, Self>::default(),
SyncComponentPlugin::<PointLight, Self>::default(),
SyncComponentPlugin::<SpotLight, Self>::default(),
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,13 @@ pub(crate) fn specialize_material_meshes(
}
}

if mesh_instance
.flags()
.contains(RenderMeshInstanceFlags::SKIN_CACHE)
{
mesh_key |= MeshPipelineKey::SKIN_CACHE;
}

work_items.push(SpecializationWorkItem {
visible_entity: *visible_entity,
retained_view_entity: view.retained_view_entity,
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_pbr/src/meshlet/instance_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ impl InstanceManager {
None,
None,
None,
None,
);

// Append instance data
Expand Down
10 changes: 10 additions & 0 deletions crates/bevy_pbr/src/prepass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,19 +1077,29 @@ pub(crate) fn specialize_prepass_material_meshes(
// If the previous frame has skins or morph targets, note that.
if motion_vector_prepass.is_some() {
if mesh_instance
.shared
.flags()
.contains(RenderMeshInstanceFlags::HAS_PREVIOUS_SKIN)
{
mesh_key |= MeshPipelineKey::HAS_PREVIOUS_SKIN;
}
if mesh_instance
.shared
.flags()
.contains(RenderMeshInstanceFlags::HAS_PREVIOUS_MORPH)
{
mesh_key |= MeshPipelineKey::HAS_PREVIOUS_MORPH;
}
}

if mesh_instance
.shared
.flags()
.contains(RenderMeshInstanceFlags::SKIN_CACHE)
{
mesh_key |= MeshPipelineKey::SKIN_CACHE;
}

work_items.push(PrepassSpecializationWorkItem {
visible_entity: *visible_entity,
retained_view_entity: extracted_view.retained_view_entity,
Expand Down
60 changes: 52 additions & 8 deletions crates/bevy_pbr/src/prepass/prepass.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,28 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {

let mesh_world_from_local = mesh_functions::get_world_from_local(vertex_no_morph.instance_index);

#ifdef SKINNED
var world_from_local = mesh_world_from_local;
#ifdef SKINNED_OR_MORPHED
#ifdef SKIN_CACHE
let first_vertex_index = mesh[vertex_no_morph.instance_index].first_vertex_index;
let vertex_index = vertex_no_morph.index - first_vertex_index;
let mesh_cached_skin_offset = mesh[vertex_no_morph.instance_index].cached_skin_offset;
let cached_skin_offset = mesh_cached_skin_offset + vertex_index;
out.world_position = vec4(skinning::cached_skinned_vertices[cached_skin_offset].position, 1.0);
#else ifdef SKINNED // SKIN_CACHE
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
// See https://github.com/gfx-rs/naga/issues/2416
var world_from_local = skinning::skin_model(
world_from_local = skinning::skin_model(
vertex.joint_indices,
vertex.joint_weights,
vertex_no_morph.instance_index
);
#else // SKINNED
var world_from_local = mesh_world_from_local;
#endif // SKINNED
#endif // SKINNED
#endif // SKINNED_OR_MORPHED

#ifndef SKIN_CACHE
out.world_position = mesh_functions::mesh_position_local_to_world(world_from_local, vec4<f32>(vertex.position, 1.0));
#endif // SKIN_CACHE
out.position = position_world_to_clip(out.world_position.xyz);
#ifdef UNCLIPPED_DEPTH_ORTHO_EMULATION
out.unclipped_depth = out.position.z;
Expand All @@ -105,9 +114,11 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {

#ifdef NORMAL_PREPASS_OR_DEFERRED_PREPASS
#ifdef VERTEX_NORMALS
#ifdef SKINNED
#ifdef SKIN_CACHE
out.world_normal = skinning::cached_skinned_vertices[cached_skin_offset].normal;
#else ifdef SKINNED // SKIN_CACHE
out.world_normal = skinning::skin_normals(world_from_local, vertex.normal);
#else // SKINNED
#else // SKINNED
out.world_normal = mesh_functions::mesh_normal_local_to_world(
vertex.normal,
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
Expand All @@ -118,13 +129,17 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
#endif // VERTEX_NORMALS

#ifdef VERTEX_TANGENTS
#ifdef SKIN_CACHE
out.world_tangent = skinning::cached_skinned_vertices[cached_skin_offset].tangent;
#else // SKIN_CACHE
out.world_tangent = mesh_functions::mesh_tangent_local_to_world(
world_from_local,
vertex.tangent,
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
// See https://github.com/gfx-rs/naga/issues/2416
vertex_no_morph.instance_index
);
#endif // SKIN_CACHE
#endif // VERTEX_TANGENTS
#endif // NORMAL_PREPASS_OR_DEFERRED_PREPASS

Expand All @@ -136,6 +151,21 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
// to know where the vertex was last frame.
#ifdef MOTION_VECTOR_PREPASS

#ifdef SKINNED_OR_MORPHED

#ifdef SKIN_CACHE
let mesh_prev_cached_skin_offset = mesh[vertex_no_morph.instance_index].prev_cached_skin_offset;
if (mesh_prev_cached_skin_offset != 0xffffffffu) {
let prev_cached_skin_offset = mesh_prev_cached_skin_offset + vertex_index;
out.previous_world_position = vec4(
skinning::prev_cached_skinned_vertices[prev_cached_skin_offset].position,
1.0
);
} else {
out.previous_world_position = out.world_position;
}
#else // SKIN_CACHE

// Take morph targets into account.
#ifdef MORPH_TARGETS

Expand Down Expand Up @@ -174,7 +204,21 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
prev_model,
vec4<f32>(prev_vertex.position, 1.0)
);
#endif // MOTION_VECTOR_PREPASS

#endif // SKIN_CACHE

#else // SKINNED_OR_MORPHED

let prev_vertex = vertex_no_morph;
let prev_model = mesh_functions::get_previous_world_from_local(vertex_no_morph.instance_index);
out.previous_world_position = mesh_functions::mesh_position_local_to_world(
prev_model,
vec4<f32>(prev_vertex.position, 1.0)
);

#endif // SKINNED_OR_MORPHED

#endif // MOTION_VECTOR_PREPASS

#ifdef VERTEX_OUTPUT_INSTANCE_INDEX
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
Expand Down
2 changes: 0 additions & 2 deletions crates/bevy_pbr/src/prepass/prepass_io.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ struct Vertex {
@location(7) color: vec4<f32>,
#endif

#ifdef MORPH_TARGETS
@builtin(vertex_index) index: u32,
#endif // MORPH_TARGETS
}

struct VertexOutput {
Expand Down
2 changes: 0 additions & 2 deletions crates/bevy_pbr/src/render/forward_io.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ struct Vertex {
@location(6) joint_indices: vec4<u32>,
@location(7) joint_weights: vec4<f32>,
#endif
#ifdef MORPH_TARGETS
@builtin(vertex_index) index: u32,
#endif
Comment thread
pcwalton marked this conversation as resolved.
};

struct VertexOutput {
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2337,6 +2337,13 @@ pub(crate) fn specialize_shadows(
_ => MeshPipelineKey::NONE,
};

if mesh_instance
.flags()
.contains(RenderMeshInstanceFlags::SKIN_CACHE)
{
mesh_key |= MeshPipelineKey::SKIN_CACHE;
}

work_items.push(ShadowSpecializationWorkItem {
visible_entity: *visible_entity,
retained_view_entity: extracted_view_light.retained_view_entity,
Expand Down
Loading