簡體   English   中英

SceneKit Rigged Character Animation可提高性能

[英]SceneKit Rigged Character Animation increase performance

我有*.DAE文件,每個字符有45-70個骨頭,我想在屏幕上有大約100個動畫角色。

然而,當我有~60個字符時,動畫需要大約13毫秒的更新循環,這是非常昂貴的,並且讓我幾乎沒有其他任務的空間。

當我想要交換動畫時,我將動畫“CAAnimationGroup”設置為Mesh SCNNode我將fadeOut設置為0.2並刪除以前的動畫,並將FadeIn設置為0.2的新動畫添加。 - >不好嗎? 我應該暫停上一個動畫並播放一個新動畫嗎? 還是更糟?

是否有更好的方法可以使用GPU或其他東西在SceneKit為裝配好的角色制作動畫?

請讓我開始正確的方向,以減少更新循環中的動畫開銷。

通過Bug雷達聯系Apple后更新我通過電子郵件收到了此問題:

正在處理此問題以便在將來的更新中修復,我們會在測試版本生成后立即通知您,您可以測試並驗證此問題。

感謝您的耐心等待。

所以,讓我們等一下,看看Apple的工程師將在多大程度上提升它:)。

如果頂點的影響小於4,SceneKit會在GPU上執行骨架動畫。 來自文檔,轉載如下


僅當此幾何源中componentsPerVector計數為4或更小時,SceneKit才會在GPU上執行骨架動畫。 較大的矢量會導致基於CPU的動畫並大幅降低渲染性能。


我使用以下代碼來檢測動畫是否在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來完成。

但是,GPU上還有另外一條關於動畫的隱藏信息,即如果你的骨架有超過60個骨骼,它就不會在GPU上執行。 知道這一點的技巧是打印默認的頂點着色器,通過附加無效的着色器修改器條目,如本文所述

頂點着色器包含以下與蒙皮相關的代碼:

#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塊骨頭。

如果您的所有角色都具有相同的骨架,那么我建議您使用上述提示檢查動畫是在CPU還是GPU上執行。 否則,您可能必須修復角色骨架,每個頂點的骨骼少於60個,影響不超過4個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM