Poor performance of facial animations.

Issue #1540 resolved
garden created an issue

I suppose the poor performance comes from driver chains that recalculate the values every frame.
Maybe there is some sense to add a check?
Something like:

if slider == 0.00
then “the entire driver chain is disabled”
else “drivers are enabled”

It's just weird that drivers are wasting performance, even when ALL the face sliders have a value of 0.00
I understand that the driver chains are confusing and some turn from one to the other, but is there nothing can do?

I want to be able to animate facial animations in the viewport at least at 30 fps.
Any ideas what can be done about it?

Comments (39)

  1. Thomas Larsson repo owner
    • changed status to open

    Unfortunately that doesn't work. All (or most) sliders drive all face bones, so we need all drivers to make them move correctly. The best way to speed up the animation is to not load more morphs than necessary.

    You can also try to Finalize Armature with Optimize Drivers enabled, although I don't quite remember what it does.

  2. Jasper29

    Sorry, I know this is for Diffeo related issues, but FPS optimization is a universal issue in Blender in generaI,

    so I just want to say that I know of a way to speed up fps tremendously (usually), but it takes a while to

    setup. You only have to do it once per character though and it saves tons of time/frustration in the long

    run. It’s an object having an armature modifier on it that usually has a huge impact on performance in

    viewport. This is because Blender calculates every vertex as the object with the armature modifier is

    deformed, not at the object level. One way around this is to put you character into Rest Position and

    duplicate your character’s mesh. Then put it into a separate collection and remove any modifiers that slow

    down viewport performance on it (SubD, Armature etc). Then select the bone deformation layer, go to Edit

    Mode, then use loop cuts to seperate your character mesh between every deformation bone (leave the

    whole head as is though and give only THAT mesh an armature modifier). Then select each ‘cut of mesh’

    and parent it to the corresponding deformation bone selecting ‘parent by bone’. Finally when playing an

    animation, hide the original collection that has your original mesh in it, and you will get a significant boost

    in performance. Pierrick Picaut explains this method better in this video-- Do this to optimize your rigs' performances in Blender 👀 - YouTube

  3. garden reporter

    @Thomas Larsson

    Finalize Armature with Optimize Drivers

    What is "Optimize Drivers"? I don't have any additional functions for "Finalize Armature".

    @Jasper29 Dude, the problem with daz figures is a ton of drivers. The method from the video will give some performance that was spent on calculating weights, but the calculations of 100500 drivers will not go anywhere.

    But this makes me think that I need to create a separate figure only with morphs of facial animations and a separate figure only with JCMs.
    And then redirect all the data of these two rigs using the "Copy Transform" constraint or drivers to the third rig.

    I also notice that the order of importing morphs is also important.
    If I import Units to an empty model first, after FACS, I get ~58 fps in the viewport. If FACS first, and then Units, then ~52fps. What could this be related to?

    I think it would be easier to disable driver groups (only face, only body). But I've read your opinion in other topics that everything is too confusing to figure it out.
    So what about such a strange setup of three rigs? The bottom line is that in theory I will be able to disable the drivers for rig with all morphs and rig with JCMs, animating sliders with rig in which only facial morphs.

  4. Jasper29

    @garden the driver situation is true, I was just putting something out there as a possible solution to increase at least some performance--the drivers are still driven by bones, and an armature still affects the main mesh. Creating separate figures for facial and JCMs would also be tedious, but it might give you the results your looking for. Unfortunately this is more of a Blender issue and I’m mot sure Diffeo as awesome as it is, will be able to do much about optimizing FPS too much

  5. garden reporter

    @Thomas Larsson There is no such option in the build (1.7.0.1414). I can't upgrade to the latest version of the addon until I complete my project.

    @Jasper29
    About removing the entire mesh except the head. This works, up to a certain number of morphs.
    My current setup works at 12fps and removing the mesh gives +1 fps.
    For example, an installation with fewer morphs gives 44fps and 66fps (+22fps).

    Here are some of my data (fps at the top is the whole mesh, fps at the bottom is only the head)

    Expressions and Visemes significantly reduce performance.

  6. Alessandro Padovani

    We discussed this a lot in #1428. With the actual implementation there seem to be no way to optimize or organize drivers.

    As Thomas says the best way is to load only the morphs you need.

    One important note. In general facs and face units are exclusive you either use one or the other. In daz studio G3 G8 work with face units and G81 G9 work with facs. So you don’t need to load both that’s what slows down performances.

    @Thomas Larsson May be we could add some info in easy import about genesis generations. That would help the user to select the needed options. And/or add default presets for G1 to G9 with the recommended options.

    Easy Import:

    • Convert to Widgets (G81)
    • Face Units (G3 G8)
    • Expressions (G3 G8)
    • Visemes (G3 G8)
    • FACS (G81 G9)
    • FACS Expressions (G81 G9)
    • FACS Details (G9)

  7. garden reporter

    @Alessandro Padovani

    So you don’t need to load both that’s what slows down performances.

    I am using G8.1 in Daz and Blender and I need both (FACS and Units). FACS doesn't have some sliders I need, and some animations work better in Units. G8.1 supports both variants in Daz and Diffeomorphic. I understand that the fewer morphs the higher the performance, but I NEED both.

  8. Alessandro Padovani

    No, G81 doesn’t get the G8 face units in daz studio, she gets facs instead. Then yes in blender you can load both face units and facs this way you can use both G8 and G81 face animations on the figure, but this doesn’t work in daz studio.

    If daz animations is what you’re concerned with, you can also bake the animation to bones, including facial animations, this way you don’t need the morphs.

    steps:

    1. in daz studio: edit > figure > bake to transforms
    2. save as pose preset, this includes facial animations
    3. import in blender

  9. garden reporter

    No, G81 doesn’t get the G8 face units in daz studio, she gets facs instead.

    By default, no, but I use this asset, which returns me all (or almost all) basic facial morphs from G8.

    In Diffeomorphic, Units also work. The Units and FACS expressions are DIFFERENT. So I need both. Some expressions look better in Units, and some in FACS, on a single character.

    I'm not interested in animation in daz.

  10. Thomas Larsson repo owner

    I have been working on a tool to optimize drivers. With a G8F character with extra everything (adjusters, hidden morphs, ERC morphs, units, expressions, visemes, facs, body morphs, jcms, flexions), it removed 2109 out of 2973 drivers. A facecap (FACS) animation that I imported went from 2.22 fps to 12.5 fps, so that is a nice improvement.

    There are still some glitches. Even if drivers for hidden morphs are removed the sliders are still in the UI. And the speedup will be less for old characters (older than a few days), since shapekey drivers will be evaluated several times. I will fix that next.

  11. Alessandro Padovani

    Commit f29de26.

    Checked on G8F with basic hair and dress, easy import with full features converted to rigify. Here she goes from 20 fps not optimized to 24 fps optimized. So I’m not sure if I miss something. I’m running a basic hardware ryzen 2200G which makes everything, not using the 1060 for the viewport.

    steps:

    1. easy import G8F with basic hair and clothing, full features, rigify.
    2. do some animation, both body and face
    3. check the fps, I get 20
    4. optimize drivers, this removes 626 out of 1230 drivers
    5. check the fps, I get 24

    I’m also not sure to understand correctly what it does. I mean I don’t use ERC in the global settings so that’s not a concern, but removing multipliers and hidden variables sounds scary, is that safe ?

  12. Thomas Larsson repo owner

    No, it is not. That’s why they are optional, and why the tooltip warns that it can change how drivers work.

  13. Alessandro Padovani

    I’m confused. Tried without remove options and it still deletes the same 626 out of 1230 drivers so there’s no difference. What drivers are deleted and is it safe to delete drivers ? If yes then why aren’t they deleted automatically after easy import ?

  14. Thomas Larsson repo owner

    Consider an example. The armature property eCTRLBrowInnerUp-Down(fin) is driven by the object property eCTRLBrowInnerUp-Down.

    We can therefore remove the driver for eCTRLBrowInnerUp-Down(fin), provided that we replace the final armature property with the raw object property in other drivers, like eCTRLBrowInnerUp-DownL(fin).

    However, we can not remove the driver for eCTRLBrowInnerUp-DownL(fin), because it depends on three properties. After optimization, some drivers for the brow have been removed:

  15. Thomas Larsson repo owner

    Another example. Before optimization a jcm shapekey is driven by an armature property, which in turn is driven by a bone rotation.

    After optimization the shapekey is driven by the bone rotation directly, and the armature driver is removed (the armature property should be removed too, but not sure if that happens yet).

    To avoid recalculating the driver, the corresponding shapekeys for clothes are now driven by the body shapekey.

  16. Alessandro Padovani

    Thank you for the explanation. If I understand correctly it is always safe to delete drivers with the optimization tool. It looks like we can also use it multiple times if we add more morphs, but it’s probably safer to just “finalize” one time, so it is not automatic but left as a manual step when the user is ready for that.

    Thank you Thomas for this incredible work you did on optimization. This makes what I call “the daz morphs hell“ less “hell“ and more blender friendly. If Garden has nothing to add we may mark as resolved then.

  17. Thomas Larsson repo owner

    It is not always safe to remove multipliers, which is why I disabled that option by default. Let us consider an example

    Import morphs with the global settings Adjust Strength = All and Make Hidden Sliders enabled. The armature property pJCMThighFwd_57_L(fin) drives the shapekey pJCMThighFwd_57_L with the expression

    M*N*(u+clamp((1 if A< -0.995 else -1.005*A if A< 0  else 0),0,1))
    

    where

    u = pJCMThighFwd_57_L (a hidden slider)
    M = Adjust JCMs(fin) (an adjuster)
    N = JCMs On(fin) (multiplier defined by DS)
    A = lThighBend rotation
    

    After optimization the multipliers M and N and the hidden slider u are removed. Then the driver for the armature property is also removed, and the shapekey is simply driven by

    clamp((1 if A< -0.995 else -1.005*A if A< 0  else 0),0,1)
    

    Some things will stop working after this optimization. The jcm shapekey can no longer be modified by a slider, nor can the overall strength be adjusted. An is we for some reason has set JCMs On = off in DS, the jcms will still be active (although normally the problem is the opposite, that jcms don’t work because somehow JCMs On is disabled accidentally).

    So some flexibility is lost after optimization, especially if multipliers are removed.

  18. Thomas Larsson repo owner

    And just a warning to everyone. The optimization tool is experimental. Make a backup of you blend file first before trying it.

  19. garden reporter

    Do I understand correctly that this function only works for characters that have not yet been converted to MHX or Rigify?
    Because it doesn't work for me on a character with MHX.

    On a new character, with morphs Units, FACS, JCMs, Flexions: 44 fps -> 59 fps. Not bad.
    With all standard morphs: 10fps -> 20fps.

  20. Thomas Larsson repo owner

    It works for me with mhx characters, both with a freshly generated one and one that is half a year old. But it may depend on the mhx version and which features were included. Are there any errors in the terminal window?

  21. Thomas Larsson repo owner

    I noticed a funny thing with the UI after optimization. If the global setting Show Final Morph Values is enabled, both the raw and final values are displayed. However, after optimization only some final values are shown, because the others have been optimized away. E.g. the final value for Brow Inner Up-Down has been removed, but the left and right versions retain their final values.

  22. garden reporter

    @Thomas Larsson

    Now, I get another crash. The model is slightly modified. It has an additional mesh and several shapekeys drivers. Maybe that's the problem?

  23. Thomas Larsson repo owner

    Second crash fixed. It was triggered by a mesh with shapekeys but no shapekey drivers.

  24. Thomas Larsson repo owner

    Beware that optimization seems to kill more drivers than it should, especially facs morphs that affect the jaw. This tool is not stable, don’t use it in production.

  25. garden reporter

    Beware that optimization seems to kill more drivers than it should, especially facs morphs that affect the jaw. This tool is not stable, don’t use it in production.

    I checked it now, and it is. Eye Blink morphs also work incorrectly. These are morphs in which both bones and shapekeys are involved.

    I understand correctly that the optimization function only works with morphs that have only one option (only bone management or only shapekey management). Morphs in which both bones and shapekeys are involved are optimized incorrectly (bone management is removed).

  26. Thomas Larsson repo owner

    Now I think that all necessary drivers are kept. Unfortunately, optimization is most effective when there are few drivers and performance may be okey anyway. The tool uses some shortcuts which are not possible if there are many drivers.

  27. garden reporter

    I checked, like morphs work correctly. Is it safe now?

    Earlier in this message, incorrect information was written.
    Okay, driver references to Custom Properties do not affect performance. I just checked it, manually copy-paste all drivers from Custom Properties (JCMs) directly into shapekeys. And there is no increase at all.

  28. Davi

    +1 for every optimization. We have a old character and we used the optimize driver button and went from very unresponsive, 1 second select of a controller, 4fps movement to responsive 8fps.

  29. Thomas Larsson repo owner

    The “WARNING:” line has annoyed me for a while, so now I removed it from the message box.

  30. garden reporter

    Maybe this data will be of interest to someone to understand which morphs most affect performance. And how much you can gain from driver optimization.

    G8 - 102fps
    G8+Face Units - 98fps
    G8+Face Units (optimized) - 98fps
    G8+FACS - 83fps
    G8+FACS (optimized) - 90fps
    G8+Face Units + FACS - 58fps
    G8+Face Units + FACS (optimized) - 74fps
    G8+FACS + Face Units - 47fps
    G8+FACS + Face Units (optimized) - 70fps
    G8+JCMs - 73fps
    G8+JCMs (optimized) - 73fps
    G8+JCMs (mute all) - 95fps
    G8+JCMs + Mute Drivers - 90fps
    G8+Flections - 92fps
    G8+Flections (optimized) - 92fps
    G8+Flections (mute all) - 96fps
    G8+JCMs + Flections - 66fps
    G8+JCMs + Flections (optimized) - 66fps
    G8+JCMs + Flections (mute all) - 91fps
    G8+Flections + JCMs - 67fps
    G8+Flections + JCMs (optimized) - 66fps
    G8+Flections + JCMs (mute all) - 91fps

  31. Alessandro Padovani

    To comment the data above.

    We see that worst performances come from face units + facs, so again don’t use them together, also because it makes little sense since facs are meant to replace face units, not to work together. As for jcms we can optimize by not importing unneeded ones, for example we most likely don’t need jcms for the fingers and they’re a lot.

    Please consider that in blender each shapekey takes the whole object geometry, so the mesh density is very relevant. For example if we can separate the head from the body that will count a lot because head shapekeys will only need the head geometry. Same separating teeth and eyes if we have teeth morphs for example. The more we separate the geometry in different objects the better it is for shapekeys, of course for what is possible with the figure.

  32. garden reporter

    Yes, Face Units + FACS slow down the character a lot. Loss of 44 fps or 28 fps (optimized).

    At the same time, Face Units has excellent performance, losing only 4 fps.
    FACS are much heavier, because they require a larger number of drivers, but they support FaceCap and look more developed (e.g. eyes).

    The import order also affects performance, if you import FACS first, then performance will be reduced more.

  33. Log in to comment