ThreeJS WebXR 在 second/third/nth 次重新进入 VR 时修改相机属性

ThreeJS WebXR modifies camera properties on re-entering VR the second/third/nth time

我在使用 WebXR 时遇到了非常奇怪的体验 API。当我重新进入 VR 时,WebXR API 更改了 VR 相机属性。当我第二次、第三次或第 n 次重新进入 VR 模式时,相机以某种方式剪切了我的对象(如下所示)。

第一次进入VR时一直正常(如下图)

我想知道为什么对象在 second/third/nth VR 尝试中被剪切以及如何调试 WebXR 沉浸式虚拟现实相机属性。

我正在使用非常基本的 WebXR API 代码如下:

    window.onload=function()
{
    init();
    animate();
}

function init()
{   
    canvas = document.getElementById( 'vw_canvas' );
    canvas.width  = canvas.clientWidth;
    canvas.height = canvas.clientHeight;
    canvasCssWidth = canvas.style.width;
    canvasCssHeight = canvas.style.height;
    group = new THREE.Object3D();//we create this to make it a parent of camera object.
    camera = new THREE.PerspectiveCamera( 75, canvas.width / canvas.height, 1, 10000 );
    group.rotation.order = 'XZY';//default is XYZ..we change this to XZY. because in case of XYZ when we rotate the object around its Y axis even the X and Z axis changes. so to avoid that we give higher priority to Z axis.
    scene = new THREE.Scene();
    group.add(camera);
    scene.add(group);

    //add more 3D objects to scene

    renderer = new THREE.WebGLRenderer({antialias:true, powerPreference: "high-performance"});
    renderer.setPixelRatio( canvas.devicePixelRatio );
    renderer.setSize( canvas.width, canvas.height );
    renderer.xr.enabled = true;
    renderer.xr.setReferenceSpaceType( 'local' );
    canvas.appendChild(renderer.domElement);

    var WEBVR = 
    {
        createButton: function ( renderer ) 
        {
            function showEnterXR( /*device*/ ) {

                var currentSession = null;

                function onSessionStarted( session ) 
                {
                    session.addEventListener( 'end', onSessionEnded );
                    renderer.xr.setSession( session );
                    vrButton.style.backgroundImage="url('icons/noVR.svg')";
                    document.getElementById("vr-button-tooltip").setAttribute("tooltip","Exit VR");
                    currentSession = session;
                    isVRpresenting=true;
                    openVRMenu();
                }

                function onSessionEnded( event ) 
                {
                    currentSession.removeEventListener( 'end', onSessionEnded );
                    renderer.xr.setSession( null );
                    vrButton.style.backgroundImage="url('icons/yesVR.svg')";
                    document.getElementById("vr-button-tooltip").setAttribute("tooltip","Enter VR");
                    currentSession = null;
                    isVRpresenting=false;
                    closeVRMenu();
                }

                vrButton.style.backgroundImage="url('icons/yesVR.svg')";
                document.getElementById("vr-button-tooltip").setAttribute("tooltip","Enter VR");
                isVRpresenting=false;
                vrButton.onclick = function () 
                {
                    if (runOnlyOnce) 
                    {
                        makeVRMenuItems();
                        runOnlyOnce=false;
                    }
                    if ( currentSession === null ) 
                    {
                        var sessionInit = { optionalFeatures: [ 'local-floor', 'bounded-floor' ] };
                        navigator.xr.requestSession( 'immersive-vr', sessionInit ).then( onSessionStarted );
                    } 
                    else 
                    {
                        currentSession.end();
                    }
                };

            }

            function showVRNotFound() 
            {
                vrButton.onclick = function () 
                {
                    //open VR popup that shows devices to use in order to exp VR
                };
                isVRavailable=false;
                vrButton.style.backgroundImage="url('icons/noVR.svg')";
                document.getElementById("vr-button-tooltip").setAttribute("tooltip","VR is not supported on your device");
                vrButton.onclick = null;
                // renderer.xr.setDevice( null );
                isVRpresenting=false;
            }

            if ( 'xr' in navigator ) 
            {
                isVRavailable=true;

                navigator.xr.isSessionSupported( 'immersive-vr' ).then( function ( supported ) {
                    supported ? showEnterXR() : showVRNotFound();
                } );

            } 

            else 
            {
                vrButton.onclick = function () 
                {
                    //open VR popup that shows devices to use in order to exp VR
                };
                isVRavailable=false;
                vrButton.style.backgroundImage="url('icons/noVR.svg')";
                document.getElementById("vr-button-tooltip").setAttribute("tooltip","VR is not supported on you device");
                isVRpresenting=false;
            }
        },
    };
    WEBVR.createButton( renderer );
}

function animate() 
{
    renderer.setAnimationLoop( animate );
    update();
}
function update() 
{
    renderer.render( scene, camera );
}

好像是WebXR session 第一次进入VR 就取了场景相机参数。然后,在第二次和后续访问中,WebXR 会话将相机设置为默认设置。因此,为了将相机属性更新为与场景相机属性相同,我们需要使用此 session.updateRenderState({ depthFar: 10000 });。在我的情况下,我的场景相机具有 depthFar=10000 但 WebXR 相机重置 depthFar 属性 在 VR 中的第二次和后续访问中达到 1000,这是截锥体剔除的原因(有问题的图像)。