使用 MTLTexture 作为 SCNScene 的环境贴图

Using a MTLTexture as the environment map of a SCNScene

我想设置一个MTLTexture物体作为场景的环境贴图,根据documentation好像是可以的。我可以使用以下代码将环境贴图设置为 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 键设置为 every possible value 它可以获取,但这也不起作用.

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

使用 MTK 纹理照明 SCN 环境

在 macOS 12.3.1 上为 iOS 15.4 应用程序使用 Xcode 13.3.1。


诀窍是,环境照明需要立方体纹理,而不是平面图像。

  • 为 MetalKit 立方体纹理创建 6 个正方形图像

  • 在XcodeAssets文件夹中创建Cube Texture Set

  • 将纹理放置到相应的插槽中

  • 如果需要,水平和垂直镜像图像

粘贴代码:

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环境光照开启。

如果您需要程序化天空盒纹理 – 使用 class.

此外, 可能对您有用。