SceneKit - 交叉淡入淡出 material 属性 纹理

SceneKit - Crossfade material property textures

SCNMaterialProperty.contents 的文档指出它是可动画的 属性 并且我确实可以在两种颜色之间执行交叉淡入淡出。但是我无法在两个图像之间交叉淡入淡出。

所以我开始怀疑这是否可能,或者我是否需要为此创建一个自定义着色器?


我试过隐式动画,在这种情况下它会立即显示“后”图像:

node.geometry.firstMaterial.diffuse.contents = [UIImage imageNamed:@"before"];
[SCNTransaction begin];
[SCNTransaction setAnimationDuration:5];
node.geometry.firstMaterial.diffuse.contents = [UIImage imageNamed:@"after"];
[SCNTransaction commit];

显式动画,什么都不做:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"contents"];
animation.fromValue = (__bridge id)[UIImage imageNamed:@"before"].CGImage;
animation.toValue = (__bridge id)[UIImage imageNamed:@"after"].CGImage;
animation.duration = 5;
[node.geometry.firstMaterial.diffuse addAnimation:animation forKey:nil];

以及通过 CALayer,它什么都不做:

CALayer *textureLayer = [CALayer layer];
textureLayer.frame = CGRectMake(0, 0, 793, 1006);
textureLayer.contents = (__bridge id)[UIImage imageNamed:@"before"].CGImage;
node.geometry.firstMaterial.diffuse.contents = textureLayer;

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"contents"];
animation.fromValue = (__bridge id)[UIImage imageNamed:@"before"].CGImage;
animation.toValue = (__bridge id)[UIImage imageNamed:@"after"].CGImage;
animation.duration = 5;
[textureLayer addAnimation:animation forKey:nil];

根据我自己的测试,当涉及纹理值(而不是纯色值)时,看起来 属性 实际上不是可动画的。这要么是 SceneKit 中的错误(即,它旨在可动画化,但不起作用),要么是 Apple 文档中的错误(即,它不旨在可动画化,但他们说是)。无论哪种方式,您都应该 file that bug 以便在 Apple 修复它时收到通知。

(这看起来也不像是电视 OS 特有的问题——我在 OS X 上也看到了。)

我能理解为什么动画纹理过渡可能不存在...从 GL/Metal 的角度来看,这需要绑定一个额外的纹理单元并且在过渡期间每个像素有两个纹理查找(而不是一个) .

我可以想到几个不错的潜在解决方法:

  1. 使用着色器修改器。写一个看起来像这样的 GLSL(ish) 片段:

    uniform sampler2D otherTexture;
    uniform float fadeFactor;
    #pragma body
    vec4 otherTexel = texture2D(otherTexture, _surface.diffuseTexcoord);
    _surface.diffuse = mix(_surface.diffuse, otherTexel, fadeFactor);
    

    将其设置在要使用 SCNShaderModifierEntryPointSurface 入口点设置动画的 material 上。然后使用 setValue:forKey:SCNMaterialPropertyotherTexture 关联,并使用 CABasicAnimationfadeFactor 从 0 动画化到 1。

  2. 使用更具动画效果的内容(如 SpriteKit 场景)作为您的 material 属性 内容,并对其进行动画处理以执行过渡。 (作为奖励,当你这样做时,你可以使用其他过渡样式。)

您的动画没有发生,因为 "contents" 属性 只有在设置为非图像颜色时才可设置动画。您可以在苹果的文档中阅读有关内容 属性.