2016-12-26 11 views
1

私は*.DAEのキャラクターのファイルにそれぞれ45-70本のボーンを持っています 私は約100人のアニメーションキャラクターを画面に表示したいと思います。SceneKitリギッドキャラクターアニメーションパフォーマンスを向上

しかし、私は〜60文字を持っていると、アニメーションは非常に高価な私の更新ループの約13ミリ秒かかるので、他のタスクのためのほとんど余裕ができません。

私は0.2にfadeOutセットで前のアニメーションを削除し、同様に0.2にFadeInセットを使って、新しいアニメーションを追加していたアニメーションを交換したいとき、私はメッシュSCNNode にアニメーション「CAAnimationGroupを使う」を設定しています。それは悪いですか?以前のアニメーションを一時停止して新しいアニメーションを再生するだけでいいですか?それとももっと悪いですか?

SceneKitでリギングされた文字をアニメーション化するには、GPUなどを使用するのが良い方法はありますか?

私のアップデートループでアニメーションオーバーヘッドを減らすには、正しい方向に向かってください。

更新 バグレーダーを経由して、アップルを接触させた後、私は、電子メールを経由して、この問題を受けたが:

この問題は、今後のアップデートで修正される作業中です、我々は あなたが通りお知らせしますすぐに私たちがベータ版をビルドしたので、 この問題をテストして確認することができます。

ご理解いただきありがとうございます。

Appleのエンジニアがそれをどの程度強化するかを待ってみましょう:)。

答えて

2

頂点の影響が4未満の場合、SceneKitはGPUで骨格アニメーションを実行します。ドキュメントから、belowを再現:このジオメトリソースでcomponentsPerVector数が4以下である場合にのみ


SceneKitは、GPU上で、骨格アニメーションを実行します。ベクトルが大きくなると、CPUベースのアニメーションが生成され、レンダリングのパフォーマンスが大幅に低下します。


Iアニメーションが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にアニメーションに関する隠された情報が1つあります。これは、骨格が60以上のボーンを持つ場合、GPUで実行されないということです。無効なシェーダーモディファイアエントリをexplained in this postとしてアタッチして、デフォルトの頂点シェーダを印刷することです。

#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上で実行されているかどうかを確認することをおすすめします。さもなければ、あなたのキャラクタースケルトンを修正しなければならないかもしれません。

+0

まあ...私のキャラクターは9回の影響が2回以上あると言っています4 :-( 影響を減らす唯一の方法はありますか? – ColdSteel

+1

残念ながら、影響を減らす必要があります。たとえば、私はBlenderを使用しているような状況に直面し、重みを再配分するためのPythonスクリプトを作成しました:https://gist.github.com/ dmsurti/b502074eae2976d5e7a0e0829520132bだから、体重を再描画せずに、そのような演算子を適用し、アニメーションデータを再エクスポートするか、またはあなたが作業している3Dアーティストがあなたのためにそれを行うことができるはずです –

+0

私の3Dアーティストは3ds maxを使用し、彼のために多くの時間を取るために:-(あなたの答えは大変ありがとうございました。私は何とかして働かそうとします。 – ColdSteel

関連する問題