当前位置: 首页 > Web前端 > HTML

使用IndexedDB缓存加速WebGL3D程序

时间:2023-03-28 17:32:04 HTML

前言在使用webgl开发3D应用的时候,经常会发现加载3D场景很慢,经常需要很长时间,这让用户体验很不友好。加载慢的主要原因是3D应用涉及到大量的资源文件。这些资源文件主要是模型和图片,而这些模型和图片往往比较大。为了加快3D场景的加速,可以在客户端使用IndexedDB缓存资源。IndexedDB,客户端持久化数据库!利用这种缓存技术,在初次访问后,3D场景中的文件级数据会被写入访问设备的本地缓存数据库,实现客户端永久生命周期,清除浏览器缓存不会影响缓存的3D模型文件。IndexedDB简介IndexedDB是由浏览器实现的前端数据持久化方案(即前端缓存)。IndexedDB基于文件存储有以下特点。这意味着它的容量可以达到可用硬盘空间的上限。非关系数据库。意思是扩容或缩容字段一般不需要修改数据库和表结构(除非新增字段作为索引)键值对存储。这意味着存储的类型丰富,没有字符串转换过程。这意味着只能将字符串存储在浏览器缓存中。异步:就是所有的操作都必须在回调中进行。本地浏览器拥有三种永久数据存储技术,分别是WebStorage、IndexedDB和WebSQL。IndexedDB具有查询高效、存储空间大、异步操作等技术特点,具有巨大的优势。大存储空间。IndexedDB的存储空间远大于LocalStorage,一般不低于250MB,甚至没有上限。在HTML5本地存储中,IndexedDB存储的数据最多。查询是有效的。IndexedDB是浏览器自带的轻量级NOSQL数据库。它比WebSql更高效,包括索引、事务处理和查询功能。异步操作。IndexedDB在运行过程中不会锁定浏览器,用户仍然可以进行其他操作,这与LocalStorage的操作是同步的相反。异步设计是为了防止大量数据的读写,拖慢网页的性能。同时,IndexedDB内部使用了一个对象仓库来存储数据。可以直接存储所有类型的数据,包括JavaScript对象,满足3D场景的存储需求。因此,使用IndexedDB缓存是最优秀的前端缓存方案。和Babylon.js一样,它的引擎级别已经支持IndexedDB缓存。可以参考以下文档:https://doc.babylonjs.com/div...。three.js使用IndexedDB的思路关于如何使用IndexedDB的资料很多,本文不再赘述。使用IndexedDB缓存模型资源,首先需要获取模型相关的资源,包括模型文件和相关图片文件。例如,对于一个GLTF模型,它的资源包括.gltf的主模型文件、.bin格式的文件、纹理贴图文件等。第一次加载和添加模型时,需要加载网络上的资源文件。通过threejs的LoadingMananger可以收集一个gltf模型的各种资源文件。代码如下:constresourceCollector=[];constloadingManager=newLoadingManager();loadingManager.setURLModifier((url,path)=>{console.log(url);if(url.startsWith("data:")||url.startsWith("blob:")){returnurl;}resourceCollector.push(url);返回url;});上面代码resourceCollector在加载模型的过程中收集所有模型资源的地址。收集后将所有资源存储在IndexedDB中:saveGltfModel:asyncfunction(options,resourceCollector){constgltfUrl=options.gltfPath;constblob={};for(leti=0;i{letstore=database.transaction(storename,'readwrite').objectStore(storename);让countReq=store.count(data.key);countReq.onsuccess=function(event){console.log("count:",event.target.result);letcount=event.target.result;if(count==0){letrequest=store.add(data);request.onerror=function(event){console.error('添加数据库中已经存在的数据')reject(event);};request.onsuccess=function(event){console.log('add添加的数据已经存储在数据库中')resolve(event);};}};});}下次获取模型的时候可以先判断是否存储在本地。如果已经存储在本地,可以直接从本地Resource获取模型:if(this.indexDbCache&&indexedDB){if(database==null){database=awaitinitialDB();}conststoreObject=awaitfindInDatabase("model_info",key);如果(storeObject){返回这个.loadGltfInDb(选项);}}缓存效果评测通过测试可以发现,对于比较大的场景,模型加载速度可以提升几倍、十倍甚至几十倍。可见IndexedDB缓存效果明显。对可视化感兴趣的可以和我交流,微信541002349。关注公众号“ITMan表叔”,及时收到更多有价值的文章。