three.js是目前国内开发Web3D应用最多的第三方库,它提供了非常多的3D显示功能。在使用的时候,虽然three.js 本身做了优化,但是在较大分辨率下,加载较大或者较多模型时会出现,帧率会越低,给人感觉就越卡,因此性能方面的优化对提高视觉体验有着积极影响。以下是我在项目(vue+threejs)开发结合度娘总结的一些思路,希望能有所帮助。
因为默认情况下requestAnimationFrame()每秒执行60次,如果在里面加个for循环,代码效率就会严重影响,同时还要减少浮点计算,系统对浮点计算开支比较大,尽量写成小数乘法。
在一些特定的应用中没有必要保持Threejs渲染频率为60FPS,那么可以通过Threejs渲染时间判断来控制Threejs渲染频率,比如设置为30FPS。
下面代码通过时钟对象.Clock
的.getDelta()
方法获得threejs两帧渲染时间间隔,然后通过时间判断来控制渲染器渲染方法.render()
每秒执行次数:
// 创建一个时钟对象Clock
var clock = new THREE.Clock();
// 设置渲染频率为30FBS,也就是每秒调用渲染器render方法大约30次
var FPS = 30;
var renderT = 1 / FPS; //单位秒 间隔多长时间渲染渲染一次
// 声明一个变量表示render()函数被多次调用累积时间
// 如果执行一次der,timeS重新置0
var timeS = 0;
function render() {requestAnimationFrame(render);//.getDelta()方法获得两帧的时间间隔var T = Delta();timeS = timeS + T;// requestAnimationFrame默认调用render函数60次,通过时间判断,降低der执行频率if (timeS > renderT) {// 控制台查看渲染器渲染方法的调用周期,也就是间隔时间是多少console.log(`调用.render时间间隔`,timeS*1000+'毫秒');der(scene, camera); //执行渲染操作...//der每执行一次,timeS置0timeS = 0;}
}
render();
不同的网格模型如果可以共享几何体或材质,最好采用共享的方式,如果两个网格模型无法共享几何体或材质,自然不需要共享,比如两个网格模型的材质颜色不同,这种情况下,一般要分别为网格模型创建一个材质对象
相同或者相似类型的对象生成时多使用clone()方法,例如生成多个类似的立方体,推荐使用group,结合clone()方法,代码如下
const group = new THREE.Group()
const bar = new THREE.Mesh(barGeo, material)
bar.scale.set(0.3, 0.3, 0.3)
for (let i = 0; i < 80; i++) {const cBar = bar.clone()group.add(cBar)
}
// 引入stats.js
import Stats from 'three/examples/js/libs/stats.min.js'
const stats = new Stats()
// 设置stats样式
stats.dom.style.position = 'absolute';
stats.p = '0px';
document.body.appendChild(stats.dom);
在渲染函数中需要添加如下代码:
function Animate() {requestAnimationFrame(Animate);Render();
}
function Render() {// 更新statsstats.update();der(scene,camera);
}
使用THREE.Sprite时,可以更好地控制单个粒子,但是当使用大量的粒子的时候,这个方法的性能会降低,并且会更复杂。此时可以使用THREE.SpriteCloud,可以轻松地管理大量的粒子,进行整体操作,此时对单个粒子的控制能力会减弱。
three场景导入模型时,可以在保证最低清晰度的时候,降低模型的复杂度,面越多,模型越大,加载所需开销就越大
调查显示100ms内的响应能让用户感觉非常流畅。50ms是 Nicholas
针对 JavaScript
得出的最佳经验值,setTimeout 延时25ms,25ms 保证主流浏览器都顺畅,可以使用类似的方法来优化three.js程序。
初始化方法以及渲染方法可以适当添加延时以分散同时渲染的压力。
当存在多个模型动画时,根据实际情况可以将多个动画拆分,再可以对每个动画requestAnimationFrame分别设置渲染频率。
beforeDestroy () {clearTimeout()try {this.scene.clear()derer.dispose()derer.forceContextLoss()t = null// cancelAnimationFrame(animationID) // 去除animationFrameconst gl = Context('webgl')gl && gl.getExtension('WEBGL_lose_context').loseContext()} catch (e) {console.log(e)}
}
一个网格模型Mesh是包含几何体geometry和材质对象Material的,几何体geometry本质上就是顶点数据,Three.js通过WebGL渲染器解析几何体的时候会调用WebGL API创建顶点缓冲区来存储顶点数据。
如果仅仅执行.children
属性中删除,解析网格模型Mesh几何体的顶点数据通过WebGL API创建的顶点缓冲区占用的内存并不会释放。
从内存中删除对象或者删除几何体时不要忘记调用以下方法,因为可能导致内存泄漏
geometry.dispose() // 删除几何体
material.dispose() // 删除材质
当加载较大模型或者渲染比较复杂的模型时,页面会有较长时间卡顿,影响用户体验。可以添加loading效果,降低用户等待焦虑。
在性能和功耗方面,集成显卡具有一般性能的特点,但基本可以满足一些日常应用,与独立显卡相比,热功耗低。虽然独立显卡的性能很强,但其热量和功耗都比较高。独立显卡在三维性能上优于集成显卡。
chrome://flags/#enable-gpu-rasterization GPU rasterization 设置为Enabled
chrome://flags/#ignore-gpu-blocklist Override software rendering list 设置为Enabled
chrome://flags/#enable-zero-copy Zero-copy rasterizer 设置为Enabled
要想GPU加速文本的功能,不仅仅要下载最新的nightlyBuild火狐(Minefield)之外,还要通过以下方法操作才能开启该功能:
tips:用threejs做大分辨率下的显示应用时,需要考虑3D渲染的显卡性能以及显卡最大分辨率与显示屏分辨率的对比情况,如果在做了相关优化之后GPU的占用率仍然偏高,页面动效卡顿,三维效果不理想,甚至出现有时候因GPU超负荷而是电脑卡死的情况,这时候就需要考虑升级显卡配置了。
本文发布于:2024-01-31 00:51:10,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170663357524102.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |