This is a revamped equivalent to #9902, though it shares none of the code. It handles all special cases that I've tested correctly. The overall technique consists of double-buffering the joint matrix and morph weights buffers, as most of the previous attempts to solve this problem did. The process is generally straightforward. Note that, to avoid regressing the ability of mesh extraction, skin extraction, and morph target extraction to run in parallel, I had to add a new system to rendering, `set_mesh_motion_vector_flags`. The comment there explains the details; it generally runs very quickly. I've tested this with modified versions of the `animated_fox`, `morph_targets`, and `many_foxes` examples that add TAA, and the patch works. To avoid bloating those examples, I didn't add switches for TAA to them. Addresses points (1) and (2) of #8423. ## Changelog ### Fixed * Motion vectors, and therefore TAA, are now supported for meshes with skins and/or morph targets.
		
			
				
	
	
		
			69 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			WebGPU Shading Language
		
	
	
	
	
	
			
		
		
	
	
			69 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			WebGPU Shading Language
		
	
	
	
	
	
#define_import_path bevy_pbr::skinning
 | 
						|
 | 
						|
#import bevy_pbr::mesh_types::SkinnedMesh
 | 
						|
 | 
						|
#ifdef SKINNED
 | 
						|
 | 
						|
@group(1) @binding(1) var<uniform> joint_matrices: SkinnedMesh;
 | 
						|
 | 
						|
// An array of matrices specifying the joint positions from the previous frame.
 | 
						|
//
 | 
						|
// This is used for motion vector computation.
 | 
						|
//
 | 
						|
// If this is the first frame, or we're otherwise prevented from using data from
 | 
						|
// the previous frame, this is simply the same as `joint_matrices` above.
 | 
						|
@group(1) @binding(6) var<uniform> prev_joint_matrices: SkinnedMesh;
 | 
						|
 | 
						|
fn skin_model(
 | 
						|
    indexes: vec4<u32>,
 | 
						|
    weights: vec4<f32>,
 | 
						|
) -> mat4x4<f32> {
 | 
						|
    return weights.x * joint_matrices.data[indexes.x]
 | 
						|
        + weights.y * joint_matrices.data[indexes.y]
 | 
						|
        + weights.z * joint_matrices.data[indexes.z]
 | 
						|
        + weights.w * joint_matrices.data[indexes.w];
 | 
						|
}
 | 
						|
 | 
						|
// Returns the skinned position of a vertex with the given weights from the
 | 
						|
// previous frame.
 | 
						|
//
 | 
						|
// This is used for motion vector computation.
 | 
						|
fn skin_prev_model(
 | 
						|
    indexes: vec4<u32>,
 | 
						|
    weights: vec4<f32>,
 | 
						|
) -> mat4x4<f32> {
 | 
						|
    return weights.x * prev_joint_matrices.data[indexes.x]
 | 
						|
        + weights.y * prev_joint_matrices.data[indexes.y]
 | 
						|
        + weights.z * prev_joint_matrices.data[indexes.z]
 | 
						|
        + weights.w * prev_joint_matrices.data[indexes.w];
 | 
						|
}
 | 
						|
 | 
						|
fn inverse_transpose_3x3m(in: mat3x3<f32>) -> mat3x3<f32> {
 | 
						|
    let x = cross(in[1], in[2]);
 | 
						|
    let y = cross(in[2], in[0]);
 | 
						|
    let z = cross(in[0], in[1]);
 | 
						|
    let det = dot(in[2], z);
 | 
						|
    return mat3x3<f32>(
 | 
						|
        x / det,
 | 
						|
        y / det,
 | 
						|
        z / det
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
fn skin_normals(
 | 
						|
    model: mat4x4<f32>,
 | 
						|
    normal: vec3<f32>,
 | 
						|
) -> vec3<f32> {
 | 
						|
    return normalize(
 | 
						|
        inverse_transpose_3x3m(
 | 
						|
            mat3x3<f32>(
 | 
						|
                model[0].xyz,
 | 
						|
                model[1].xyz,
 | 
						|
                model[2].xyz
 | 
						|
            )
 | 
						|
        ) * normal
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |