做项目的过程中,遇到了很多的卡顿问题,最后经由暮志未晚 https://www.wjceo.com/ 群内各个大佬的指点,明白释放缓存的重要性,在这里作为一篇小笔记记录在这里
1.删除场景中的物体时,记得同时调用dispose方法来清空显存占用
/** * 清空当前obj对象的缓存 * @param mesh mesh对象 * */ function clearCache(mesh) { let mesh ; mesh.geometry.dispose(); mesh.material.dispose(); }
上述方法中,需要传入一个参数,该参数可以是一个mesh对象,也可以是一个object3D对象及其子类,然后将其内部的geometry,material(若有texture对象也需要把texture清除)使用.dispose()方法,清空它们在显卡中的缓存
可以在chrome中,按下Shitft+Esc检测显卡缓存
简单的小示例代码,主要用于测试清空缓存的效果
测试过程:
1.changeSphere方法中注释掉
clearCache(list[i])
这一行后,每次切换球体,都会导致显卡内存成倍增加,切换几次后,浏览器崩溃
2.使用了clearCache()清空缓存后,显卡内存不再增加
这里就不上图了,可以自行下来做测试
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../three.js-master/build/three.js"></script> <!--引入跟随鼠标移动事件的JS --> <script src="../three.js-master/examples/js/controls/OrbitControls.js"></script> <!--引入编辑框,屏幕右上角--> <script src="../three.js-master/examples/js/libs/dat.gui.min.js"></script> <style> body{ } </style> </head> <body> <input type="button" value="刷新当前页面球体" onclick="changeSphere()"> <script> //声明全局的场景, 相机,渲染器,灯光 var scene,camera,renderer,light; function init() { //创建场景 scene = new THREE.Scene(); //创建相机 camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,2000); camera.position.z = 335; camera.position.y =158; camera.position.x =114; camera.rotation.set(-0.24,0.01,0); //创建灯光 light = new THREE.PointLight(0xffffff,1); //将灯光添加到相机中 camera.add(light); //将相机添加进场景 scene.add(camera); //创建渲染器, 设定背景透明 renderer = new THREE.WebGLRenderer({alpha:true}); //设定渲染器大小 renderer.setSize(window.innerWidth*0.75,window.innerHeight*0.75); //将渲染器放到<body></body>中 document.body.appendChild(renderer.domElement); } //在场景中添加1000个球体 var list = []; function initMesh(){ for(let i =0;i<1000;i++){ let geometry = new THREE.SphereGeometry(5,16,16); let material = new THREE.MeshLambertMaterial({color:0xffffff*Math.random(),wireframe:true}); let mesh = new THREE.Mesh(geometry,material); mesh.position.x = Math.random()*2000-1000; mesh.position.y = Math.random()*2000-1000; mesh.position.z = Math.random()*2000-1000; list[i]= mesh; scene.add(list[i]); } } //对应按钮的事件,清空所有当前的球体,重新生成1000个新的球体 function changeSphere() { for(let i =0;i<list.length;i++){ let geometry = new THREE.SphereGeometry(5,16,16); let material = new THREE.MeshLambertMaterial({color:0xffffff*Math.random(),wireframe:true}); let mesh = new THREE.Mesh(geometry,material); mesh.position.x = Math.random()*2000-1000; mesh.position.y = Math.random()*2000-1000; mesh.position.z = Math.random()*2000-1000; // clearCache(list[i]); //取消该行注释后,每次切换新的球体时,显卡缓存会被清理 scene.remove(list[i]); list[i] = mesh; scene.add(list[i]); } } //orbit相机视角控制器 function initOrbit(){ var orbit = new THREE.OrbitControls(camera,renderer.domElement); renderer.render(scene,camera); } //执行动作之后,将移动结果展现出来 function animate(){ renderer.render(scene,camera); requestAnimationFrame(animate); } /** * 清空当前obj对象的缓存 * @param object object3D对象或mesh对象 * */ function clearCache(object) { let mesh = object; mesh.geometry.dispose(); mesh.material.dispose(); } /** * 清空渲染器缓存,该demo中无需使用 */ function clearRenderer(){ renderer.dispose(); renderer.forceContextLoss(); renderer.context = null; renderer.domElement = null; renderer = null; } //当窗口加载完成时,执行上述所有方法 window.onload = function start(){ init(); initMesh(); initOrbit(); animate(); } </script> </body> </html>
2.切换页面时,清空当前页面缓存
笔者在Vue+threejs的项目中,使用了组件切换,页面并没有刷新,但是每次都会重载一次场景,致使场景异常的卡顿,所以在每次切换组件后,调用了下列方法来清空上一个组件中的缓存,使得项目大幅度优化
在上述代码中,有一段方法并未在该示例中使用,这段代码就是用来清空渲染器缓存
function clearRenderer(){ renderer.dispose(); renderer.forceContextLoss(); renderer.context = null; renderer.domElement = null; renderer = null; }
该方法会将显存中,当前页面所有的显存清除,当你要清空当前画布,生成新的画布时调用,会清空上一个画布所占用的显卡缓存,从而优化整体项目