Three.js 未捕获的安全错误:无法在“WebGLRenderingContext”上执行“texImage2D”:

san*_*dav 5 three.js

这个问题源于之前html5视频在android手机上无法播放的问题。(Three.js WebGLRenderered 视频无法在 Android 手机上播放

正如 mrdoob 提到的,video.play() 在移动设备上应该通过用户发起的事件(例如单击)明确显示。完成此操作后,我就可以播放该文件了。但是我只能听到视频的音频部分。屏幕仍然一片空白。此外,我在开发控制台上看到以下异常。

未捕获的安全错误:无法在“WebGLRenderingContext”上执行“texImage2D”:视频元素包含跨源数据,并且可能无法加载。三分钟.js:507

我没有通过我的代码加载任何图像,正如您在下面的代码中看到的那样,错误似乎被抛出在 Three.min.js 文件中。(下面的代码是http:// Threejs.org/examples/#webgl_materials_video的稍微修改版本,以使其在移动设备上运行)

请注意,这仅发生在移动设备上。该示例在网络上完美运行。

非常感谢您的帮助!

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - materials - video</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: #000;
                color: #fff;
                margin: 0px;
                overflow: hidden;
                font-family:Monospace;
                font-size:13px;
                text-align:center;
                font-weight: bold;
                text-align:center;
            }

            a {
                color:#0078ff;
            }

            #info {
                color:#fff;
                position: absolute;
                top: 0px; width: 100%;
                padding: 5px;
                z-index:100;
            }

        </style>
    </head>
    <body>

        <div id="info">
            <a href="http://threejs.org" target="_blank">three.js</a> - webgl video demo. playing <a href="http://durian.blender.org/" target="_blank">sintel</a> trailer
        </div>

        <script src="js/three.min.js"></script>

        <script src="js/shaders/ConvolutionShader.js"></script>
        <script src="js/shaders/CopyShader.js"></script>

        <script src="js/postprocessing/EffectComposer.js"></script>
        <script src="js/postprocessing/RenderPass.js"></script>
        <script src="js/postprocessing/MaskPass.js"></script>
        <script src="js/postprocessing/BloomPass.js"></script>
        <script src="js/postprocessing/ShaderPass.js"></script>

        <script src="js/Detector.js"></script>

        <video id="video" autoplay loop style="display:none">
            <source src="textures/sintel.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
            <source src="textures/sintel.ogv" type='video/ogg; codecs="theora, vorbis"'>
        </video>

        <script>

            if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

            var container;

            var camera, scene, renderer, element;

            var video, texture, material, mesh;

            var composer;

            var mouseX = 0;
            var mouseY = 0;

            var windowHalfX = window.innerWidth / 2;
            var windowHalfY = window.innerHeight / 2;

            var cube_count,

                meshes = [],
                materials = [],

                xgrid = 20,
                ygrid = 10;

            init();
            animate();

            function init() {

                container = document.createElement( 'div' );
                document.body.appendChild( container );

                camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
                camera.position.z = 500;

                scene = new THREE.Scene();

                var light = new THREE.DirectionalLight( 0xffffff );
                light.position.set( 0.5, 1, 1 ).normalize();
                scene.add( light );

                renderer = new THREE.WebGLRenderer( { antialias: false } );
                renderer.setSize( window.innerWidth, window.innerHeight );

                element=renderer.domElement;
                element.addEventListener('click', fullscreen, false);

                container.appendChild( renderer.domElement );

                video = document.getElementById( 'video' );

                texture = new THREE.Texture( video );
                texture.minFilter = THREE.LinearFilter;
                texture.magFilter = THREE.LinearFilter;
                texture.format = THREE.RGBFormat;
                texture.generateMipmaps = false;

                //

                var i, j, ux, uy, ox, oy,
                    geometry,
                    xsize, ysize;

                ux = 1 / xgrid;
                uy = 1 / ygrid;

                xsize = 480 / xgrid;
                ysize = 204 / ygrid;

                var parameters = { color: 0xffffff, map: texture },
                    material_base = new THREE.MeshLambertMaterial( parameters );

                renderer.initMaterial( material_base, scene.__lights, scene.fog );

                cube_count = 0;

                for ( i = 0; i < xgrid; i ++ )
                for ( j = 0; j < ygrid; j ++ ) {

                    ox = i;
                    oy = j;

                    geometry = new THREE.BoxGeometry( xsize, ysize, xsize );

                    change_uvs( geometry, ux, uy, ox, oy );

                    materials[ cube_count ] = new THREE.MeshLambertMaterial( parameters );

                    material = materials[ cube_count ];

                    material.hue = i/xgrid;
                    material.saturation = 1 - j/ygrid;

                    material.color.setHSL( material.hue, material.saturation, 0.5 );

                    mesh = new THREE.Mesh( geometry, material );

                    mesh.position.x =   ( i - xgrid/2 ) * xsize;
                    mesh.position.y =   ( j - ygrid/2 ) * ysize;
                    mesh.position.z = 0;

                    mesh.scale.x = mesh.scale.y = mesh.scale.z = 1;

                    scene.add( mesh );

                    mesh.dx = 0.001 * ( 0.5 - Math.random() );
                    mesh.dy = 0.001 * ( 0.5 - Math.random() );

                    meshes[ cube_count ] = mesh;

                    cube_count += 1;

                }

                renderer.autoClear = false;

                document.addEventListener( 'mousemove', onDocumentMouseMove, false );

                // postprocessing

                var renderModel = new THREE.RenderPass( scene, camera );
                var effectBloom = new THREE.BloomPass( 1.3 );
                var effectCopy = new THREE.ShaderPass( THREE.CopyShader );

                effectCopy.renderToScreen = true;

                composer = new THREE.EffectComposer( renderer );

                composer.addPass( renderModel );
                composer.addPass( effectBloom );
                composer.addPass( effectCopy );

                //

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

            }
            function fullscreen() {

                video.play();
                console.log(video);
                  if (container.requestFullscreen) {
                    container.requestFullscreen();
                  } else if (container.msRequestFullscreen) {
                    container.msRequestFullscreen();
                  } else if (container.mozRequestFullScreen) {
                    container.mozRequestFullScreen();
                  } else if (container.webkitRequestFullscreen) {
                    container.webkitRequestFullscreen();
                  }
                }

            function onWindowResize() {

                windowHalfX = window.innerWidth / 2;
                windowHalfY = window.innerHeight / 2;

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

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

            }

            function change_uvs( geometry, unitx, unity, offsetx, offsety ) {

                var faceVertexUvs = geometry.faceVertexUvs[ 0 ];

                for ( var i = 0; i < faceVertexUvs.length; i ++ ) {

                    var uvs = faceVertexUvs[ i ];

                    for ( var j = 0; j < uvs.length; j ++ ) {

                        var uv = uvs[ j ];

                        uv.x = ( uv.x + offsetx ) * unitx;
                        uv.y = ( uv.y + offsety ) * unity;

                    }

                }

            }


            function onDocumentMouseMove(event) {

                mouseX = ( event.clientX - windowHalfX );
                mouseY = ( event.clientY - windowHalfY ) * 0.3;

            }

            //

            function animate() {

                requestAnimationFrame( animate );

                render();

            }

            var h, counter = 1;

            function render() {

                var time = Date.now() * 0.00005;

                camera.position.x += ( mouseX - camera.position.x ) * 0.05;
                camera.position.y += ( - mouseY - camera.position.y ) * 0.05;

                camera.lookAt( scene.position );

                if ( video.readyState === video.HAVE_ENOUGH_DATA ) {

                    if ( texture ) texture.needsUpdate = true;

                }

                for ( i = 0; i < cube_count; i ++ ) {

                    material = materials[ i ];

                    h = ( 360 * ( material.hue + time ) % 360 ) / 360;
                    material.color.setHSL( h, material.saturation, 0.5 );

                }

                if ( counter % 1000 > 200 ) {

                    for ( i = 0; i < cube_count; i ++ ) {

                        mesh = meshes[ i ];

                        mesh.rotation.x += 10 * mesh.dx;
                        mesh.rotation.y += 10 * mesh.dy;

                        mesh.position.x += 200 * mesh.dx;
                        mesh.position.y += 200 * mesh.dy;
                        mesh.position.z += 400 * mesh.dx;

                    }

                }

                if ( counter % 1000 === 0 ) {

                    for ( i = 0; i < cube_count; i ++ ) {

                        mesh = meshes[ i ];

                        mesh.dx *= -1;
                        mesh.dy *= -1;

                    }

                }

                counter ++;

                renderer.clear();
                composer.render();

            }


        </script>

    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

san*_*dav 8

正如这里所讨论的:https://code.google.com/p/chromium/issues/detail? id=173727 “video”属性应该有这样的设置:

video.setAttribute('crossorigin', 'anonymous');
Run Code Online (Sandbox Code Playgroud)

但仅此一点并不能解决问题。这必须在 .load() 和 .play() 之前设置。我在 .load() 之后遇到了这个,但它不起作用。所以这样做:

video.setAttribute('crossorigin', 'anonymous');
video.src = "video/test.m4v";
video.src = "video/test.mp4";
video.load(); // must call after setting/changing source
video.play();
Run Code Online (Sandbox Code Playgroud)

此解决方案适用于由于上述安全错误而无法在移动设备上播放的视频。


需要明确的是crossorigin,设置告诉浏览器向服务器请求使用视频的权限。服务器仍然必须授予该权限。如果服务器未授予权限设置,则该crossorigin属性将不允许您使用视频。