做项目的过程中,遇到了很多的卡顿问题,最后经由暮志未晚 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;
}
该方法会将显存中,当前页面所有的显存清除,当你要清空当前画布,生成新的画布时调用,会清空上一个画布所占用的显卡缓存,从而优化整体项目