使用IndexedDB缓存给WebGL三维程序加速

哑火协议
• 阅读 3627

前言

使用webgl开发三维应用的时候,经常会发现三维场景加载比较慢,往往需要等待挺长时间,这样用户的体验就很不友好。 造成加载慢的原因,主要是三维应用涉及到的资源文件会特别多,这些资源文件主要是模型及其图片,往往这些模型和图片都会比较大。

为了加快三维场景的加快速度,可以使用IndexedDB在客户端进行资源缓存。IndexedDB,即客户端持久化数据库!使用本缓存技术,在初次访问后,3D场景中的文件级别数据将写入访问设备本地缓存数据库,在客户端实现永久的生命周期,清除浏览器缓存也不影响已缓存的3D模型文件。

IndexedDB介绍

IndexedDB 是一个前端数据持久化解决方案(即前端缓存),由浏览器实现。
IndexedDB又如下特点

  • 基于文件存储。意味着其容量可达到硬盘可用空间上限
  • 非关系型数据库。意味着扩展或收缩字段一般无须修改数据库和表结构(除非新增字段用做索引)
  • 键值对存储。意味着存取无须字符串转换过程
  • 存储类型丰富。意味着浏览器缓存中不再是只能存字符串了
  • 异步: 意味着所有操作都要在回调中进行

本地浏览器拥有三种永久存储数据技术,分别为Web Storage、IndexedDB、Web SQL。IndexedDB具备查询高效、存储空间大和异步操作等技术特征,有巨大的优势。

存储空间大。IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。在HTML5本地存储中,IndexedDB存储的数据则是最多的。

查询高效。IndexedDB是一种轻量级NOSQL数据库,是由浏览器自带。相比Web Sql更加高效,包括索引、事务处理和查询功能。

异步操作。 IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。

与此同时,IndexedDB 内部采用对象仓库存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象,满足了三维场景的存储需要。

因此 使用IndexedDB缓存是一种最为优异的前端缓存方案。像Babylon.js,其引擎层面已经支持了IndexedDB缓存。可以参考如下文档:
https://doc.babylonjs.com/div...

three.js使用IndexedDB的思路

有关具体如何使用IndexedDB,有很多资料进行介绍,此文不在赘述。

使用IndexedDB缓存模型资源,首先需要获取模型相关的资源,这些模型资源包括模型文件以及相关的图片文件。 比如对于GLTF模型而言,其资源包括.gltf的模型主文件,.bin格式的文件,纹理贴图文件等等。 首次加载加一个模型的时候,肯定是加载网络上的资源文件,通过threejs的LoadingMananger可以收集一个gltf模型的各种资源文件。 代码如下:

    const resourceCollector = [];
    const loadingManager = new LoadingManager();
    loadingManager.setURLModifier( (url,path) => {
      console.log(url);
      if(url.startsWith("data:") || url.startsWith("blob:")) {
        return url;
      }
      resourceCollector.push(url);
      return url;
    });

上述代码resourceCollector收集了加载模型过程中所有的模型资源的地址。 收集之后把所有资源存储到IndexedDB中:

saveGltfModel:async function(options,resourceCollector){
    const gltfUrl = options.gltfPath;
    const blobs = {};
    for(let i = 0;i < resourceCollector.length;i ++) {
      let url = resourceCollector[i];
      let blob = await loadAsBlob(url);
      blobs[url] = blob;
      await addToDatabase("model",{key:url,blob})
    }
    await addToDatabase("model_info",{key:gltfUrl,content:resourceCollector});
  },

其中loadAsBlob是把一个资源加载成为blob对象,代码如下:

  const xhr = new XMLHttpRequest();
  xhr.open("GET", url);
  xhr.responseType = "blob";
  xhr.onerror = function() {reject("Network error.")};
  xhr.onload = function() {
      if (xhr.status === 200) {resolve(xhr.response)}
      else {reject("Loading error:" + xhr.statusText)}
  };
  xhr.send();

而addToDatabase方法把资源添加到IndexedDB数据库。

function addToDatabase(storename, data) {
  const promise = new Promise( (resolve,reject) => {
    let store = database.transaction(storename, 'readwrite').objectStore(storename);
    let countReq = store.count(data.key);
    countReq.onsuccess = function(event) {
      console.log("count:",event.target.result);
      let count = event.target.result;
      if(count ==  0) {
        let request = store.add(data);
        request.onerror = function (event) {
          console.error('add添加数据库中已有该数据')
          reject(event);
        };
        request.onsuccess = function (event) {
          console.log('add添加数据已存入数据库')
          resolve(event);
        };
      }
    };
  });
}

