SceneKit索具角色动画可提高性能 [英] SceneKit Rigged Character Animation increase performance

查看:91
本文介绍了SceneKit索具角色动画可提高性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有*.DAE个文件,每个字符有45-70根骨头, 我想在屏幕上显示大约100个动画角色.

I have *.DAE files for characters each has 45-70 bones, I want to have about 100 animated characters on the screen.

但是,当我拥有约60个字符时,动画花费了约13ms的更新循环,这是非常昂贵的,并且几乎没有其他任务的余地.

However when I have ~60 Characters the animations takes ~13ms of my update loop which is very costly, and leaves me almost no room for other tasks.

我正在将动画"CAAnimationGroup"设置为网格SCNNode 当我想交换动画时,我要删除以前的fadeOut设置为0.2的动画,并添加新的FadeIn设置为0.2的动画. ->不好吗?我应该暂停上一个动画然后播放一个新的动画吗?还是更糟?

I am setting the animations "CAAnimationGroup" to the Mesh SCNNode when I want to swap animations I am removing the previous animations with fadeOut set to 0.2 and adding the new Animation with FadeIn set to 0.2 as well. -> Is it bad ? Should I just pause a previous animation and play a new one ? or is it even worse?

是否有更好的方法可以使用GPU或其他方式为SceneKit中的绑定角色设置动画?

Is there better ways to animate rigged characters in SceneKit maybe using GPU or something ?

请让我朝正确的方向开始,以减少更新循环中的动画开销.

Please get me started to the right direction to decrease the animations overhead in my update loop.

更新 通过Bug雷达与Apple联系后,我通过电子邮件收到了此问题:

Update After Contacting Apple via Bug radar I received this issue via E-Mail:

此问题正在处理中,将在以后的更新中修复,我们将 让我们知道,一旦我们有一个beta版本,您就可以测试和验证 这个问题.

This issue is being worked on to be fixed in a future update, we will let you know as soon as we have a beta build you can test and verify this issue.

感谢您的耐心等候.

因此,让我们拭目以待,看看苹果的工程师们会在多大程度上增强它:).

So lets wait and see how far Apple's Engineers will enhance it :).

推荐答案

如果顶点的影响小于4,SceneKit会在GPU上进行骨骼动画处理.从文档中复制了:

SceneKit does the skeletal animation on the GPU if your vertices have less than 4 influences. From the docs, reproduced below:

仅当此几何图形源中的 componentsPerVector计数为4以下时,SceneKit才会在GPU上执行骨骼动画.较大的向量会导致基于CPU的动画并大大降低渲染性能.

SceneKit performs skeletal animation on the GPU only if the componentsPerVector count in this geometry source is 4 or less. Larger vectors result in CPU-based animation and drastically reduced rendering performance.

我已经使用以下代码来检测动画是否在GPU上完成:

I have used the following code to detect if the animation is done on the GPU:

- (void)checkGPUSkinningForInScene:(SCNScene*)character
                          forNodes:(NSArray*)skinnedNodes {
  for (NSString* nodeName in skinnedNodes) {
    SCNNode* skinnedNode =
        [character.rootNode childNodeWithName:nodeName recursively:YES];
    SCNSkinner* skinner = skinnedNode.skinner;
    NSLog(@"******** Skinner for node %@ is %@ with skeleton: %@",
          skinnedNode.name, skinner, skinner.skeleton);
    if (skinner) {
      SCNGeometrySource* boneIndices = skinner.boneIndices;
      SCNGeometrySource* boneWeights = skinner.boneWeights;
      NSInteger influences = boneWeights.componentsPerVector;
      if (influences <= 4) {
        NSLog(@" This node %@ with %lu influences is skinned on the GPU",
              skinnedNode.name, influences);
      } else {
        NSLog(@" This node %@ with %lu influences is skinned on the CPU",
              skinnedNode.name, influences);
      }
    }
  }
}

您传递SCNScene和附加了SCNSkinner的节点名称,以检查动画是在GPU还是CPU上完成的.

You pass the SCNScene and the names of nodes which have SCNSkinner attached to check if the animation is done on the GPU or the CPU.

但是,GPU上还有其他一些有关动画的隐藏信息,那就是如果您的骨骼上有60多个骨骼,则不会在GPU上执行.要知道的诀窍是通过将无效的着色器修改器条目附加为在此帖子中进行了解释.

However, there is one other hidden piece of information about animation on the GPU which is that if your skeleton has more than 60 bones, it won't be executed on the GPU. The trick to know that is to print the default vertex shader, by attaching an invalid shader modifier entry as explained in this post.

顶点着色器包含以下与蒙皮相关的代码:

The vertex shader contains the following skinning related code:

#ifdef USE_SKINNING
uniform vec4 u_skinningJointMatrices[60];

....

    #ifdef USE_SKINNING
  {
    vec3 pos = vec3(0.);
    #ifdef USE_NORMAL
    vec3 nrm = vec3(0.);
    #endif
  #if defined(USE_TANGENT) || defined(USE_BITANGENT)
    vec3 tgt = vec3(0.);
    #endif
    for (int i = 0; i < MAX_BONE_INFLUENCES; ++i) {
#if MAX_BONE_INFLUENCES == 1
        float weight = 1.0;
#else
        float weight = a_skinningWeights[i];
#endif
      int idx = int(a_skinningJoints[i]) * 3;
      mat4 jointMatrix = mat4(u_skinningJointMatrices[idx], u_skinningJointMatrices[idx+1], u_skinningJointMatrices[idx+2], vec4(0., 0., 0., 1.));
            pos += (_geometry.position * jointMatrix).xyz * weight;
      #ifdef USE_NORMAL
            nrm += _geometry.normal * mat3(jointMatrix) * weight;
      #endif
      #if defined(USE_TANGENT) || defined(USE_BITANGENT)
            tgt += _geometry.tangent.xyz * mat3(jointMatrix) * weight;
      #endif
    }
    _geometry.position.xyz = pos;

这显然意味着您的骨骼应限制为60块骨头.

which clearly implies that your skeleton should be restricted to 60 bones.

如果所有角色都具有相同的骨架,那么我建议您使用以上技巧检查动画是在CPU还是GPU上执行的.否则,您可能必须将角色骨骼固定为骨骼少于60个,每个顶点的影响不超过4个.

If all your characters have the same skeleton, then I would suggest just check if the animation is executed on CPU or GPU using the above tips. Otherwise you may have to fix your character skeleton to have less than 60 bones and not more than 4 influences per vertex.

这篇关于SceneKit索具角色动画可提高性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