将MTLTexture用作SCNScene的环境贴图

31

我想将一个MTLTexture对象设置为场景的环境贴图,因为根据文档,这似乎是可能的。我可以使用以下代码将环境贴图设置为UIImage

let roomImage = UIImage(named: "room")
scene.lightingEnvironment.contents = roomImage

这样做是有效的,我可以看到我的金属物体上反射出图像。我尝试将图像转换为 MTLTexture 并使用以下代码将其设置为环境贴图:

let roomImage = UIImage(named: "room")
let loader = MTKTextureLoader(device: MTLCreateSystemDefaultDevice()!)
let envMap = try? loader.newTexture(cgImage: (roomImage?.cgImage)!, options: nil)
scene.lightingEnvironment.contents = envMap

然而,这并不起作用,我最终得到了一个没有对象反射的空环境贴图。

另外,我尝试将options设置为nil,而是尝试使用MTKTextureLoader.Option.textureUsage关键字和它可能获得的每个可能的值,但这也没有起作用。

编辑:您可以查看存储库中的示例项目,并使用它来重现此用例。


我相信这是一个被支持的使用案例。你的图片尺寸是多少?它是什么格式(我假设是PNG)?在加载完成后,envMap是否包含非nil值?如果你在加载行之后设置断点,能否在Xcode中快速查看它(可视化检查其内容)? - warrenm
1
@warrenm 这张图片是一个1024x512的PNG文件。envMap似乎已经成功创建,快速查看显示与roomImage相同的图像。 - halileohalilei
3
提交漏洞报告的时间到了。请访问http://bugreport.apple.com提交漏洞报告。 - warrenm
发布了一个可行的解决方案。 - Andy Jazz
1
@AndyJazz,我已经放弃了这个项目和平台很长时间了,所以我会相信你的话并接受你的答案,因为你似乎提供了一个非常详细的解决方案。感谢你的努力! - halileohalilei
嗨@halileohalilei,回答一个获得31个赞的问题永远不会太晚。))) - Andy Jazz
1个回答

2
使用 Xcode 13.3.1 在 macOS 12.3.1 上为 iOS 15.4 应用程序使用 MTK 纹理照明 SCN 环境。


译文:技巧是,环境光照需要一个立方体纹理,而不是一个平面图像。
  • 为MetalKit立方体纹理创建6个正方形图像

enter image description here

在 Xcode 的“资产(Assets)”文件夹中创建立方体纹理集。

enter image description here

将纹理放置到它们对应的插槽中。

enter image description here

水平和垂直镜像,如果需要的话。

enter image description here

粘贴代码:
import ARKit
import MetalKit

class ViewController: UIViewController {

    @IBOutlet var sceneView: ARSCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()    
        let scene = SCNScene()
        
        let imageName = "CubeTextureSet"
        let textureLoader = MTKTextureLoader(device: sceneView.device!)

        let environmentMap = try! textureLoader.newTexture(name: imageName, 
                                                    scaleFactor: 2, 
                                                         bundle: .main, 
                                                        options: nil)
        
        let daeScene = SCNScene(named: "art.scnassets/testCube.dae")!

        let model = daeScene.rootNode.childNode(withName: "polyCube", 
                                             recursively: true)!
        
        scene.lightingEnvironment.contents = environmentMap
        scene.lightingEnvironment.intensity = 2.5
        scene.background.contents = environmentMap

        sceneView.scene = scene
        sceneView.allowsCameraControl = true
        scene.rootNode.addChildNode(model)
    }
}

将金属材料应用于模型。现在MTL环境照明已开启。

enter image description here

如果您需要过程化的天空盒纹理,请使用MDLSkyCubeTexture类。
此外,这篇帖子可能对您有用。

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