Multiple SCNView audio error

247 views Asked by At

I'm working on a game that support both normal playing and VR using SceneKit. When playing normally I have a single SCNView, one camera which also corresponds to the view audio listener. When switching to VR mode I split the screen into two SCNView both playing the same scene from two different camera with the audio listener positioned between them, no problem here.

In my game I need positional audio so I use SCNAudioSuorce to play the sound effect using a SCNAction but since the same scene is playing in both view how can I mute one of them and have the audio only came from the other? I've searched the web and the documentation but found nothing about this.

iOS 11 Update: after testing my app on iOS 11 and trying to play a sound while in VR mode the app crashes on the rendering queue thread at __UpdateAudioTransform because I play that sound, removing it from the action (which includes other nodes transformations) makes the game run fine.

Update 1: Thanks to @rickster advice I tried implementing a SCNTechnique and following Apple documentation I got this

SCNTechnique(dictionary: [
    "passes" : [
        "leftView": [
            "draw": "DRAW_SCENE",
            "pointOfView": stereoCameraLeftName,
            "viewport": "(0, 0, 400, 400)"
        ],
        "rightView": [
            "draw": "DRAW_SCENE",
            "pointOfView": stereoCameraRightName,
            "viewport": "(200, 0, 400, 400)"
        ]
    ],
    "sequence": [ "leftView", "rightView" ]
    ])

where stereoCameraLeftName and stereoCameraRightName are defined elsewhere as strings and used as the names of the nodes containing the corresponding cameras and the viewports dimensions are just for testing. When I apply this technique to the scene it doesn't work and depending on how the scene pointOfView is set I either see the full scene filled with the background colour (pointOfView set to the camera used for non VR mode, no more linked to the scene graph) or the full size rendered using one of the two cameras (pointOfView set to nil), what am I missing?

Update 2: after some trail and error I found that the correct way to define a simple pass for a custom viewport is like this, with w and h defined as CGFloat:

let technique = SCNTechnique(dictionary: [
    "passes" : [
        "leftView": [
            "outputs": [ "color": "COLOR" ],
            "draw": "DRAW_SCENE",
            "colorStates": [
                "clear": true,
                "clearColor": "sceneBackground"
            ],
            "pointOfView": stereoCameraLeftName,
            "viewport": "0 0 \(w) \(h)"
        ],
        "rightView": [
            "outputs": [ "color": "COLOR" ],
            "draw": "DRAW_SCENE",
            "colorStates": [
                "clear": false
            ],
            "pointOfView": stereoCameraRightName,
            "viewport": "\(w) 0 \(w) \(h)",
            "blendStates": [
                "colorOp": "add",
                "alphaOp": "add"
            ]
        ]
    ],
    "sequence": [ "leftView", "rightView" ]
])

But there is a problem: when the second pass is rendered the left side of the screen remain black (clear colour) and the right side is rendered correctly, if I exclude this pass leaving only the first one the left side is correctly rendered and the right side appear with the scene background colour as expected. What's strange is that if instead of testing on my iPhone 6s running iOS 11 I test on a simulator (iOS 11) all seems to work fine, I'm sure I'm missing something in combining the two passes.

Update 2.1: removing blendStates from the second pass gives the same results.

Update 3: trying to recreate a MWE to recreate the problem I've found that my approach is correct, I'll try to investigate other parts of my projects to find where's the problem.

Final update: the problems seems to be caused by antialiasing being active on the view, disabling it make the SCNTechnique works fine, seems like a bug of iOS 11 and I've already filed a bug report.

1

There are 1 answers

9
rickster On BEST ANSWER

This is one of a number of issues with trying to render the same scene in multiple views. (Others include performance and concurrency.) Instead, it's probably a better choice to use only a single view, and use SCNTechnique to render the view's scene twice in it.

When you configure a technique, you can set the pointOfView separately for each draw pass — that'd probably be handy if you're looking for stereo separation.

You can also set the viewport for each pass. If you're doing some sort of stereo rendering, you'd use this to make one render pass cover one half of the view, and the other render pass cover the other half.