Opengl es SceneKit-交叉淡入淡出材质属性纹理

Opengl es SceneKit-交叉淡入淡出材质属性纹理,opengl-es,core-animation,scenekit,Opengl Es,Core Animation,Scenekit,的文档声明它是一个可设置动画的属性,实际上我可以在两种颜色之间执行交叉淡入淡出。但是,我无法在两幅图像之间进行交叉淡入淡出 所以我开始怀疑这是否可能,或者我是否需要为此创建一个自定义着色器 我尝试过隐式动画,在这种情况下,它会立即显示“after”图像: node.geometry.firstMaterial.diffuse.contents = [UIImage imageNamed:@"before"]; [SCNTransaction begin]; [SCNTransaction se

的文档声明它是一个可设置动画的属性,实际上我可以在两种颜色之间执行交叉淡入淡出。但是,我无法在两幅图像之间进行交叉淡入淡出

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


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

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 *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];

以及通过一个不起任何作用的
CALayer

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 *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中的一个bug(即,它的目的是可以设置动画,但不起作用),要么是苹果文档中的bug(即,它的目的不是可以设置动画,但他们说可以)。无论哪种方式,你都应该在苹果修复它时得到通知

(这看起来也不是tvOS特有的问题——我在OSX上也看到了这一点。)

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

我可以想出几个不错的潜在解决办法:

  • 使用着色器修改器。编写一个类似以下内容的GLSL(ish)代码段:

    uniform sampler2D otherTexture;
    uniform float fadeFactor;
    #pragma body
    vec4 otherTexel = texture2D(otherTexture, _surface.diffuseTexcoord);
    _surface.diffuse = mix(_surface.diffuse, otherTexel, fadeFactor);
    
    使用
    SCNShaderModifierEntryPointSurface
    入口点在要设置动画的材质上设置它。然后使用
    setValue:forKey:
    SCNMaterialProperty
    otherTexture
    关联,并使用
    CABasicAnimation
    fadeFactor
    从0设置为1

  • 使用更具动画效果的内容(如SpriteKit场景)作为材质属性内容,并设置动画以执行过渡。(作为奖励,当您这样做时,您可以使用其他过渡样式。)


  • 您的动画没有发生,因为“内容”属性只有在设置为“颜色”而不是“图像”时才可设置动画。您可以在苹果的内容属性文档中阅读。

    您是否尝试过在两种材质之间设置更改动画,而不是在同一材质属性的两个内容值之间设置更改动画?非常感谢,这非常有效!我以前曾尝试通过KVC绑定纹理,但我错误地直接指定了图像,而没有使用
    SCNMaterialProperty
    ,回想起来这似乎很愚蠢。我马上把雷达归档。你好@rickster,你能举个例子说明如何将CABasicAnimation应用于fadeFactor吗?我尝试了很多东西,但都不管用!!!请帮忙。ThanksI刚刚又看了一眼文档,但我找不到任何关于图像不适合制作动画的信息。从文档中:属性内容:指定接收者的内容。这可以是颜色(NSColor/UIColor)、图像(NSImage/CGImageRef)、层(CALayer)、路径(NSString或NSURL)、SpriteKit场景(SKScene)或纹理(SKTexture、id或GLKTextureInfo)。设置为颜色时可设置动画。嗯,即使我搜索“设置为颜色时可设置动画”,我也无法在此页面上找到它:。你在哪里看到的?我知道了。我不使用Xcode,所以我指的是我链接到的在线文档,奇怪的是它们会出现分歧。如果当前内容是纯色,则可以使用显式或隐式动画(请参见动画场景内容)更改为另一种颜色,创建在两种颜色之间淡入淡出的效果。使用动画从其他内容类型更改或更改为其他内容类型会导致纹理内容类型(或本身已设置动画的类型)之间的动画转换发生瞬时转换,请创建着色器修改器(请参见SCN可调整)。