Open mvaligursky opened 4 years ago
I wrote a quick prototype for this, and the results are reasonably positive. I created a scene with 100 of characters, each 70 bones, single mesh/skin each. The syncHierarchy for this takes 3ms per frame on MacBook Pro.
Disabling hierarchy update, and moving it to SkinInstance.updateMatrices saved those 3ms, while not changing cost of updateMatrices, as the need to multiply matrix with inverse of root is removed, and replaced by a matrix multiply to 'update hierarchy' - multiply local matrix with parent matrix. The result are still 2 matrix multiplies per bone.
Positive - by removing multiply with inverse root, we improve precision of skinning, as hierarchy update of character takes place in character's space, instead of evaluating it at world space and then bringing it to character space for rendering, when precision of floats in Mat4 has already been lost.
Overall - this is a nice optimization, but only saves about 3ms in the frame from about 80. Priority should be given to following issues which have the potential to move the needle a lot more:
In future, hoping for SIMD to get available in JS, it will dramatically improve CPU based Math of the engine.
Related to #2202.
Currently to render the animated character, we sync the hierarchy to generate world matrices for bones. Then we multiply those matrices by inverse character root bone matrix to have them in local space - which is pretty expensive.
We should explore a possibility to create an optimized hierarchy structure for characters to speed this up:
flatten the hierarchy into array of matrices (possibly pointing to original hierarchy directly), stored in breadth-first order, allowing world matrices by updated in a single loop, possibly using wasm module
matrices in this flat storage would be relative to character root, allowing us to avoid matrix multiply per bone
This would have impact on many things a solution would need to handle, such as: