Как использовать видео "HEVC с альфа-каналом" в SceneKit? - PullRequest
0 голосов
/ 06 ноября 2019

На WWDC 2019 Apple объявила, что теперь она обрабатывает HEVC с Alpha в iOS , и заявляет, что она может быть использована в SceneKit.

Я часами пыталсябез удачи.

Моя цель - использовать видео в качестве текстуры на плоскости SCNNode и сделать эту плоскость прозрачной там, где видео прозрачно.

Я использую HEVC с альфа-видео, предоставленным Apple в этом проекте xcode (видео с 2 марионетками).

Я работаю с XCode 11.2 на реальном устройстве с iOS 13.2.

Я пробовал разные подходы.

Подход 1. Использование AVPlayer в качестве диффузного + прозрачного содержимого моегоМатериал SCNNode

let videoURL = Bundle.main.url(forResource: “puppets_with_alpha_hevc“, withExtension: "mov", subdirectory: "Assets.scnassets");
let player = AVPlayer(url: videoURL! as URL)
let material = SCNMaterial()
material.diffuse.contents = player
material.transparent.contents = player
plane?.geometry?.materials = [material];
player.play();

Результат: видео воспроизводится с черными пикселями вместо прозрачных.

Подход 2. Вставьте AVPlayer в SKVideoNode, затем внедритеSKVideoNode в SKScene и используйте SKScene в качестве содержимого diffuse + для материала моего SCNNode

. Это, похоже, распространенный способ отображения видео в качестве материала в SceneKit. Кроме того, в примере, представленном Apple о том, как визуализировать «видео HEVC с альфа», они используют SKVideoNode (но не в контексте SceneKit).

let videoNode = SKVideoNode(avPlayer: player)
let spritescene = SKScene(size: CGSize(width: 360, height: 480))
let spriteKitScene = SKScene(size: CGSize(width: 360.0 / 2.0, height: 480.0 / 2.0))
spriteKitScene.scaleMode = .aspectFit
videoNode.position = CGPoint(x: spriteKitScene.size.width / 2.0, y: spriteKitScene.size.height / 2.0)
videoNode.size = spriteKitScene.size
spriteKitScene.addChild(videoNode)
let material = SCNMaterial()
material.diffuse.contents = spriteKitScene
material.transparent.contents = spriteKitScene
plane?.geometry?.materials = [material];

Результат: получить этот сбой:

validateFunctionArguments: 3577: сбой утверждения `Функция фрагмента (FastSingle_FragFunc): отсутствует привязка сэмплера по индексу 0 для u_texture_sampler [0]. '

Примечание: Я не получаю эту ошибку, когда использую обычное видео HEVC без альфа-канала.

Подход 3. Используйте шейдер материала, чтобы скопировать альфа-значения извидео на прозрачную карту материала.

let material = SCNMaterial()
material.diffuse.contents = player
material.shaderModifiers = [
    SCNShaderModifierEntryPoint.surface :  "_surface.transparent.a = _surface.diffuse.a;"
];
plane?.geometry?.materials = [material];

Результат: видео отображается с черными пикселями вместо прозрачных. Альфа-информация, по-видимому, отсутствует в _surface.diffuse.a

Подход 4. Использование шейдера с SKScene вместо AVPlayer

Результат: та же ошибка, что и в подходе 2.

Кто-нибудь знает, как заставить это работать?

1 Ответ

0 голосов
/ 06 ноября 2019

Первый фрагмент кода должен работать (без необходимости установки свойства материала transparent). Если вы сделаете следующее изменение в игровом шаблоне macOS SceneKit, вы получите правильный результат, однако он не будет работать с игровым шаблоном iOS SceneKit.

// retrieve the ship node
let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!
let videoURL = Bundle.main.url(forResource: "puppets_with_alpha_hevc", withExtension: "mov", subdirectory: "art.scnassets");
let player = AVPlayer(url: videoURL! as URL)
let material = SCNMaterial()
material.diffuse.contents = player
player.play();
ship.enumerateHierarchy { (node, _) in
    if let geometry = node.geometry {
        geometry.materials = [material];
    }
}

В этом случае может потребоваться подайте ошибку для исправления версии iOS.

...