下一次获取模型的时候,可以先判断是否以及本地存储,如果已经本地存储,就可以直接从本地获取模型资源:

 if(this.indexDbCache && indexedDB) {
      if(database == null) {
        database = await initialDB();
      }
      const storeObject = await findInDatabase("model_info",key);
      if(storeObject) {
        return this.loadGltfInDb(options);
      }
    }

缓存效果测评

通过测试可以发现对于比较大的场景,模型加载的速度可以提高几倍,十几倍甚至几十倍。 由此可见,IndexedDB缓存效果很明显。

如果对可视化感兴趣,可以和我交流,微信541002349。

关注公号“ITMan彪叔” 可以及时收到更多有价值的文章。

点赞
收藏
评论区
推荐文章
GoCoding GoCoding
4年前
可微渲染 SoftRas 实践
是目前主流三角网格可微渲染器之一。可微渲染通过计算渲染过程的导数,使得从单张图片学习三维结构逐渐成为现实。可微渲染目前被广泛地应用于三维重建,特别是人体重建、人脸重建和三维属性估计等应用中。安装conda安装PyTorch环境:bashcondacreatentorchpython3.8ycondaactivatetorchconda
阮小五 阮小五
2年前
Maya 2024中文特别版 适用于Apple M和 intel/win系统
AutodeskMaya是一款由Autodesk公司开发的三维计算机图形动画制作软件。它被广泛应用于电影、电视、游戏、动画等领域中,用于创建各种三维模型、场景、特效和动画。以下是Maya的主要特点:1.强大的建模工具:Maya提供了各种建模工具,如多边形建
陆石六 陆石六
2年前
Mac 上最好用的三维建模软件,Rhino 7 for Mac 完美兼容版
哪里下载Mac上最好用的三维建模软件,Rhino7forMac完美兼容版资源啊,Rhino7forMac是一款专业的三维建模软件,它广泛应用于建筑、造型、工程、讲解、分析和产品设计等领域。这个软件突出的特点是给用户提供了高度的自由度和灵活性,可以用于完成各
布袋罗汉 布袋罗汉
2年前
CINEMA 4D Studio R2023(c4d三维动画设计)
CINEMA4D是一款由德国MaxonComputer公司开发的三维建模、动画和渲染软件。它可以帮助用户创建各种复杂的三维图形和动画效果,如电影特效、电视广告、游戏界面等等。CINEMA4D具有强大的建模和动画工具,可以帮助用户轻松创建各种三维模型和动画效
Stella981 Stella981
3年前
ArcGIS API for JS4.7加载FeatureLayer,点击弹出信息并高亮显示
 我加载的是ArcGISServer本地发布的FeatureService,ArcGISAPIforJS4.7记载FeatureLayer时,在二维需要通过代码启用WebGL渲染,在三维模式下,则不需要。不启用WebGL,则无法显示进行高亮显示。我在二维模式下,高亮接口是没有生效,因此,二维模式下,自己写了一个高亮,三维还是用的自带的高亮。二维
Stella981 Stella981
3年前
Python使用VTK三维3D图形绘制入门教程
安装:pipinstallvtk学习一个东西最快的方法是知道基本原理和用途VTK有啥用不能做游戏。适合快速开发绘制静态三维模型。所以类似多用途折叠工具刀用处多,但是不能用在特别费劲的场合。!vtk不能用于制作游戏只适合快速的绘制静态三维模型(https://oscimg.oschina.net/oscn
Stella981 Stella981
3年前
Cocos Creator 资源加载流程剖析【三】——Load部分
Load流程是整个资源加载管线的最后一棒,由Loader这个pipe负责(loader.js)。通过Download流程拿到内容之后,需要对内容做一些“加载”处理。使得这些内容可以在游戏中使用。这里并不是所有的资源都需要进行一个加载处理,目前只有图片、Json、Plist、Uuid(Prefab、场景)等资源才会执行加载的流程,其他的资源在Downloa
Stella981 Stella981
3年前
Creator避免UI一次性加入场景
      通过层级管理器,做出来的UI,一次性放到场景里,加载无用的资源太多了,会导致加载速度慢,浪费内存,使用预制资源,一开始不使用的资源,使用预制资源,需要的时候加载进来,不需要的时候移除掉。      下图是实现的效果图,功能很简单,只为了实现原理。!(https://oscimg.oschina.net/oscnet/2d
沉浸式虚拟现实技术研发_华锐互动
众所周知,通过利用计算机来模拟一个三维空间的虚拟世界,提供用户关于视觉等感官的模拟,带给用户真实的沉浸式体验,用户可以没有限制地观察三维空间内的事物甚至是实现无障碍沟通。就目前来说,虚拟现实技术的发展前景是非常不错的,应用领域也是相当广阔的,如教育,汽车,图书馆,展览等多个领域,利用VR/3D技术构建一个三维立体的虚拟场景,还原真实世界。那么,虚拟现实技术未