three.js vive 耳机中的等距柱状视频抖动

three.js equirectangular video shaking in vive headset

我在 three.js 球体上渲染了一个等距柱状视频,并在 VIVE 上测试了 Chromium WebVR 的性能。

我注意到当我在 VIVE 中环顾四周时,视频会震动。这让我感到头晕目眩。

如果我将视频替换为图像,振动就会停止。我测试不同的视频,每个视频都会振动。因此,当 three.js 尝试在球体上渲染这些视频时,可能会出现问题。

我也检查fps。大约是 85~90 fps。看起来不错。

(在此之前,我已经使用 WebVR Boilerplate 在移动设备上测试了相同的脚本,并在 Cardboard 中观看了视频,它工作正常。没有晃动和振动。fps 约为 50。)

在测试时,我无意中发现如果我在 three.js 示例 webvr_vive_sculp.html 中放置一个球体,振动会减少。 fps 也减少到 50~60。如果我在原始脚本中限制 fps,则没有任何改变。

有人遇到过这个问题吗?

这是我的脚本:

<!DOCTYPE html>
<html lang="en">
    <head>
    <title>360 video in vive</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <style>

        body {

        background-color: #000000;
        margin: 0px;
        overflow: hidden;
        }

        #info {
            position: absolute;
            top: 0px; width: 100%;
            color: #ffffff;
            padding: 5px;
            font-family:Monospace;
            font-size:13px;
            font-weight: bold;
            text-align:center;
        }

        a {
            color: #ffffff;
        }
    </style>
</head>
<body>

    <div id="container"></div>


    <script src="../build/three.js"></script>
    <script src="js/controls/VRControls.js"></script>
    <script src="js/effects/VREffect.js"></script>
    <script src="js/vr/ViveController.js"></script>
    <script src="js/vr/WebVR.js"></script>


    <script>
        if ( WEBVR.isAvailable() === false ) {

            document.body.appendChild( WEBVR.getMessage() );

        }


        var camera, scene, renderer;
        var effect, controls;
        var video;

        init();
        animate();

        function init() {

            var container, mesh;

            container = document.getElementById( 'container' );


            camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 );
            camera.target = new THREE.Vector3( 0, 0, 0 );

            controls = new THREE.VRControls( camera );
            controls.standing = true;

            scene = new THREE.Scene();

            // 360 video
            video      = document.createElement('video');
            video.autoplay = true;
            video.src    = 'video/8Kevil_3840x1920_hq.webm'; // 'video/Danger in the Room.webm' // 8Kevil_3840x1920_hq
            video.crossOrigin = '';
            videoTexture = new THREE.Texture(video);
            videoTexture.minFilter = THREE.LinearFilter;
            videoTexture.magFilter = THREE.LinearFilter;
            videoTexture.format = THREE.RGBFormat;

            // 360 video sphere   
            var cubeGeometry = new THREE.SphereGeometry(500, 60, 40);
            var sphereMat = new THREE.MeshBasicMaterial({map: videoTexture});
            sphereMat.side = THREE.BackSide;
            var cube = new THREE.Mesh(cubeGeometry, sphereMat);
            scene.add(cube);

            renderer = new THREE.WebGLRenderer();
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );



            effect = new THREE.VREffect( renderer );
            if ( WEBVR.isAvailable() === true ) {

                document.body.appendChild( WEBVR.getButton( effect ) );

            }
            window.addEventListener( 'resize', onWindowResize, false );

        }

        function onWindowResize() {

            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            renderer.setSize( window.innerWidth, window.innerHeight );

        }

        function animate() {

            effect.requestAnimationFrame( animate );
            update();

        }

        function update() {
            if( video.readyState === video.HAVE_ENOUGH_DATA ){
                videoTexture.needsUpdate = true;
            }

            controls.update();
            effect.render( scene, camera );

        }

    </script>
</body>


WebVr 目前不能很好地处理视频纹理,如果您暂停视频,闪烁就会停止吗?

您可以试用 Firefox nightly,它可以更好地处理视频纹理,并且通常具有较低的延迟。

您可以通过在体验过程中打开 vive 菜单并摇头来对其进行测试,在 Chrome 中您会注意到 Vive 的原生菜单性能与您在昏暗背景中的体验之间存在更多延迟。

尝试使用videoTexture.minFilter = THREE.NearestFilter;videoTexture.maxFilter = THREE.NearestFilter;

对于球体使用 new THREE.SphereGeometry(500, 720, 4); 我知道它看起来很奇怪,但这样你会在球体的 top/bottom 上得到更平滑的缝合。