0

我用下面的代码创建了一个 3d 场景。

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>3d Model using HTML5 and three.js</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 {
                font-family: Monospace;
                background-color: #f0f0f0;
                margin: 0px;
                overflow: hidden;
            }
        </style>
    </head>
    <body>

        <script src="three.min.js" type="text/javascript"></script>
        <script src="Curve.js" type="text/javascript"></script>
        <script src="TubeGeometry.js" type="text/javascript"></script>      
        <script src="Stats.js" type="text/javascript"></script>
        <script src="Detector.js" type="text/javascript"></script>

        <script>
        // variables
        var container, stats;

        var camera, scene, renderer, splineCamera, cameraHelper, cameraEye;

        var text, plane, tube, tubeMesh, parent;

        var targetRotation = 0;
        var targetRotationOnMouseDown = 0;

        var mouseX = 0;
        var mouseXOnMouseDown = 0;

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

        var binormal = new THREE.Vector3();
        var normal = new THREE.Vector3();



        init();                     
        animate();

        function init(){

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

            // info div
            info = document.createElement( 'div' );
            info.style.position = 'absolute';
            info.style.top = '10px';
            info.style.width = '100%';
            info.style.textAlign = 'center';
            //info.innerHTML = 'Drag to spin the cylinder<br/> You can identify cylinder face by clicking on it.</br>';         
            container.appendChild( info );

            // camera
            camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );
            camera.position.set(30,10,10);
            //camera.up = new THREE.Vector3( 0, 1, 1 );

            // scene            
            scene = new THREE.Scene();
            camera.lookAt(scene.position);

            // light            
            scene.add( new THREE.AmbientLight( 0x404040 ) );
            light = new THREE.DirectionalLight( 0xffffff );
            light.position.set( 0, 1, 0 );
            scene.add( light );

            // CONTROLS
            controls = new THREE.TrackballControls( camera );

            // Grid
            geometry = new THREE.Geometry();
            geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) );
            geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) );

            for ( var i = 0; i <= 20; i ++ ) {

                line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
                line.position.z = ( i * 50 ) - 500;
                scene.add( line );

                line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
                line.position.x = ( i * 50 ) - 500;
                line.rotation.y = 90 * Math.PI / 180;
                scene.add( line );
            }

            // extrudePath, Helix Curve
            extrudePath = new THREE.SplineCurve3([
                                                new THREE.Vector3(0, 10, 10),
                                                new THREE.Vector3(10, 0, 10),
                                                new THREE.Vector3(10, 0, 0)
                                            ]);

            console.log(extrudePath);

            // Tube Geometry
            var segments = 50;
            var closed = false;
            var debug = true;
            var radiusSegments = 12;

            //alert('hello');                       
            var tube = new THREE.TubeGeometry(extrudePath, segments, 2, radiusSegments, closed, debug);

            // Tube Mesh
            tubeMesh = THREE.SceneUtils.createMultiMaterialObject( tube, [
                new THREE.MeshLambertMaterial({
                    color: 0xff00ff,
                    opacity: tube.debug ? 0.2 : 0.8,
                    transparent: true
                }),
                new THREE.MeshBasicMaterial({
                    color: 0x000000,
                    opacity: 0.5,
                    wireframe: true
            })]);

            parent = new THREE.Object3D();
            parent.position.y = 100;

            if ( tube.debug ) tubeMesh.add( tube.debug );
            //parent.add( tubeMesh );                   
            scene.add( tubeMesh );

            // projector
            projector = new THREE.Projector();

            // renderer
            //renderer = new THREE.CanvasRenderer();
            renderer = new THREE.WebGLRenderer( { antialias: true } ); 
            renderer.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer.domElement );               

            // stats
            stats = new Stats();
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.top = '0px';
            container.appendChild( stats.domElement );

            document.addEventListener( 'mousedown', onDocumentMouseDown, false );
            document.addEventListener( 'mouseover', onDocumentMouseOver, false );
            document.addEventListener( 'touchstart', onDocumentTouchStart, false );
            document.addEventListener( 'touchmove', onDocumentTouchMove, false );               

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

        }           

        function onWindowResize() {

            camera.left = window.innerWidth / - 2;
            camera.right = window.innerWidth / 2;
            camera.top = window.innerHeight / 2;
            camera.bottom = window.innerHeight / - 2;
            camera.aspect = window.innerWidth / window.innerHeight;
            //camera.updateProjectionMatrix();
            renderer.setSize( window.innerWidth, window.innerHeight );

        }

        function onDocumentMouseDown( event ) {
            event.preventDefault();

            document.addEventListener( 'mousemove', onDocumentMouseMove, false );
            document.addEventListener( 'mouseup', onDocumentMouseUp, false );
            document.addEventListener( 'mouseout', onDocumentMouseOut, false );

            mouseXOnMouseDown = event.clientX - windowHalfX;
            targetRotationOnMouseDown = targetRotation;         
        }

        function onDocumentMouseMove( event ) {

            mouseX = event.clientX - windowHalfX;

            targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;

        }

        function onDocumentMouseUp( event ) {

            document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
            document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
            document.removeEventListener( 'mouseout', onDocumentMouseOut, false );

        }

        function onDocumentMouseOut( event ) {

            document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
            document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
            document.removeEventListener( 'mouseout', onDocumentMouseOut, false );

        }

        function onDocumentMouseOver( event ) {

            document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
            document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
            document.removeEventListener( 'mouseout', onDocumentMouseOut, false );

        }

        function onDocumentTouchStart( event ) {

            if ( event.touches.length === 1 ) {

                event.preventDefault();

                mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
                targetRotationOnMouseDown = targetRotation;

            }

        }

        function onDocumentTouchMove( event ) {
            if ( event.touches.length === 1 ) {
                event.preventDefault();
                mouseX = event.touches[ 0 ].pageX - windowHalfX;
                targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
            }
        }

        function animate() {
            requestAnimationFrame( animate );
            render();
            update();
        }

        function update()
        {
            controls.update();
            stats.update();
        }

        function render() {             
            tubeMesh.rotation.y += ( targetRotation - tubeMesh.rotation.y ) * 0.15;         
            camera.updateMatrixWorld();
            renderer.render( scene, camera );
        }           

        </script>
    </body>
</html> 

现在,当我将渲染从 WebGL 更改为 Canvas 时,移动浏览器上的 FPS 从 56-57 FPS 下降到 1-2 FPS。本机浏览器在页面上不显示任何内容,并且在 Opera 页面中操作变得太慢。如何使用 Canvas 渲染快速进行页面操作,或者如何在移动浏览器上启用 webgl 渲染?

4

2 回答 2

2

画布渲染器仅是软件模式,这意味着没有 GPU 加速,CPU 必须完成所有艰苦的工作,这就是你的 fps 下降的原因。

AFAIK 并不是每个移动浏览器都能够使用 webgl 渲染器,你可以试试 opera mobile 它能够使用 webgl。

于 2012-09-18T14:17:19.867 回答
1

加快画布渲染的一种方法是减少 TubeGeometry 中使用的段数

于 2012-12-20T07:24:42.540 回答