如何在SceneKit中使用带Alpha通道的HEVC视频?

6

在2019年的WWDC开发者大会上,苹果宣布iOS现在支持HEVC带有Alpha通道,并表示这可以在SceneKit中使用。

我已经尝试了几个小时,但是没有成功。

我的目标是将视频作为SCNNode平面的纹理,并使该平面在视频透明部分也透明。

我使用了苹果在这个xcode项目(2个木偶的视频)中提供的带有HEVC Alpha通道的视频。

我正在使用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用作SCNNode材质的漫射+材质内容

这似乎是在SceneKit中显示视频作为材质的常见方法。此外,在苹果提供的关于如何渲染“带alpha的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: 断言失败 `Fragment Function(FastSingle_FragFunc): 缺少索引为0的sampler绑定,用于u_texture_sampler[0]。'

注意: 当我使用没有alpha通道的普通HEVC视频时,我不会收到此错误。

方法3. 使用材质着色器将alpha值从视频复制到材质的透明贴图中。

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相同的错误。

有人知道如何解决这个问题吗?

更新:2020年1月7日

我尝试了不同的方法,使用iOS 13.3和XCode 11.3。 => 相同的结果。

我刚刚向苹果报告了这个问题,感谢@mnuages提供的链接。

更新:2020年3月24日

iOS 13.4发布后,该问题得到了解决。

具有透明度的HEVC视频可以直接在SceneKit中处理,无需操纵材质的透明内容或使用着色器。


第一个片段在iOS 13.2.3上也存在相同的问题。像素是黑色而不是透明的。来自wwdc示例代码的相同视频(木偶)。 - ryancrunchi
1
问题似乎已经在iOS 13.4 beta中得到解决。 - mnuages
SKScene/SKVideoNode 崩溃似乎只会在场景中仅有视频的情况下出现。我在从苹果的示例代码中简单地删除桥梁背景图像后遇到了这个崩溃。 - Giles
将一个透明的精灵添加到场景中可以解决这个问题。 - Giles
你能解决这个问题吗?我在SceneKit中使用了相同的代码和相同的视频,采用了第二种方法(approach2),但是出现了你提到的相同崩溃情况。在iOS 14.8.1设备上进行了测试。 - ajith Kumark
1个回答

1

第一个代码片段应该可以正常工作(无需设置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版本。

这个问题似乎在iOS 13.4 beta版本中已经得到了修复。 - mnuages

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接