背景

近期做一个关于石油化工的3D数字孪生项目,模型均为客户那边提供,模型文件是obj+mtl+jpg组合。因为有较多局部控制动画,所以建模被要求拆分成多个obj模型,然后在场景中自动组合使用。

现象

用THREEJS加载模型添加到场景中后发现两个问题:

1.渲染速度很慢;

2.如果浏览器同时开两个或窗口,那么会出现黑屏闪一下,然后页面就全白了,场景也都没了(如下图所示)。

调查

经过调查发现,打开一个窗口时,GPU内存被占用3.6G,打开两个的时候直接飙到5.2G,我这里GPU专用内存是6G,所以打开三个的时候直接就蹦了,所以就出现了黑屏的现象。

分析

我查看了客户提供的资源文件总大小,大概40M左右(obj+mtl+jpg),所以感觉应该不是导入文件过大问题。

无意间修改了一个mtlLoader的代码,错把objLoader.setMaterials(material)给注释掉了,导致场景中模型没显示任何贴图。

但却惊奇的发现,GPU内存只占用了0.2G。

所以我就大胆猜测,内存应该是都被导入的mtl占用了。经过不带mtl只导入obj的测试,验证了我的猜测是对的。

有了方向,基本就成功了一半,所以接下来开始对mtlLoader中onLoad进来的material对象进行分析。

ThreeJS的MTLLoader中onLoad返回的是一个MaterialCreator对象,其中包含了materials和materialsInfo两个属性,一个存放mesh对象使用的材质对象,一个存放对应的mtl文件内容(如下图)。

一个mtl文件解析成一个MaterialCreator,一个MaterialCreator的materials中又有多个材质对象,所以好几G内存的占用,会不会是因为材质对象中有重复的。因为我记得THREEJS中,相同的对象不要重复创建,尽量使用clone,这样能提高性能。材质对象,如果是多个,那么就会被渲染多次。如果是相同的,通过clone,那是不是就渲染一次了。

带着这个疑问,我去查看了一下mtl源文件。发现确实是好多相同的描述出现在不同的mtl文件中,比如newmtl Material__2,这种描述,好多mtl文件中都有,有些是完全一样的内容,有些虽然名一样,但是内容不一样。那么这些一样的,处在不同mtl文件中的,在被threejs解析添加到场景后,不就是按独立的材质被单独渲染么,明明是一样的内容,却按新的来渲染,这不就造成了资源浪费,消耗了很多内存么,渲染次数多了,渲染速度自然就慢了。

解决

修改了一下mtlLoader的代码,创建一个map(什么都可以,不一定是map),用materialsInfo转成MD5作为key,用对应的materials作为value,加载一个缓存一个,如果当前加载的材质对象在缓存中存在,则直接clone一个,否则作为新的存入缓存。

核心代码:

    // 相同材质采用克隆方式,不单独渲染,只需渲染45个材质对象,内存占用优化到1G,渲染速度3秒左右const mtlCache = new Map()shNameList.forEach(name => {mtlLoader.load('model/sh/整体罐区/' + name + '.mtl', (material) => {material.preload()Object.keys(material.materialsInfo).forEach(k => {const key = md5(JSON.stringify(material.materialsInfo[k]), 32)if (mtlCache.has(key)) {material.materials[k].copy(mtlCache.get(key))} else {mtlCache.set(key, material.materials[k])}})const objLoader = new OBJLoader()objLoader.setMaterials(material)objLoader.load('model/sh/整体罐区/' + name + '.obj', (object) => {ts.scene.add(object)})})})console.log(mtlCache)// 单独渲染材质对象,需渲染261个材质对象,占用3.6G内存,渲染花费9秒左右// const mtlList = []// shNameList.forEach(name => {//   mtlLoader.load('model/sh/整体罐区/' + name + '.mtl', (material) => {//     console.log(material)//     const objLoader = new OBJLoader()//     material.preload()//     Object.keys(material.materials).forEach(k => {//       mtlList.push(material.materials[k])//     })//     objLoader.setMaterials(material)//     objLoader.load('model/sh/整体罐区/' + name + '.obj', (object) => {//       ts.scene.add(object)//     })//   })// })// console.log(mtlList)

对比

优化前:

优化后:

