SceneKit - текстуры свойств материала Crossfade

Документация для 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];

2 ответа

Решение

Из моего собственного тестирования не похоже, что это свойство фактически анимируемо, когда задействованы значения текстуры (а не значения сплошного цвета). Либо это ошибка в SceneKit (т.е. она предназначена для анимации, но она не работает), либо это ошибка в документах Apple (т.е. она не предназначена для анимации, но они говорят, что это так). В любом случае вы должны зарегистрировать эту ошибку, чтобы получать уведомления, когда Apple исправит ее.

(Это также не похоже на то, что это проблема, связанная с TVOS- я вижу это и в 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 точка входа. Тогда используйте setValue:forKey: связать SCNMaterialProperty с otherTexture и CABasicAnimation оживить fadeFactor от 0 до 1.

  2. Используйте что-то более анимированное (например, сцену SpriteKit) в качестве содержимого свойства материала и анимируйте это для выполнения перехода. (В качестве бонуса, когда вы делаете это таким образом, вы можете использовать другие стили перехода.)

Ваша анимация не происходит, потому что свойство "содержимого" является анимируемым, только если для него задан цвет, а не изображение. Вы можете прочитать его в документации Apple по содержанию собственности.

Другие вопросы по тегам