diff --git a/content/news/2023-07-07-bevy-0.11/default-pose-bw.png b/content/news/2023-07-07-bevy-0.11/default-pose-bw.png new file mode 100644 index 0000000000..7f8339ac0d Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/default-pose-bw.png differ diff --git a/content/news/2023-07-07-bevy-0.11/frown-pose-bw.png b/content/news/2023-07-07-bevy-0.11/frown-pose-bw.png new file mode 100644 index 0000000000..ab5585ffb4 Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/frown-pose-bw.png differ diff --git a/content/news/2023-07-07-bevy-0.11/index.md b/content/news/2023-07-07-bevy-0.11/index.md index f99c4601d5..26e831d8f7 100644 --- a/content/news/2023-07-07-bevy-0.11/index.md +++ b/content/news/2023-07-07-bevy-0.11/index.md @@ -15,9 +15,125 @@ Since our last release a few months ago we've added a _ton_ of new features, bug +* **Morph targets**: Vertex-based animations * **Parallax mapping**: Materials now support an optional depth map, giving flat surfaces a feel of depth through parallaxing the material's textures. +## Morph Targets + +
authors: @nicopap, @cart
+ +Bevy, since the 0.7 release, supports 3D animations. + +But it only supported _skeletal_ animations. Leaving on the sidewalk a common +animation type called _morph targets_ (aka blendshapes, aka keyshapes, and a slew +of other name). This is the grandparent of all 3D character animation! +[Crash Bandicoot]'s run cycle used morph targets. + + +
Character model by Samuel Rosario (© all rights reserved), used with permission. Modified by nicopap, using the Snow character texture by Demeter Dzadik for Blender Studios (🅯 CC-BY). +
+ + +Nowadays, an animation artist will typically use a skeleton rig for wide +moves and morph targets to clean up the detailed movements. + +When it comes to game assets, however, the complex skeleton rigs used by +artists for faces and hands are too heavy. Usually, the poses are +"baked" into morph poses, and facial expression transitions are handled +in the engine through morph targets. + +Morph targets is a very simple animation method. Take a model, have a base +vertex position, move the vertices around to create several poses: + +
+

Default

A wireframe rendering of a character's face with a neutral expression
+

Frown

Wireframe rendering of a frowning character
+

Smirk

Wireframe rendering of a smirking character
+
+ +Store those poses as a difference between the default base mesh and the variant +pose, then, at runtime, _mix_ each pose. Now that we have the difference with +the base mesh, we can get the variant pose by simply adding to the base +vertices positions. + +That's it, the morph target shader looks like this: + +```rust +fn morph_vertex(vertex: Vertex) { + for (var i: u32 = 0u; i < pose_count(); i++) { + let weight = weight_for_pose(i); + vertex.position += weight * get_difference(vertex.index, position_offset, i); + vertex.normal += weight * get_difference(vertex.index, normal_offset, i); + } +} +``` + +In Bevy, we store the weights per pose in the `MorphWeights` component. + +```rust +fn set_weights_system(mut morph_weights: Query<&mut MorphWeights>) { + for mut entity_weights in &mut morph_weights { + let weights = entity_weights.weights_mut(); + + weights[0] = 0.5; + weights[1] = 0.25; + } +} +``` + +Now assuming that we have two morph targets, (1) the frown pose, (2) +the smirk pose: + +
+
+

[0.0, 0.0]

+

default pose

+ Neutral face expression +
+
+

[1.0, 0.0]

+

frown only

+ Frowning +
+
+

[0.0, 1.0]

+

smirk only

+ Smirking +
+
+

[0.5, 0.0]

+

half frown

+ Slightly frowning +
+
+

[1.0, 1.0]

+

both at max

+ Making faces +
+
+

[0.5, 0.25]

+

bit of both

+ Slightly frowning/smirking +
+
+ +While conceptually simple, it requires communicating to the GPU a tremendous +amount of data. Thousand of vertices, each 288 bits, several model variations, +sometimes a hundred. + +Bevy's morph target implementation is similar to BabyloneJS's. We store the +vertex data as pixels in a 3D texture. This allows morph targets to not only +run on WebGPU, but also on the WebGL2 wgpu backend. + +This could be improved in a number of ways, but it is sufficient for an +initial implementation. + + + +[Crash Bandicoot]: https://en.wikipedia.org/wiki/Crash_Bandicoot_(video_game)#Gameplay + ## Parallax Mapping
author: @nicopap
diff --git a/content/news/2023-07-07-bevy-0.11/morph_target_both-0.png b/content/news/2023-07-07-bevy-0.11/morph_target_both-0.png new file mode 100644 index 0000000000..fe6f8de5cc Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/morph_target_both-0.png differ diff --git a/content/news/2023-07-07-bevy-0.11/morph_target_default-0.png b/content/news/2023-07-07-bevy-0.11/morph_target_default-0.png new file mode 100644 index 0000000000..0ae9c4fb73 Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/morph_target_default-0.png differ diff --git a/content/news/2023-07-07-bevy-0.11/morph_target_frown-0.png b/content/news/2023-07-07-bevy-0.11/morph_target_frown-0.png new file mode 100644 index 0000000000..50bbb81fbe Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/morph_target_frown-0.png differ diff --git a/content/news/2023-07-07-bevy-0.11/morph_target_frown-half-0.png b/content/news/2023-07-07-bevy-0.11/morph_target_frown-half-0.png new file mode 100644 index 0000000000..69d4f97339 Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/morph_target_frown-half-0.png differ diff --git a/content/news/2023-07-07-bevy-0.11/morph_target_smirk-quarter-frown-half-0.png b/content/news/2023-07-07-bevy-0.11/morph_target_smirk-quarter-frown-half-0.png new file mode 100644 index 0000000000..7167347071 Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/morph_target_smirk-quarter-frown-half-0.png differ diff --git a/content/news/2023-07-07-bevy-0.11/morph_target_smirk.mp4 b/content/news/2023-07-07-bevy-0.11/morph_target_smirk.mp4 new file mode 100644 index 0000000000..ee088e289f Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/morph_target_smirk.mp4 differ diff --git a/content/news/2023-07-07-bevy-0.11/morph_target_smirk.png b/content/news/2023-07-07-bevy-0.11/morph_target_smirk.png new file mode 100644 index 0000000000..44213d0e1d Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/morph_target_smirk.png differ diff --git a/content/news/2023-07-07-bevy-0.11/morph_targets_video.mp4 b/content/news/2023-07-07-bevy-0.11/morph_targets_video.mp4 new file mode 100644 index 0000000000..bb3e40655f Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/morph_targets_video.mp4 differ diff --git a/content/news/2023-07-07-bevy-0.11/smirk-pose-bw.png b/content/news/2023-07-07-bevy-0.11/smirk-pose-bw.png new file mode 100644 index 0000000000..d2911a788e Binary files /dev/null and b/content/news/2023-07-07-bevy-0.11/smirk-pose-bw.png differ