THREEJS导入外部OBJ+MTL后内存优化相关推荐

  1. ThreeJS导入外部obj和mtl

    本文将介绍 如何使用ThreeJS导入obj和带贴图mtl的外部obj模型: 使用AmbientLight为场景所有物体添加基础光源: 使用SpotLight为场景添加聚光灯效果,并为obj添加阴影效 ...

  2. 使用threejs导入外部模型与滑动查看【微信小程序】-裁-

    目录 可行方法 1.下载示例项目: 2.CV 改代码 弃稿[不要用] 可行方法 好不容易找到的参考文章: https://segmentfault.com/a/1190000041147784 1.下 ...

  3. 【Android 内存优化】内存抖动 ( 垃圾回收算法总结 | 分代收集算法补充 | 内存抖动排查 | 内存抖动操作 | 集合选择 )

    文章目录 一. 垃圾回收算法总结 二. 分代收集算法补充 三. 查看 Java 虚拟机 四. 获取 Android 应用可使用最大内存 五. 内存抖动标志 六. 排查内存抖动 七. 常见的造成内存抖动 ...

  4. threejs+vue房子模型,实现BSP模型剪切,导入obj+mtl文件

    threejs版本选择 "dependencies": {"@types/three": "^0.126.1", "three&q ...

  5. threeJs导入3D皮卡丘.obj模型,使用.jpg贴图,实现缩放旋转查看功能

    先来看下最终的效果. 导入obj模型 如果仅使用Mesh几何而不加载任何外部资源,则网页应直接在文件系统中运行,只需双击HTML文件打开即可以预览.而由于3D模型是从外部加载进来的,由于浏览器的原始策 ...

  6. Threejs渲染obj+mtl模型源码,3D工厂模型

    1,介绍 Threejs实现引入工厂模型,加载obj+mtl模型源码下载,可用于学习研究,二次开发 2,部分代码 // 创建一个场景,它将包含我们所有的元素,如物体,相机和灯光. var scene ...

  7. Java 3D导入obj模型后颜色显示 出错显示白色,或者笔记本电脑显示彩色,但是台式机仍为白色

    Java 3D导入obj模型后颜色显示 出错显示白色,或者笔记本电脑显示彩色,但是台式机仍为白色 代码问题 首先,确保代码中编辑了给模型导入颜色 //function:读取.obj文件,并将其添加到S ...

  8. springBoot打war包后,启动时导入外部配置文件

    之前一直都是将配置文件等全部打成一个包使用,后来因为维护啥的都比较困难,所以将配置文件移出来,从外界去依赖: 首先就是在项目的 configuration文件夹中添加一个类: LocalSetting ...

  9. Android性能优化 - 内存优化

    性能优化系列阅读 Android性能优化 性能优化 - 消除卡顿 性能优化- 内存优化 性能分析工具 - TraceView Android性能分析工具 为什么内存优化? 在一个商业项目中,很有可能因 ...

最新文章

  1. Unity3d 简单的小球沿贝塞尔曲线运动(适合场景漫游使用)
  2. AndroidStudio报错:Emulator: I/O warning : failed to load external entity file:/C:/Users/Administrator
  3. 信息安全之仿射密码加密和解密
  4. MySQL count(1) count(*) 比较 详解
  5. sco linux crontab重启,crontab 详解
  6. HightCharts与后台交互
  7. LeetCode 724. Find Pivot Index
  8. 【数据结构笔记46】Sort with Swap(0,*)只允许交换0的排序
  9. 如何准备Java初级和高级的技术面试
  10. python设置路径变量_python – Bokeh中设置的静态路径变量在哪里(对于create_html_snippet)...
  11. 2019西安交大计算机专业研究生分数线,2019西安交通大学研究生分数线汇总(含2016-2019历年复试)...
  12. 利用Cytoscape进行生物相互作用网络可视化及拓扑分析
  13. iapp禁止抓包软件代码
  14. c语言中的inv是什么缩写,INV(inv是什么的缩写)
  15. python的print函数用逗号分隔时输出不用空格_python print 按逗号或空格分隔的方法...
  16. 相位展开(phase unwrapping)
  17. MediaInfo与wmv3 wma3 的解码器
  18. Web站相关知识与Web程序的访问流程
  19. 计算机弹不出音乐怎么办,win7电脑没声音弄不出来怎么办
  20. 《软技能——代码之外的生存指南》笔记

热门文章

  1. ASP.NET Core开发-后台任务利器Hangfire使用
  2. 【C++】严重性代码说明项目文件行错误
  3. 高斯过程 (Gaussian Process)
  4. 【数学】扩展卢卡斯定理
  5. 离散数学-集合-笛卡尔积-07
  6. 透彻分析JAVA内存泄漏和内存溢出的区别
  7. android跳转到微信小程序
  8. group by 取每组最新的一条
  9. redis的可视化RDM操作批量删除key
  10. 禁止百度,神马,搜狗等搜索引擎转码