When rendering a mesh with blend shapes, the vertex shader will skip any shapes with a weight close to zero. However, compressed animation blend shape tracks output a weight above this threshold even though the original animated weight was zero. This could cause a performance issue if an animation has a lot of zero weight blend shapes. It will also affect the visuals, although that will be hard to see as the weight is very close to zero.
Note that there's another potential issue with how blend shape tracks and other tracks are doing unorm rounding. I've filed that as https://github.com/godotengine/godot/issues/99796, and will roll both fixes into the same PR unless advised otherwise.
Steps to reproduce
Launch the MRP project. The main scene has two cubes playing an animation with some zero weight blend shape tracks. Left cube = uncompressed animation, right cube = compressed. Initially there should be no visual difference.
Repo option 1 (requires code changes): Apply change https://github.com/greeble-dev/godot/commit/107bbe62e444f8d517a96a8732d016838e52779e to skeleton.glsl, which will force any blend shape that passes the weight threshold to blend with a weight of one instead. This is just a hacky way to show if the vertex shader skipped the shape. Launch the project and note that the cube with compressed animation is now distorted while the uncompressed animation is unchanged.
Repro option 2 (no code changes): Breakpoint Animation::try_blend_shape_track_interpolate, then in the editor select node AnimCompressed/AnimationPlayer to trigger the breakpoint. Note that the compressed path returns a weight of -0.00012207.
Tested versions
Reproducible in Godot v4.4.dev [bbc54692c].
System information
Windows 10.0.19045. Compiled with MSVC.
Issue description
When rendering a mesh with blend shapes, the vertex shader will skip any shapes with a weight close to zero. However, compressed animation blend shape tracks output a weight above this threshold even though the original animated weight was zero. This could cause a performance issue if an animation has a lot of zero weight blend shapes. It will also affect the visuals, although that will be hard to see as the weight is very close to zero.
The blend shape compression code is:
A weight of 0.0 compresses to unorm 32767, which decompresses to -0.00012207. This is slightly bigger than the vertex shader's threshold of 0.0001.
A potential fix is to change the 65535 scale to 65534 (https://github.com/greeble-dev/godot/commit/06502a0fbf778f1000e948261dbb3a20d4551b87). This means zero still compresses to unorm 32767, but that now decompresses to zero. The change would be backwards compatible with assets that were compressed before the change.
I can make a PR with this change if desired.
Note that there's another potential issue with how blend shape tracks and other tracks are doing unorm rounding. I've filed that as https://github.com/godotengine/godot/issues/99796, and will roll both fixes into the same PR unless advised otherwise.
Steps to reproduce
Launch the MRP project. The main scene has two cubes playing an animation with some zero weight blend shape tracks. Left cube = uncompressed animation, right cube = compressed. Initially there should be no visual difference.
Repo option 1 (requires code changes): Apply change https://github.com/greeble-dev/godot/commit/107bbe62e444f8d517a96a8732d016838e52779e to skeleton.glsl, which will force any blend shape that passes the weight threshold to blend with a weight of one instead. This is just a hacky way to show if the vertex shader skipped the shape. Launch the project and note that the cube with compressed animation is now distorted while the uncompressed animation is unchanged.
Repro option 2 (no code changes): Breakpoint
Animation::try_blend_shape_track_interpolate
, then in the editor select nodeAnimCompressed/AnimationPlayer
to trigger the breakpoint. Note that the compressed path returns a weight of -0.00012207.To test the potential fix, apply change https://github.com/greeble-dev/godot/commit/06502a0fbf778f1000e948261dbb3a20d4551b87. Launch the editor and select node
AnimCompressed/AnimationPlayer
to make it update. The cubes should now match, showing that the blend shape is correctly skipped.Minimal reproduction project (MRP)
bug-blend-shape-repro.zip