SceneKit Rigged Character Animation增加性能

我有*.DAE文件,每个字符有45-70个骨头,我想在屏幕上有大约100个animationangular色。

但是当我有60个人物的时候,animation需要13ms的更新循环,这个代价非常昂贵,并且让我几乎没有其他任务的余地。

当我想要交换animation时,我将animation“CAAnimationGroup”设置为网格SCNNode 。我将fadeOut设置为0.2并添加新的FadeIn设置为0.2的animation,以删除以前的animation。 – >这不好吗? 我应该暂停一个以前的animation,并播放一个新的? 还是更糟?

有没有更好的方法来animation在SceneKit操纵angular色可能使用GPU或其他?

请让我开始正确的方向,以减less更新循环中的animation开销。

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

这个问题正在努力修复在未来的更新,我们会让你知道,只要我们有一个testing版本,你可以testing和validation这个问题。

感谢您的耐心等待。

所以让我们拭目以待苹果工程师将会加强它:)

如果您的顶点的影响小于4,则SceneKit会在GPU上执行骨架animation。 来自文档,转载如下 :


只有在此几何源中componentsPerVector数为4或更less时, SceneKit才会在GPU上执行骨骼animation。 较大的向量导致基于CPU的animation并大大降低渲染性能。


我已经使用下面的代码来检测animation是否在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和附加了SCNScene的节点名来检查animation是在GPU还是CPU上完成的。

然而,在GPU上还有另外一个关于animation的隐藏信息,那就是如果你的骨骼有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块骨头。

如果你的所有angular色都具有相同的骨架,那么我build议只使用上面的提示来检查animation是在CPU还是GPU上执行的。 否则,你可能不得不修复你的angular色骨架,每个顶点的骨骼less于60个,影响不超过4个。