多次重绘场景后的性能降低,内存似乎没问题

时间:2013-04-26 07:32:08

标签: three.js webgl

我有一些不好的问题,在动态多次重绘场景后帧率大幅下降,我希望有人可以提供帮助。在之前的三个版本中,我注意到内存泄漏,这在实际版本中似乎很好。我不知道为什么如果内存保持正常和cpu也会降低性能。

我的应用程序是由ajax调用触发的,它在不同的div容器中绘制canvasas。通过在新容器中初始化webgl,旧容器将被清理。

基本功能类似于以下代码。如果你按下按钮让我说20次,你会看到帧率下降:

http://jsfiddle.net/crizzis/YuJj6/

<input type="button" value="activate rendering in Div1" onclick="init_webgl(1);"></input>
<div id="webgl_container_1" onclick="init_webgl(1);" style="top:0px; height:300px; border:1px solid blue"></div>    
<input type="button" value="activate rendering in Div2" onclick="init_webgl(2);"></input>
<div id="webgl_container_2" onclick="init_webgl(2);"style="top:500px;height:300px; border:1px solid red"></div> 
    <script type="text/javascript"> 
        var camera, fov=70, controls, scene, projector, renderer, container;
        var time=0;
        //init_webgl(1);

        function init_webgl(styleId) {  

            console.log('writing webgl canvas to div with style Id: webgl_container_'+styleId);

            if (scene!=null){
                destroyWebGl();
            }   

            container = document.getElementById('webgl_container_'+styleId);    

            scene = new THREE.Scene();

            camera = new THREE.PerspectiveCamera( fov, container.clientWidth / container.clientHeight, 1, 10000 );
            camera.setViewOffset( container.clientWidth, container.clientHeight, 0, 0, container.clientWidth, container.clientHeight );
            camera.position.z = 350;                
            scene.add(camera);              

            projector = new THREE.Projector();

            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setSize(container.clientWidth, container.clientHeight);

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

            parent = new THREE.Object3D();
            scene.add( parent );                        

            container.appendChild( renderer.domElement );

            console.log('webgl initialized');
            init_renderObjects();
        }            

        function init_renderObjects(){                  
            for (var x = 0; x < 400; x++){
                var cube = new THREE.Mesh( 
                 new THREE.CubeGeometry( 50, 50, 50 ),
                 new THREE.MeshPhongMaterial( { ambient: 0xffffff, color: 0xffffff, opacity: 0.58,specular: 0xffffff, shininess: 40, shading: THREE.SmoothShading,  transparent: true,  wireframe: false } )
                );      
                cube.position.x = 100*x;
                parent.add( cube );
            }                
            animate();
        }

        function animate() {
            requestAnimationFrame(animate);
            timedelta=Date.now()-time;
            time = Date.now();          

            var children = parent.children;
            for(var i = children.length-1;i>=0;i--){
                var child = children[i];
                child.rotation.y = child.rotation.y+timedelta*0.005;
            };              
            render();
        }           

        function render() {             
            if (renderer!=null)renderer.render( scene, camera );                
        }

        function destroyWebGl(){              
             console.log( "destroyWebGl");
             console.log( "before programs"+ renderer.info.memory.programs );
             console.log( "before geometries"+ renderer.info.memory.geometries );
             console.log( "before textures"+ renderer.info.memory.textures );            

            var children = parent.children;
            for(var i = children.length-1;i>=0;i--){
                var child = children[i];
                child.geometry.dispose();
                child.material.dispose();
                parent.remove(child);
            };  

            scene.remove(parent);
            //renderer.deallocateObject( parent );

            camera = null;
            controls= null; 
            scene=null;
            projector=null;  
            parent=null;                    

            container.removeChild( renderer.domElement );       
            container=null;

            console.log( "after programs:" + renderer.info.memory.programs );
            console.log( "after geometries" + renderer.info.memory.geometries );
            console.log( "after textures" + renderer.info.memory.textures );              

            renderer=null;
            console.log('finished destroy');
        }            
        </script> 

1 个答案:

答案 0 :(得分:0)

您的init_webgl函数调用animate(),这意味着动画循环不会被清除,每次按下按钮时都会重新初始化动画循环。点击20次后,您将运行20个动画循环。

您只需在程序开始时调用animate()一次,然后将其从按钮点击代码中删除。