为什么 SCNLight 会在 SCNScene 中自动创建? (场景套件)

Why SCNLight created automatically in SCNScene? (SceneKit)

这是我发现的一种奇怪的现象。有一个很简单的例子,我有一个空的ARSCNView,只有根节点和摄像头,所以这意味着摄像头是打开的,但是屏幕上什么也没有(只有摄像头)。

我从 viewDidLoad() { printAllScene(node: scnView.scene.rootNode) } 调用了一个方法来打印场景中的所有节点

    private func printAllScene(node: SCNNode) {
        print("node: \(node), parent is: \(String(describing: node.parent))")
        
        for curNode in node.childNodes {
            printAllScene(node: curNode)
        }
    }

这个递归方法打印了场景中的所有节点,所以我在viewDidLoad()中调用它之后得到这样的输出

>>> 1
node: <SCNNode: 0x283313300 | 1 child>, parent is: nil
node: <SCNNode: 0x283318500 | camera=<SCNCamera: 0x1065261c0> | no child>, parent is: Optional(<SCNNode: 0x283313300 | 1 child>)
<<<

这里一切正常,但是在我从单击按钮调用相同的打印方法后,几秒钟后我得到另一个输出

>>> 3
node: <SCNNode: 0x283313300 | 3 children>, parent is: nil
node: <SCNNode: 0x283318500 pos(-0.002828 0.016848 0.034329) rot(0.229921 0.895326 -0.381477 0.336716) scale(1.000000 1.000000 1.000000) | camera=<SCNCamera: 0x1065261c0> | no child>, parent is: Optional(<SCNNode: 0x283313300 | 3 children>)
node: <SCNNode: 0x283336d00 | light=<SCNLight: 0x103973dd0 | type=probe> | no child>, parent is: Optional(<SCNNode: 0x283313300 | 3 children>)
node: <SCNNode: 0x283324800 pos(-0.007079 -0.074922 0.031407) rot(0.000000 -1.000000 0.000000 1.474911) | light=<SCNLight: 0x103985120 | type=probe> | no child>, parent is: Optional(<SCNNode: 0x283313300 | 3 children>)
<<<

它已经有3个children而不是一个,如何??然后再过几秒钟,我尝试再次单击并获得另一个输出

>>> 3
node: <SCNNode: 0x283313300 | 4 children>, parent is: nil
node: <SCNNode: 0x283318500 pos(0.000974 0.011970 0.039510) rot(0.231398 0.878019 -0.418974 0.304382) scale(1.000000 1.000000 1.000000) | camera=<SCNCamera: 0x1065261c0> | no child>, parent is: Optional(<SCNNode: 0x283313300 | 4 children>)
node: <SCNNode: 0x283336d00 | light=<SCNLight: 0x103973dd0 | type=probe> | no child>, parent is: Optional(<SCNNode: 0x283313300 | 4 children>)
node: <SCNNode: 0x283324800 pos(-0.007079 -0.074922 0.031407) rot(0.000000 -1.000000 0.000000 1.474911) | light=<SCNLight: 0x11aceec70 | type=probe> | no child>, parent is: Optional(<SCNNode: 0x283313300 | 4 children>)
node: <SCNNode: 0x28332ac00 pos(-0.007079 -0.074922 0.031407) rot(0.000000 -1.000000 0.000000 1.474911) | light=<SCNLight: 0x11b908130 | type=probe> | no child>, parent is: Optional(<SCNNode: 0x283313300 | 4 children>)
<<<

它有 4 个 children,有趣吧?

会不会跟配置有关?就像 ARKit 试图创建与真实光环境相关的光节点,以便在场景中模拟它或类似的东西?

UPD

感谢@mnuages,真的这个 属性 automaticallyUpdatesLighting 似乎非常接近正确的解决方案,我将它设置为 viewDidLoad 像这样 scnView.automaticallyUpdatesLighting = false,但是它对我的情况没有影响,我仍然看到轻节点正在添加。

UPD2

我当前的实现是-

...
override func viewWillAppear(_ animated: Bool) {
        let config = ARWorldTrackingConfiguration()
        config.environmentTexturing = .automatic
        scnView.session.run(config)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        scnView.scene = SCNScene()
        scnView.scene.lightingEnvironment.contents = .none
        scnView.scene.background.contents = .none
        scnView.automaticallyUpdatesLighting = false
        
        scnView.delegate = self
        scnView.showsStatistics = true
...

但问题仍然可以重现。

您是否在视图上设置了 automaticallyUpdatesLighting 属性?

来自documentation

If this value is true (the default), the view automatically creates one or more SCNLight objects, adds them to the scene, and updates their properties to reflect estimated lighting information from the camera scene. Set this value to false if you want to directly control all lighting in the SceneKit scene.

我认为你在谈论 SceneKit Procedural Sky。您可以使用以下命令将其关闭:

sceneView.scene?.lightingEnvironment.contents = .none      // Probe Light

sceneView.scene?.background.contents = .none               // Image

或者,您可以通过编程方式打开 skybox

sceneView.scene?.background.contents = MDLSkyCubeTexture(name: "heaven",
                                              channelEncoding: .float32,
                                            textureDimensions: vector_int2(512, 
                                                                           512),
                                                    turbidity: 0.12,
                                                 sunElevation: 1.00,
                                    upperAtmosphereScattering: 0.05,
                                                 groundAlbedo: 0.32)

sceneView.scene?.lightingEnvironment.contents = sceneView.scene?.background.contents

sceneView.scene?.lightingEnvironment.intensity = 1.5

P.S.

如果您正在使用 ship.scn 场景,您可能记得那里的 Procedural Sky 已打开。

最终问题出在ar配置上

ARKit automatically adds light probes when environment texturing is enabled. You can disable this behavior by setting the environmentTexturing property's value in your configuration to .none.